/* * Führt den 2-Opt Algorithmus aus, um eine lokal optimale Bahnplanung zu erreichen */ public Druckfolge _2Opt(Druckfolge initialLösung, Graph_ graph, bool isInfill) { Druckfolge _2optLösung = new Druckfolge(initialLösung); Druckfolge neueLösung = _2optLösung.DeepCopy(); /* * Die Inkremente für i,j bestimmten fast vollständig die Laufzeit des gesamten Programms und sind deshalb * je nach Fall anzupassen. * Kleine Inkremente: Liefern eine Bahnplanung mit geringeren Kosten, aber die Laufzeit des Programms steigt exponentiell * Große Inkremente: Liefern eine Bahnplanung mit höheren Kosten, aber die Laufzeit bleibt sehr gering */ for (int i = 0; i < graph.GetVoxelKoordinaten().Count; i += graph.GetVoxelKoordinaten().Count / 20) { for (int j = 1; j < graph.GetVoxelKoordinaten().Count; j += graph.GetVoxelKoordinaten().Count / 40) { neueLösung = _2optLösung.DeepCopy(); _2OptSwap(neueLösung, graph.GetVoxelKoordinaten(), isInfill, i, j); if (!(neueLösung.GetGesamtkosten() > _2optLösung.GetGesamtkosten())) { _2optLösung = neueLösung.DeepCopy(); } } } return(_2optLösung); }
/* * Umwandlung einer Voxelschicht zu einem Graphen. Anhand von Nachbarschaften werden kosten für die Kanten festgelegt, und absetzpunkte werden definiert. * Ein Absetzpunkt ensteht immer wenn ein Voxel nicht direkt zu einem der 26 umliegenden (oder sich selbst) benachbart ist. */ private Graph_ VoxelToGraph(List <Voxel> voxel) { Graph_ graph = new Graph_(); foreach (var v in voxel) { List <double> graphElemente = new List <double>(); foreach (var w in voxel) { int[] distanz = new int[3] { 0, 0, 0 }; distanz = v.VoxelKoordinatenDistanz(w); /* * Berechne für alle Benachbarten und nicht benachbarten Knoten jeden Knotens, die Distanz * zu den anderen Knoten. Füge die VoxelKoordinaten hinzu. Nachbarschaftsfunktion je nach Druckwunsch auswählen */ if (v.IsNeighbor6(w)) { graphElemente.Add(EudklidDistanzAusVoxelDistanz(distanz)); } else { graphElemente.Add(ABSETZKOSTEN + EudklidDistanzAusVoxelDistanz(distanz)); } } graph.AddGraphElement(graphElemente); graph.AddVoxelKoordinaten(v.getKoords()); } MarkiereEigenknoten(graph); return(graph); }
/* * Generieren einer ersten Bahnplanungslösung mit dem Nearest-Neighbor Verfahren * 1. Es wird ein Ausgangsknoten festgelegt * 2. Von diesem Knoten aus wird die Kante mit den geringsten Kosten gesucht * 3. Der Knoten der an dieser Kante hängt wird als nächstes in die Prioritätsliste einsortiert * 4. Die Kosten werden Summiert * 5. Wiederhole 2. bis keine Knoten mehr vorhanden sind */ private Druckfolge NearestNeighbor(Graph_ graph, int startNode) { Druckfolge initialLösung = new Druckfolge(); // 1. Startpunkt = Erster Knoten int aktuellerKnoten = startNode; int minimumKnotenNummer = startNode; MarkiereKnoten(aktuellerKnoten, graph); initialLösung.AddPriority((uint)startNode); for (int i = 0; i < graph.GetGraph().Count - 1; i++) { double minimum = MARKIERKOSTEN * 10; for (int j = 0; j < graph.GetGraph().Count; j++) { if (graph.GetGraphElement(aktuellerKnoten, j) < minimum) { minimum = graph.GetGraphElement(aktuellerKnoten, j); minimumKnotenNummer = j; } } // Füge den Knoten mit günstigster Kante in die Druckreihenfolge ein initialLösung.AddPriority((uint)minimumKnotenNummer); initialLösung.SummiereGesamtkosten((uint)minimum); // Aktualisiere den Knoten von dem aus die günstigste Kante gesucht wird aktuellerKnoten = minimumKnotenNummer; MarkiereKnoten(aktuellerKnoten, graph); } return(initialLösung); }
public Bahn Bahnplanung(List <Voxel> voxelList, int layerIndex) { /* * Teilen der gesamten Voxelliste in Randvoxel und Rest, damit unterschiedliche Bahnen geplant werden können * splitList[0] enthält Schichtränder * splitList[1] enthält alle anderen Voxel */ List <List <Voxel> > splitList = new List <List <Voxel> >(SplitVoxelList(voxelList)); /* * Erstelle zwei Graphen : Randvoxel-Graph und Restvoxel-Graph * False und True zeigen hier jeweils nur an ob es sich bei den Verarbeitungsschritten um * Infillvoxel handelt oder nicht, wegen der Nachbarschaftskontrolle */ Graph_ randGraph = new Graph_(VoxelToGraph(splitList[0], false)); Graph_ restGraph = new Graph_(VoxelToGraph(splitList[1], true)); // Erstellen der Druckfolgen Druckfolge initialRand = new Druckfolge(); Druckfolge initialRest = new Druckfolge(); Druckfolge _2optRand = new Druckfolge(); Druckfolge _2optRest = new Druckfolge(); Druckfolge optimizedRand = new Druckfolge(0.0); Druckfolge optimizedRest = new Druckfolge(0.0); /* * Da nur lokale Optima bestimmt werden, werden mehrere Durchläufe erzeugt, von denen das Beste ausgewählt wird. */ for (int NNRUNS = 0; NNRUNS < ANZAHL_NNRUNS; NNRUNS++) { Random randomizer = new Random(); int startNodeRand = (randomizer.Next(0, randGraph.GetGraph().Count - 1)); int startNodeRest = (randomizer.Next(0, restGraph.GetGraph().Count - 1)); // Generieren einer NN-Tour mit random Startknoten initialRand = NearestNeighbor(randGraph.DeepCopy(), startNodeRand); initialRest = NearestNeighbor(restGraph.DeepCopy(), startNodeRest); // Verbesserung der initialen Lösung durch 2-opt _2optRand = _2Opt(initialRand, randGraph.DeepCopy(), false); _2optRest = _2Opt(initialRest, restGraph.DeepCopy(), true); //Behalten des besten lokalen Optimums if (_2optRand.GetGesamtkosten() < optimizedRand.GetGesamtkosten()) { optimizedRand = _2optRand.DeepCopy(); } if (_2optRest.GetGesamtkosten() < optimizedRest.GetGesamtkosten()) { optimizedRest = _2optRest.DeepCopy(); } } Bahn bahn = new Bahn(splitList, randGraph, restGraph, optimizedRand, optimizedRest, layerIndex); return(bahn); }
/* * Markiert die Kante eines Knotens zu sich selbst damit diese nicht als Weg eingetragen wird, * unter Berücksichtigung der Matrixeigenschaft der Liste von Listen. */ private Graph_ MarkiereEigenknoten(Graph_ graph) { for (int i = 0; i < graph.GetGraph().Count; i++) { graph.SetGraph(graph.GetGraphElement(i, i) + MARKIERKOSTEN, i, i); } return(graph); }
//DeepCopy eines Graphen public Graph_ DeepCopy() { Graph_ deepCopy = new Graph_(); deepCopy.m_graph = new List <List <double> >(GetGraph()); deepCopy.m_VoxelKoordinaten = new List <ushort[]>(m_VoxelKoordinaten); return(deepCopy); }
//Setter public void SetBahn(Bahn bahn) { m_splitList = bahn.m_splitList; m_randGraph = bahn.m_randGraph; m_restGraph = bahn.m_restGraph; m_optimizedRand = bahn.m_optimizedRand; m_optimizedRest = bahn.m_optimizedRest; m_layerIndex = bahn.m_layerIndex; }
//Markiert einen Knoten, für alle anderen Knoten in den Kostenlisten private static Graph_ MarkiereKnoten(int knoten, Graph_ graph) { for (int i = 0; i < graph.GetGraph().Count; i++) { graph.SetGraph(graph.GetGraphElement(i, knoten) + MARKIERKOSTEN, i, knoten); } graph.SetGraph(graph.GetGraphElement(knoten, knoten) - MARKIERKOSTEN, knoten, knoten); return(graph); }
public Bahn(List <List <Voxel> > splitList, Graph_ randGraph, Graph_ restGraph, Druckfolge optimizedRand, Druckfolge optimizedRest, int layerIndex) { m_splitList = splitList; m_randGraph = randGraph; m_restGraph = restGraph; m_optimizedRand = optimizedRand; m_optimizedRest = optimizedRest; m_layerIndex = layerIndex; }
public Druckfolge _2Opt(Druckfolge initialLösung, Graph_ graph) { Druckfolge _2optLösung = new Druckfolge(initialLösung); Druckfolge neueLösung = _2optLösung.DeepCopy(); for (int improve = 0; improve < 5; improve++) { for (int i = 0; i < graph.GetVoxelKoordinaten().Count; i++) { for (int j = i + 1; j < graph.GetVoxelKoordinaten().Count; j++) { neueLösung = _2optLösung.DeepCopy(); _2OptSwap(neueLösung, graph.GetVoxelKoordinaten(), i, j); if (!(neueLösung.GetGesamtkosten() > _2optLösung.GetGesamtkosten())) { _2optLösung = neueLösung.DeepCopy(); } } } } return(_2optLösung); }
public void Bahnplanung(List <Voxel> voxelList) { /* * Teilen der gesamten Voxelliste in Randvoxel und Rest, damit unterschiedliche Bahnen geplant werden können * splitList[0] enthält Schichtränder * splitList[1] enthält alle anderen Voxel */ List <List <Voxel> > splitList = new List <List <Voxel> >(SplitVoxelList(voxelList)); // Erstelle zwei Graphen : Randvoxel-Graph und Restvoxel-Graph Graph_ randGraph = new Graph_(VoxelToGraph(splitList[0])); Graph_ restGraph = new Graph_(VoxelToGraph(splitList[1])); // Erstellen der Druckfolgen Druckfolge initialRand = new Druckfolge(); Druckfolge initialRest = new Druckfolge(); Druckfolge _2optRand = new Druckfolge(); Druckfolge _2optRest = new Druckfolge(); Druckfolge optimizedRand = new Druckfolge(); Druckfolge optimizedRest = new Druckfolge(); for (int NNRUNS = 0; NNRUNS < 10; NNRUNS++) { Random randomizer = new Random(); int startNode = (randomizer.Next(0, restGraph.GetGraph().Count)); // Generieren einer NN-Tour mit random Startknoten initialRand = NearestNeighbor(randGraph.DeepCopy(), startNode); initialRest = NearestNeighbor(restGraph.DeepCopy(), startNode); // Verbesserung der initialen Lösung durch 2-opt _2optRand = _2Opt(initialRand, randGraph.DeepCopy()); _2optRest = _2Opt(initialRest, restGraph.DeepCopy()); //Behalten des besten lokalen Optimums if (_2optRand.GetGesamtkosten() < optimizedRand.GetGesamtkosten()) { optimizedRand = _2optRand.DeepCopy(); } if (_2optRest.GetGesamtkosten() < optimizedRest.GetGesamtkosten()) { optimizedRest = _2optRest.DeepCopy(); } } // Textoutput für Koordinate(X,Y,Z), Priority string path = "F:\\Uni\\Uni WS 17_18\\Studienprojekt\\ProgrammierKram\\GraphUmwandlung"; using (StreamWriter outputFile = new StreamWriter(path + @"\Data.txt")) { uint index = 0; for (int i = 0; i < restGraph.GetVoxelKoordinaten().Count; i++) { index = optimizedRest.GetPriorityItem(i); outputFile.Write(restGraph.GetVoxelKoordinate(0, (int)index) + " " + restGraph.GetVoxelKoordinate(1, (int)index) + " " + restGraph.GetVoxelKoordinate(2, (int)index) + "\r\n"); } } using (StreamWriter outputFile = new StreamWriter(path + @"\DataINIT.txt")) { uint index = 0; for (int i = 0; i < restGraph.GetVoxelKoordinaten().Count; i++) { index = initialRest.GetPriorityItem(i); outputFile.Write(restGraph.GetVoxelKoordinate(0, (int)index) + " " + restGraph.GetVoxelKoordinate(1, (int)index) + " " + restGraph.GetVoxelKoordinate(2, (int)index) + "\r\n"); } } }
public Graph_(Graph_ graph) { m_graph = graph.m_graph; m_VoxelKoordinaten = graph.m_VoxelKoordinaten; }
public void Bahnplanung(List <Voxel> voxelList, double robotGeschwindigkeit, double extrusionsGeschwindigkeit, string path, string fileName, int layerIndex) { /* * Teilen der gesamten Voxelliste in Randvoxel und Rest, damit unterschiedliche Bahnen geplant werden können * splitList[0] enthält Schichtränder * splitList[1] enthält alle anderen Voxel */ List <List <Voxel> > splitList = new List <List <Voxel> >(SplitVoxelList(voxelList)); /* * Erstelle zwei Graphen : Randvoxel-Graph und Restvoxel-Graph * False und True zeigen hier jeweils nur an ob es sich bei den Verarbeitungsschritten um * Infillvoxel handelt oder nicht, wegen der Nachbarschaftskontrolle */ Graph_ randGraph = new Graph_(VoxelToGraph(splitList[0], false)); Graph_ restGraph = new Graph_(VoxelToGraph(splitList[1], true)); // Erstellen der Druckfolgen Druckfolge initialRand = new Druckfolge(); Druckfolge initialRest = new Druckfolge(); Druckfolge _2optRand = new Druckfolge(); Druckfolge _2optRest = new Druckfolge(); Druckfolge optimizedRand = new Druckfolge(); Druckfolge optimizedRest = new Druckfolge(); for (int NNRUNS = 0; NNRUNS < 5; NNRUNS++) { Random randomizer = new Random(); int startNodeRand = (randomizer.Next(0, randGraph.GetGraph().Count - 1)); int startNodeRest = (randomizer.Next(0, restGraph.GetGraph().Count - 1)); // Generieren einer NN-Tour mit random Startknoten initialRand = NearestNeighbor(randGraph.DeepCopy(), startNodeRand); initialRest = NearestNeighbor(restGraph.DeepCopy(), startNodeRest); // Verbesserung der initialen Lösung durch 2-opt _2optRand = _2Opt(initialRand, randGraph.DeepCopy(), false); _2optRest = _2Opt(initialRest, restGraph.DeepCopy(), true); //Behalten des besten lokalen Optimums if (_2optRand.GetGesamtkosten() < optimizedRand.GetGesamtkosten()) { optimizedRand = _2optRand.DeepCopy(); } if (_2optRest.GetGesamtkosten() < optimizedRest.GetGesamtkosten()) { optimizedRest = _2optRest.DeepCopy(); } } /* * Textoutput für Koordinate(X,Y,Z), Orientierung(Winkel1,Winkel2,Winkel3), Robotergeschwindigkeit, * Extrusionsgeschwindigkeit vom Vorgänger zu diesem Punkt, Nummer der Schicht */ List <bool> absetzPunkte = new List <bool>(); List <double> absetzDouble = new List <double>(); absetzPunkte.Add(false); int index = 0; int index2 = 0; using (StreamWriter outputFile = File.AppendText(path + fileName)) { Voxel v = new Voxel(randGraph.GetVoxelKoordinatenAtIndex(0)); Voxel v2; for (int i = 0; i < splitList[0].Count; i++) { if (absetzPunkte[i]) { //Hier Extrusionsgeschwindigkeit eintragen absetzDouble.Add(extrusionsGeschwindigkeit); } else { absetzDouble.Add(0); } index = (int)optimizedRand.GetPriorityItem(i); v = new Voxel(randGraph.GetVoxelKoordinatenAtIndex(index)); if ((i + 1) < splitList[0].Count) { index2 = (int)optimizedRand.GetPriorityItem(i + 1); } if ((index2) < splitList[0].Count) { v2 = new Voxel(randGraph.GetVoxelKoordinatenAtIndex(index2)); absetzPunkte.Add(v.IsNeighbor6(v2)); } outputFile.Write(randGraph.GetVoxelKoordinate(0, index) + " " + randGraph.GetVoxelKoordinate(1, index) + " " + randGraph.GetVoxelKoordinate(2, index) + " " + splitList[0][index].getOrientierungAt(0) + " " + splitList[0][index].getOrientierungAt(1) + " " + splitList[0][index].getOrientierungAt(2) + " " + robotGeschwindigkeit + " " + absetzDouble[i] + " " + layerIndex + " " + "\r\n"); } //outputFile.Write("\r\n"); absetzPunkte.Clear(); absetzDouble.Clear(); index = (int)optimizedRest.GetPriorityItem(0); v2 = new Voxel(restGraph.GetVoxelKoordinatenAtIndex(index)); absetzPunkte.Add(v.IsNeighbor6(v2)); for (int i = 0; i < splitList[1].Count; i++) { if (absetzPunkte[i]) { //Hier Extrusionsgeschwindigkeit eintragen absetzDouble.Add(extrusionsGeschwindigkeit); } else { absetzDouble.Add(0); } index = (int)optimizedRest.GetPriorityItem(i); v = new Voxel(restGraph.GetVoxelKoordinatenAtIndex(index)); if ((i + 1) < splitList[1].Count) { index2 = (int)optimizedRest.GetPriorityItem(i + 1); } if ((index2) < splitList[1].Count) { v2 = new Voxel(restGraph.GetVoxelKoordinatenAtIndex(index2)); absetzPunkte.Add(v.IsNeighbor26(v2)); } outputFile.Write(restGraph.GetVoxelKoordinate(0, index) + " " + restGraph.GetVoxelKoordinate(1, index) + " " + restGraph.GetVoxelKoordinate(2, index) + " " + splitList[1][index].getOrientierungAt(0) + " " + splitList[1][index].getOrientierungAt(1) + " " + splitList[1][index].getOrientierungAt(2) + " " + robotGeschwindigkeit + " " + absetzDouble[i] + " " + layerIndex + " " + "\r\n"); } } }