From 5bab9b599233cebe27ea4d7b37575a504be8aa39 Mon Sep 17 00:00:00 2001 From: i23007 Date: Mon, 8 Jul 2024 17:12:08 +0200 Subject: [PATCH 1/3] Improved Algortihms and A Star Heuristik --- graph/DirectedGraph.java | 58 ++++++++--------- graph/Graph.java | 2 +- graph/NameDoesNotExistException.java | 8 +-- graph/UndirectedGraph.java | 59 +++++++++--------- .../ProjektGraph/graph/DirectedGraph.class | Bin 12586 -> 12979 bytes out/production/ProjektGraph/graph/Graph.class | Bin 7868 -> 7970 bytes .../ProjektGraph/graph/UndirectedGraph.class | Bin 11121 -> 11514 bytes .../graph/WrapperComparator.class | Bin 1114 -> 1113 bytes .../ProjektGraph/graph/WrapperElement.class | Bin 1590 -> 1590 bytes 9 files changed, 65 insertions(+), 62 deletions(-) diff --git a/graph/DirectedGraph.java b/graph/DirectedGraph.java index 6c3ced1..e2fb4f9 100644 --- a/graph/DirectedGraph.java +++ b/graph/DirectedGraph.java @@ -247,16 +247,16 @@ public class DirectedGraph exten // Den nächsten Knoten, der am wenigsten kostet, besuchen WrapperElement nextVertex = queue.poll(); - // Knoten als besucht makieren - visited.put(nextVertex.getElement(), true); - - - // Logging - textDescription = "Visit " + nextVertex.getElement().getName(); - System.out.println(textDescription); - nextVertex.getElement().getScreenVertex().setColor(Color.BLUE); - this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); - + // Falls Knoten schon besucht + if(!visited.get(nextVertex.getElement())){ + // Knoten als besucht makieren + visited.put(nextVertex.getElement(), true); + textDescription = "Visit " + nextVertex.getElement().getName(); + // Logging + System.out.println(textDescription); + nextVertex.getElement().getScreenVertex().setColor(Color.BLUE); + this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); + } // Wenn Weg gefunden, brich ab if (nextVertex.getElement() == n2) { @@ -333,7 +333,7 @@ public class DirectedGraph exten - public int getShortestPathAStar(MarkedVertex n1, MarkedVertex n2) { + public double getShortestPathAStar(MarkedVertex n1, MarkedVertex n2) { // Erstellt Hashmap um Distanz von Startnoten zu jedem Knoten auf dem Graph zu tracken // Erstellt Hashmap um zu tracken welche Knoten schon besucht wurden @@ -341,11 +341,11 @@ public class DirectedGraph exten // Initialisierung aller Distanzen auf UNENDLICH (= -1) // Initialisierung, dass kein Knoten besucht wurde // Initialisierung aller Vorgänger auf null - HashMap, Integer> distance = new HashMap<>(); + HashMap, Double> distance = new HashMap<>(); HashMap, Boolean> visited = new HashMap<>(); HashMap, MarkedVertex> predecessors = new HashMap<>(); for (MarkedVertex i: this.getAllVertexes()) { - distance.put(i, -1); + distance.put(i, -1.0); visited.put(i, false); predecessors.put(i, null); } @@ -355,15 +355,15 @@ public class DirectedGraph exten // Distanz zu Startknoten auf 0 // Weg zu Startknoten in die Schlange aufnehmen - distance.put(n1, 0); + distance.put(n1, 0.0); queue.add(new WrapperElement<>(n1, 0)); // Variable, die Distanz zwischen aktuellem Knoten und Nachfolger speichert - int dist = 0; + double dist = 0; // Variable, die Distanz zwischen dem potenziell nächsten Knoten und dem Zielknoten speichert - int airDist = 0; + double airDist = 0; // Variable, die Distanz zwischen dem aktuellen Knoten bis zum Endknoten speichert - int distToFinish = 0; + double distToFinish = 0; // Zähler für LogList int step = 0; // String für den Description Inhalt @@ -380,15 +380,17 @@ public class DirectedGraph exten // Den nächsten Knoten, der am wenigsten kostet, besuchen WrapperElement nextVertex = queue.poll(); - // Knoten als besucht makieren - visited.put(nextVertex.getElement(), true); - - // Logging - textDescription = "Visit " + nextVertex.getElement().getName(); - System.out.println(textDescription); - nextVertex.getElement().getScreenVertex().setColor(Color.BLUE); - this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); + // Falls Knoten schon besucht + if(!visited.get(nextVertex.getElement())){ + // Knoten als besucht makieren + visited.put(nextVertex.getElement(), true); + textDescription = "Visit " + nextVertex.getElement().getName(); + // Logging + System.out.println(textDescription); + nextVertex.getElement().getScreenVertex().setColor(Color.BLUE); + this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); + } // Wenn Weg gefunden, brich ab if (nextVertex.getElement() == n2) { @@ -417,8 +419,8 @@ public class DirectedGraph exten if (j.getSource() == nextVertex.getElement() && j.getDestination() == i) { //Berechnung der Heuristik über die Luftdistanz des nächsten Knoten zum Zielknoten - airDist = (int) Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2) - + Math.pow((i.getCords()[1] - n2.getCords()[1]), 2)); + airDist = Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2) + + Math.pow((i.getCords()[1] - n2.getCords()[1]), 2)) / 100; // Berechne Distanz zu nächstem Knoten EdgeWeightMarking marking = (EdgeWeightMarking) j.getMarking(); @@ -440,7 +442,7 @@ public class DirectedGraph exten distance.put(i, dist); // Logging - textDescription = "Add " + i.getName() + " with " + dist + " weight to queue."; + textDescription = "Add " + i.getName() + " with " + distToFinish + " weight to queue."; System.out.println(textDescription); i.getScreenVertex().setColor(Color.YELLOW); this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); diff --git a/graph/Graph.java b/graph/Graph.java index ef74af1..b1a0b7e 100644 --- a/graph/Graph.java +++ b/graph/Graph.java @@ -276,5 +276,5 @@ public abstract class Graph { public abstract int getShortestPathDijkstra(MarkedVertex n1, MarkedVertex n2); - public abstract int getShortestPathAStar(MarkedVertex n1, MarkedVertex n2); + public abstract double getShortestPathAStar(MarkedVertex n1, MarkedVertex n2); } diff --git a/graph/NameDoesNotExistException.java b/graph/NameDoesNotExistException.java index 65834fc..b482bbf 100644 --- a/graph/NameDoesNotExistException.java +++ b/graph/NameDoesNotExistException.java @@ -28,12 +28,12 @@ class WrapperElement { // ATTRIBUTE private MarkedVertex n1; - private int prio; + private double prio; // KONSTRUKTOR - public WrapperElement(MarkedVertex n1, int prio) { + public WrapperElement(MarkedVertex n1, double prio) { this.n1 = n1; this.prio = prio; } @@ -46,7 +46,7 @@ class WrapperElement { } - public int getPrio() { + public double getPrio() { return this.prio; } @@ -62,6 +62,6 @@ class WrapperElement { class WrapperComparator implements Comparator> { public int compare(WrapperElement element1, WrapperElement element2) { - return Integer.compare(element1.getPrio(), element2.getPrio()); + return Double.compare(element1.getPrio(), element2.getPrio()); } } diff --git a/graph/UndirectedGraph.java b/graph/UndirectedGraph.java index c7bb47d..c41a2b2 100644 --- a/graph/UndirectedGraph.java +++ b/graph/UndirectedGraph.java @@ -182,15 +182,16 @@ public class UndirectedGraph ext // Den nächsten Knoten, der am wenigsten kostet, besuchen WrapperElement nextVertex = queue.poll(); - // Knoten als besucht makieren - visited.put(nextVertex.getElement(), true); - - - // Logging - textDescription = "Visit " + nextVertex.getElement().getName(); - System.out.println(textDescription); - nextVertex.getElement().getScreenVertex().setColor(Color.BLUE); - this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); + // Falls Knoten schon besucht + if(!visited.get(nextVertex.getElement())){ + // Knoten als besucht makieren + visited.put(nextVertex.getElement(), true); + textDescription = "Visit " + nextVertex.getElement().getName(); + // Logging + System.out.println(textDescription); + nextVertex.getElement().getScreenVertex().setColor(Color.BLUE); + this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); + } // Wenn Weg gefunden, brich ab @@ -267,7 +268,7 @@ public class UndirectedGraph ext } - public int getShortestPathAStar(MarkedVertex n1, MarkedVertex n2) { + public double getShortestPathAStar(MarkedVertex n1, MarkedVertex n2) { // Erstellt Hashmap um Distanz von Startnoten zu jedem Knoten auf dem Graph zu tracken // Erstellt Hashmap um zu tracken welche Knoten schon besucht wurden @@ -275,11 +276,11 @@ public class UndirectedGraph ext // Initialisierung aller Distanzen auf UNENDLICH (= -1) // Initialisierung, dass kein Knoten besucht wurde // Initialisierung aller Vorgänger auf null - HashMap, Integer> distance = new HashMap<>(); + HashMap, Double> distance = new HashMap<>(); HashMap, Boolean> visited = new HashMap<>(); HashMap, MarkedVertex> predecessors = new HashMap<>(); for (MarkedVertex i: this.getAllVertexes()) { - distance.put(i, -1); + distance.put(i, -1.0); visited.put(i, false); predecessors.put(i, null); } @@ -289,15 +290,15 @@ public class UndirectedGraph ext // Distanz zu Startknoten auf 0 // Weg zu Startknoten in die Schlange aufnehmen - distance.put(n1, 0); + distance.put(n1, 0.0); queue.add(new WrapperElement<>(n1, 0)); // Variable, die Distanz zwischen aktuellem Knoten und Nachfolger speichert - int dist = 0; + double dist = 0; // Variable, die Distanz zwischen dem potenziell nächsten Knoten und dem Zielknoten speichert - int airDist = 0; + double airDist = 0; // Variable, die Distanz zwischen dem aktuellen Knoten bis zum Endknoten speichert - int distToFinish = 0; + double distToFinish = 0; // Zähler für LogList int step = 0; // String für den Description Inhalt @@ -314,16 +315,16 @@ public class UndirectedGraph ext // Den nächsten Knoten, der am wenigsten kostet, besuchen WrapperElement nextVertex = queue.poll(); - // Knoten als besucht makieren - visited.put(nextVertex.getElement(), true); - - - // Logging - textDescription = "Visit " + nextVertex.getElement().getName(); - System.out.println(textDescription); - nextVertex.getElement().getScreenVertex().setColor(Color.BLUE); - this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); - + // Falls Knoten schon besucht + if(!visited.get(nextVertex.getElement())){ + // Knoten als besucht makieren + visited.put(nextVertex.getElement(), true); + textDescription = "Visit " + nextVertex.getElement().getName(); + // Logging + System.out.println(textDescription); + nextVertex.getElement().getScreenVertex().setColor(Color.BLUE); + this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); + } // Wenn Weg gefunden, brich ab if (nextVertex.getElement() == n2) { @@ -352,8 +353,8 @@ public class UndirectedGraph ext if (j.getSource() == nextVertex.getElement() && j.getDestination() == i) { //Berechnung der Heuristik über die Luftdistanz des nächsten Knoten zum Zielknoten - airDist = (int) Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2) - + Math.pow((i.getCords()[1] - n2.getCords()[1]), 2)); + airDist = Math.sqrt(Math.pow((i.getCords()[0] - n2.getCords()[0]), 2) + + Math.pow((i.getCords()[1] - n2.getCords()[1]), 2)) / 100; // Berechne Distanz zu nächstem Knoten EdgeWeightMarking marking = (EdgeWeightMarking) j.getMarking(); @@ -375,7 +376,7 @@ public class UndirectedGraph ext distance.put(i, dist); // Logging - textDescription = "Add " + i.getName() + " with " + dist + " weight to queue."; + textDescription = "Add " + i.getName() + " with " + distToFinish + " weight to queue."; System.out.println(textDescription); i.getScreenVertex().setColor(Color.YELLOW); this.logList.add(new OurLogElement(step, textDescription, 0, this.getScreenGraphCopy())); diff --git a/out/production/ProjektGraph/graph/DirectedGraph.class b/out/production/ProjektGraph/graph/DirectedGraph.class index ef11134497884ed67415dabdf28aa3bd53ef99a7..3f8f629f64b17942007981bcefd89a489370202e 100644 GIT binary patch delta 5144 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 J06!6A{s;5=h06c{ diff --git a/out/production/ProjektGraph/graph/Graph.class b/out/production/ProjektGraph/graph/Graph.class index 1104eeea720d10d78bbddd2c058e62942c44004e..bf2464792481efdcc16b91dd9a10cdbe052ace8f 100644 GIT binary patch delta 173 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 diff --git a/out/production/ProjektGraph/graph/WrapperElement.class b/out/production/ProjektGraph/graph/WrapperElement.class index f7c11db25a6a58ae479cc929b2b64cf549fe1db7..12509f91fc115bb8bc6342deafde857e6d8a335d 100644 GIT binary patch delta 82 zcmdnSvyEp$FQd!EJ|Hn!hA|jO7BDUWlA=tZj4qqAndF#+m>F0Y7#R4qwlgqlX>Vm< i*V33go88HD7#R4qwlgqlX>Vm< i*OHk$o8 Date: Mon, 8 Jul 2024 18:03:30 +0200 Subject: [PATCH 2/3] Window size and Example restructuring --- OurApplication/OurApplication.java | 2 +- graph/ExampleGraphs.java | 120 ++++++++---------- .../OurApplication/OurAlgorithm.class | Bin 2490 -> 2490 bytes .../OurApplication/OurApplication.class | Bin 3016 -> 3016 bytes .../ProjektGraph/graph/DirectedGraph.class | Bin 13065 -> 13065 bytes 5 files changed, 56 insertions(+), 66 deletions(-) diff --git a/OurApplication/OurApplication.java b/OurApplication/OurApplication.java index 8717486..055edfb 100644 --- a/OurApplication/OurApplication.java +++ b/OurApplication/OurApplication.java @@ -73,7 +73,7 @@ public class OurApplication { frame.pack(); applet.init(); applet.start(); - frame.setSize(1000,800); + frame.setSize(1350,800); frame.setVisible(true); } diff --git a/graph/ExampleGraphs.java b/graph/ExampleGraphs.java index db9619d..3208d3b 100644 --- a/graph/ExampleGraphs.java +++ b/graph/ExampleGraphs.java @@ -8,6 +8,59 @@ public class ExampleGraphs { public DirectedGraph example1() { + /* + * Erstellt einen Beispielgraphen (Beispiel 4), der sich ideal für die Demonstration der Funktionsweise + * des Dijkstra- und A*-Algorithmus eignet. Der Graph enthält eine Vielzahl von Knoten, die durch + * gewichtete Kanten verbunden sind. Dies ermöglicht es, den kürzesten Weg von einem Startknoten zu einem + * Zielknoten effizient zu berechnen und die Unterschiede zwischen den beiden Algorithmen in der + * Pfadfindung zu veranschaulichen. + * + * + */ + + DirectedGraph example4 = new DirectedGraph<>(); + + // Erstellung der Knoten mit Koordinaten + MarkedVertex A = new MarkedVertex<>(50, 250, "Start", null, null); + MarkedVertex B = new MarkedVertex<>(150, 150, "B", null, null); + MarkedVertex C = new MarkedVertex<>(150, 350, "C", null, null); + MarkedVertex D = new MarkedVertex<>(250, 100, "D", null, null); + MarkedVertex E = new MarkedVertex<>(250, 250, "E", null, null); + MarkedVertex F = new MarkedVertex<>(350, 200, "F", null, null); + MarkedVertex G = new MarkedVertex<>(450, 300, "G", null, null); + MarkedVertex H = new MarkedVertex<>(450, 100, "Ende", null, null); + + + // Hinzufügen der Knoten zum Graphen + example4.addVertex(A); + example4.addVertex(B); + example4.addVertex(C); + example4.addVertex(D); + example4.addVertex(E); + example4.addVertex(F); + example4.addVertex(G); + example4.addVertex(H); + + // Erstellung der Kanten mit Gewichtungen + example4.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(4))); + example4.addEdge(new MarkedEdge<>("AC", A, C, new EdgeWeightMarking(2))); + example4.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(5))); + example4.addEdge(new MarkedEdge<>("BD", B, D, new EdgeWeightMarking(10))); + example4.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(3))); + example4.addEdge(new MarkedEdge<>("CE", C, E, new EdgeWeightMarking(7))); + example4.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(2))); + example4.addEdge(new MarkedEdge<>("DF", D, F, new EdgeWeightMarking(2))); + example4.addEdge(new MarkedEdge<>("EF", E, F, new EdgeWeightMarking(5))); + example4.addEdge(new MarkedEdge<>("EG", E, G, new EdgeWeightMarking(10))); + example4.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(3))); + example4.addEdge(new MarkedEdge<>("FH", F, H, new EdgeWeightMarking(6))); + example4.addEdge(new MarkedEdge<>("GH", G, H, new EdgeWeightMarking(1))); + + return example4; + } + + public DirectedGraph example2() { + /* * Beispiel 1 zeigt ein Gitter aus Knoten und Kanten, bei dem jeder Knoten mit * seinen horizontal und vertikal benachbarten Knoten verbunden ist. Alle Kanten @@ -18,8 +71,6 @@ public class ExampleGraphs { * Demonstrieren, wie der A*-Algorithmus durch gezieltere Suche effizienter ist * als der Dijkstra-Algorithmus in einem strukturierten Gittergraphen. * - * Startknoten: A - * Endknoten: Y */ DirectedGraph example1 = new DirectedGraph<>(); @@ -63,7 +114,7 @@ public class ExampleGraphs { graph.addEdge(backwardEdge); } - public DirectedGraph example2() { + public DirectedGraph example3() { DirectedGraph example2 = new DirectedGraph<>(); @@ -73,8 +124,6 @@ public class ExampleGraphs { * Der andere Weg (unten) hat mehr Knoten mit höherer Gewichtung der Kanten. Der Algorithmus sollte zuerst den oberen * Weg erkunden, bis er die hohe Gewichtung der letzten Kante des unteren Wegs berücksichtigt. * - * Startknoten: A - * Endknoten: E */ MarkedVertex A = new MarkedVertex<>(100, 100, "Start", null, null); @@ -107,15 +156,13 @@ public class ExampleGraphs { - public DirectedGraph example3() { + public DirectedGraph example4() { /* * Beispiel 3 zeigt ein Labyrinth mit vier horizontalen Wegen, die jeweils aus vier Knoten bestehen. * Jeder Weg führt zum Endpunkt E1, E2, E3 bzw. E4. Ziel ist es zu zeigen, dass die Algorithmen auch * potenziell falsche Wege erkunden können, bevor sie den richtigen Endpunkt erreichen. * - * Startknoten: A - * Endknoten: E2 */ DirectedGraph example3 = new DirectedGraph<>(); @@ -187,63 +234,6 @@ public class ExampleGraphs { return example3; } - - - - public DirectedGraph example4() { - - /** - * Erstellt einen Beispielgraphen (Beispiel 4), der sich ideal für die Demonstration der Funktionsweise - * des Dijkstra- und A*-Algorithmus eignet. Der Graph enthält eine Vielzahl von Knoten, die durch - * gewichtete Kanten verbunden sind. Dies ermöglicht es, den kürzesten Weg von einem Startknoten zu einem - * Zielknoten effizient zu berechnen und die Unterschiede zwischen den beiden Algorithmen in der - * Pfadfindung zu veranschaulichen. - * - * Startknoten: A - * Zielknoten: H - * - */ - - DirectedGraph example4 = new DirectedGraph<>(); - - // Erstellung der Knoten mit Koordinaten - MarkedVertex A = new MarkedVertex<>(50, 250, "Start", null, null); - MarkedVertex B = new MarkedVertex<>(150, 150, "B", null, null); - MarkedVertex C = new MarkedVertex<>(150, 350, "C", null, null); - MarkedVertex D = new MarkedVertex<>(250, 100, "D", null, null); - MarkedVertex E = new MarkedVertex<>(250, 250, "E", null, null); - MarkedVertex F = new MarkedVertex<>(350, 200, "F", null, null); - MarkedVertex G = new MarkedVertex<>(450, 300, "G", null, null); - MarkedVertex H = new MarkedVertex<>(450, 100, "Ende", null, null); - - - // Hinzufügen der Knoten zum Graphen - example4.addVertex(A); - example4.addVertex(B); - example4.addVertex(C); - example4.addVertex(D); - example4.addVertex(E); - example4.addVertex(F); - example4.addVertex(G); - example4.addVertex(H); - - // Erstellung der Kanten mit Gewichtungen - example4.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(4))); - example4.addEdge(new MarkedEdge<>("AC", A, C, new EdgeWeightMarking(2))); - example4.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(5))); - example4.addEdge(new MarkedEdge<>("BD", B, D, new EdgeWeightMarking(10))); - example4.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(3))); - example4.addEdge(new MarkedEdge<>("CE", C, E, new EdgeWeightMarking(7))); - example4.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(2))); - example4.addEdge(new MarkedEdge<>("DF", D, F, new EdgeWeightMarking(2))); - example4.addEdge(new MarkedEdge<>("EF", E, F, new EdgeWeightMarking(5))); - example4.addEdge(new MarkedEdge<>("EG", E, G, new EdgeWeightMarking(10))); - example4.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(3))); - example4.addEdge(new MarkedEdge<>("FH", F, H, new EdgeWeightMarking(6))); - example4.addEdge(new MarkedEdge<>("GH", G, H, new EdgeWeightMarking(1))); - - return example4; - } } diff --git a/out/production/ProjektGraph/OurApplication/OurAlgorithm.class b/out/production/ProjektGraph/OurApplication/OurAlgorithm.class index 0b458fa9216d08ec146601c4c1199e8ec2cb903a..a7794764b867e3069f6c525c687c62dc5ac12a03 100644 GIT binary patch delta 17 Ycmdlbyi0gPDJN?P11m%5henNc1d@d$dx6KQ=)ENOTtOV-- delta 15 XcmX>henNc1d@d&D7n>JysWSoqGHL~j diff --git a/out/production/ProjektGraph/graph/DirectedGraph.class b/out/production/ProjektGraph/graph/DirectedGraph.class index c2eba1904169841572d59cf93f7e4d0eda25c873..34918258aa7e7fa9099780d491abd2a1898e7ffa 100644 GIT binary patch delta 300 zcmWN{O(=r_7zgm@|9_;3%S1+aTX9fouSMHxHlIseM7gLbhjH3*xh=``DpF1k&Kwlw z;vnVbb4rU^Z*nn{ltn&k?DV_*te6$s%XpF};=rjmaV8BomjEs#f=d}gS|)KNQCv$L zH!_D?SwdEpVap2cWDWPSjtAL9PPXtUyU5ESo+N{3vGF1~6yzIkaNr$v_<(^=nD{~n zKbSxfQ~1L)1v5zkaS{nC=2?afmSdZh*kKh8=!DH0{IZtSbg_-~>@FE$BS+c9SvGTl z22*s?VhfMh%Hz^Xvz=Lbn5W5CcCbjVR-H~EKhVOI(D|vvThw)pH8e_r#7lH8`HT> z>(XX)ZL_+udEMHA;bZ=XFu$Uh0N>3Kot9|KBsd`tgKIGM>eEL$8zSXN= z4PY8X8jgTQaSD^9agw!2idIP1DjC`&OIKv;n;f#pryLJ~|3eheMIj@2nV^U%N{CX* zHf8Kk!4Z{Q;3Gjb&-nSF#-&l~im7vc>Rl}ju8x3fq}h3!X>mbXT_hj!Ob(1i)P ONjlsdof|K{JpKTdGDzY8 From 6206aa87917804892374484c6df85ca88c82518d Mon Sep 17 00:00:00 2001 From: Sean Reich Date: Mon, 8 Jul 2024 18:26:18 +0200 Subject: [PATCH 3/3] JavaDoc ExampleGraphs --- .idea/workspace.xml | 32 +-- OurApplication/OurApplication.java | 6 - graph/ExampleGraphs.java | 248 ++++++++++-------- .../OurApplication/OurApplication.class | Bin 3016 -> 2847 bytes .../ProjektGraph/graph/ExampleGraphs.class | Bin 6300 -> 6300 bytes 5 files changed, 152 insertions(+), 134 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index f43f747..01c547d 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -6,15 +6,9 @@ - - - - - - - - - + + + - { + "keyToString": { + "Application.Display.executor": "Run", + "Application.OurApplication.executor": "Run", + "Application.OurLegendArea.executor": "Run", + "RunOnceActivity.ShowReadmeOnStart": "true", + "git-widget-placeholder": "main", + "kotlin-language-version-configured": "true", + "last_opened_file_path": "C:/Git/ProjektGraphMain" } -}]]> +} diff --git a/OurApplication/OurApplication.java b/OurApplication/OurApplication.java index 055edfb..3ba9a59 100644 --- a/OurApplication/OurApplication.java +++ b/OurApplication/OurApplication.java @@ -43,13 +43,7 @@ public class OurApplication { */ public static void main(String[]args){ - Random random = new Random(); - DirectedGraph myGraph = new DirectedGraph<>(); - - ExampleGraphs temp = new ExampleGraphs(); - //myGraph = temp.example2(); - //sean: Ich wollte erst hier dann das ausgewählte Beispiel reinhauen, jedoch wird das hier nur einmal am Anfang aufgerufen System.out.println(myGraph.toString()); diff --git a/graph/ExampleGraphs.java b/graph/ExampleGraphs.java index 3208d3b..5a47940 100644 --- a/graph/ExampleGraphs.java +++ b/graph/ExampleGraphs.java @@ -1,24 +1,30 @@ package graph; import java.awt.*; -import java.util.ArrayList; -import java.util.List; +/** + * Class containing example graphs for demonstration purposes. + */ public class ExampleGraphs { + /** + * Creates an example graph suitable for demonstrating Dijkstra's and A* algorithms. + * This graph contains multiple nodes connected by weighted edges, allowing efficient + * calculation of shortest paths from a start node to an end node. + * + * @return Directed graph instance for example 1. + */ public DirectedGraph example1() { /* - * Erstellt einen Beispielgraphen (Beispiel 4), der sich ideal für die Demonstration der Funktionsweise + * Erstellt einen Beispielgraphen, der sich ideal für die Demonstration der Funktionsweise * des Dijkstra- und A*-Algorithmus eignet. Der Graph enthält eine Vielzahl von Knoten, die durch * gewichtete Kanten verbunden sind. Dies ermöglicht es, den kürzesten Weg von einem Startknoten zu einem - * Zielknoten effizient zu berechnen und die Unterschiede zwischen den beiden Algorithmen in der - * Pfadfindung zu veranschaulichen. - * + * Zielknoten effizient zu berechnen und die Pfadfindung der beiden Algorithmen zu veranschaulichen. * */ - DirectedGraph example4 = new DirectedGraph<>(); + DirectedGraph example1 = new DirectedGraph<>(); // Erstellung der Knoten mit Koordinaten MarkedVertex A = new MarkedVertex<>(50, 250, "Start", null, null); @@ -32,48 +38,53 @@ public class ExampleGraphs { // Hinzufügen der Knoten zum Graphen - example4.addVertex(A); - example4.addVertex(B); - example4.addVertex(C); - example4.addVertex(D); - example4.addVertex(E); - example4.addVertex(F); - example4.addVertex(G); - example4.addVertex(H); + example1.addVertex(A); + example1.addVertex(B); + example1.addVertex(C); + example1.addVertex(D); + example1.addVertex(E); + example1.addVertex(F); + example1.addVertex(G); + example1.addVertex(H); // Erstellung der Kanten mit Gewichtungen - example4.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(4))); - example4.addEdge(new MarkedEdge<>("AC", A, C, new EdgeWeightMarking(2))); - example4.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(5))); - example4.addEdge(new MarkedEdge<>("BD", B, D, new EdgeWeightMarking(10))); - example4.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(3))); - example4.addEdge(new MarkedEdge<>("CE", C, E, new EdgeWeightMarking(7))); - example4.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(2))); - example4.addEdge(new MarkedEdge<>("DF", D, F, new EdgeWeightMarking(2))); - example4.addEdge(new MarkedEdge<>("EF", E, F, new EdgeWeightMarking(5))); - example4.addEdge(new MarkedEdge<>("EG", E, G, new EdgeWeightMarking(10))); - example4.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(3))); - example4.addEdge(new MarkedEdge<>("FH", F, H, new EdgeWeightMarking(6))); - example4.addEdge(new MarkedEdge<>("GH", G, H, new EdgeWeightMarking(1))); + example1.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(4))); + example1.addEdge(new MarkedEdge<>("AC", A, C, new EdgeWeightMarking(2))); + example1.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(5))); + example1.addEdge(new MarkedEdge<>("BD", B, D, new EdgeWeightMarking(10))); + example1.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(3))); + example1.addEdge(new MarkedEdge<>("CE", C, E, new EdgeWeightMarking(7))); + example1.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(2))); + example1.addEdge(new MarkedEdge<>("DF", D, F, new EdgeWeightMarking(2))); + example1.addEdge(new MarkedEdge<>("EF", E, F, new EdgeWeightMarking(5))); + example1.addEdge(new MarkedEdge<>("EG", E, G, new EdgeWeightMarking(10))); + example1.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(3))); + example1.addEdge(new MarkedEdge<>("FH", F, H, new EdgeWeightMarking(6))); + example1.addEdge(new MarkedEdge<>("GH", G, H, new EdgeWeightMarking(1))); - return example4; + return example1; } + /** + * Creates an example grid graph where each node is connected to its horizontal and vertical neighbors. + * All edges have the same weight. The start node is in one corner of the grid, and the end node is + * in the opposite corner, demonstrating the efficiency of the A* algorithm in structured grid graphs. + * + * @return Directed graph instance for example 2. + */ public DirectedGraph example2() { /* - * Beispiel 1 zeigt ein Gitter aus Knoten und Kanten, bei dem jeder Knoten mit + * Beispiel 2 zeigt ein Gitter aus Knoten und Kanten, bei dem jeder Knoten mit * seinen horizontal und vertikal benachbarten Knoten verbunden ist. Alle Kanten * haben die gleiche Gewichtung. Der Startknoten befindet sich in einer Ecke - * des Gitters und der Zielknoten in der gegenüberliegenden Ecke. - * - * Ziel: - * Demonstrieren, wie der A*-Algorithmus durch gezieltere Suche effizienter ist + * des Gitters und der Zielknoten in der gegenüberliegenden Ecke. Dadurch wird gezeigt, + * wie der A*-Algorithmus durch gezieltere Suche effizienter ist * als der Dijkstra-Algorithmus in einem strukturierten Gittergraphen. * */ - DirectedGraph example1 = new DirectedGraph<>(); + DirectedGraph example2 = new DirectedGraph<>(); int size = 5; MarkedVertex[][] vertices = new MarkedVertex[size][size]; @@ -88,7 +99,7 @@ public class ExampleGraphs { name = "Ende"; } vertices[row][col] = new MarkedVertex<>(50 + col * 100, 50 + row * 100, name, null, null); - example1.addVertex(vertices[row][col]); + example2.addVertex(vertices[row][col]); } } @@ -96,36 +107,36 @@ public class ExampleGraphs { for (int row = 0; row < size; row++) { for (int col = 0; col < size; col++) { if (col < size - 1) { - addBidirectionalEdge(example1, vertices[row][col], vertices[row][col + 1], new EdgeWeightMarking(1)); + addBidirectionalEdge(example2, vertices[row][col], vertices[row][col + 1], new EdgeWeightMarking(1)); } if (row < size - 1) { - addBidirectionalEdge(example1, vertices[row][col], vertices[row + 1][col], new EdgeWeightMarking(1)); + addBidirectionalEdge(example2, vertices[row][col], vertices[row + 1][col], new EdgeWeightMarking(1)); } } } - return example1; - } - - private void addBidirectionalEdge(DirectedGraph graph, MarkedVertex from, MarkedVertex to, EdgeWeightMarking weight) { - MarkedEdge forwardEdge = new MarkedEdge<>("edge" + from.getName() + "_" + to.getName(), from, to, weight); - MarkedEdge backwardEdge = new MarkedEdge<>("edge" + to.getName() + "_" + from.getName(), to, from, weight); - graph.addEdge(forwardEdge); - graph.addEdge(backwardEdge); + return example2; } + /** + * Creates an example graph illustrating two paths from a start node to an end node with different characteristics: + * one path with few nodes and mostly low-weight edges, and another path with more nodes and higher-weight edges. + * The algorithms will alternate exploration between these paths. + * + * @return Directed graph instance for example 3. + */ public DirectedGraph example3() { - DirectedGraph example2 = new DirectedGraph<>(); - /* - * Beispiel 2 zeigt zwei Wege von einem Startknoten zu einem Zielknoten mit unterschiedlichen Eigenschaften: - * Ein Weg (oben) hat wenige Knoten mit Kanten geringer Gewichtung, außer der letzten Kante, die hohe Gewichtung hat. - * Der andere Weg (unten) hat mehr Knoten mit höherer Gewichtung der Kanten. Der Algorithmus sollte zuerst den oberen - * Weg erkunden, bis er die hohe Gewichtung der letzten Kante des unteren Wegs berücksichtigt. + * Beispiel 3 zeigt zwei Wege von einem Startknoten zu einem Zielknoten mit unterschiedlichen Eigenschaften: + * Ein Weg (oben) hat wenige Knoten mit Kanten geringer Gewichtung, außer der vorletzten Kante, die hohe Gewichtung hat. + * Der andere Weg (unten) hat mehr Knoten mit höherer Gewichtung der Kanten. Die Algorithmen wechseln also mit dem Erkunden + * zwischen den beiden Pfaden. * */ + DirectedGraph example3 = new DirectedGraph<>(); + MarkedVertex A = new MarkedVertex<>(100, 100, "Start", null, null); MarkedVertex B = new MarkedVertex<>(250, 50, "B", null, null); MarkedVertex C = new MarkedVertex<>(400, 100, "C", null, null); @@ -134,38 +145,44 @@ public class ExampleGraphs { MarkedVertex F = new MarkedVertex<>(250, 200, "F", null, null); MarkedVertex G = new MarkedVertex<>(550, 200, "G", null, null); - example2.addVertex(A); - example2.addVertex(B); - example2.addVertex(C); - example2.addVertex(D); - example2.addVertex(E); - example2.addVertex(F); - example2.addVertex(G); + example3.addVertex(A); + example3.addVertex(B); + example3.addVertex(C); + example3.addVertex(D); + example3.addVertex(E); + example3.addVertex(F); + example3.addVertex(G); - example2.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(1))); - example2.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(1))); - example2.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(10))); - example2.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(1))); + example3.addEdge(new MarkedEdge<>("AB", A, B, new EdgeWeightMarking(1))); + example3.addEdge(new MarkedEdge<>("BC", B, C, new EdgeWeightMarking(1))); + example3.addEdge(new MarkedEdge<>("CD", C, D, new EdgeWeightMarking(10))); + example3.addEdge(new MarkedEdge<>("DE", D, E, new EdgeWeightMarking(1))); - example2.addEdge(new MarkedEdge<>("AF", A, F, new EdgeWeightMarking(5))); - example2.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(5))); - example2.addEdge(new MarkedEdge<>("GE", G, E, new EdgeWeightMarking(5))); + example3.addEdge(new MarkedEdge<>("AF", A, F, new EdgeWeightMarking(5))); + example3.addEdge(new MarkedEdge<>("FG", F, G, new EdgeWeightMarking(5))); + example3.addEdge(new MarkedEdge<>("GE", G, E, new EdgeWeightMarking(5))); - return example2; + return example3; } - - + /** + * Creates an example labyrinth graph with four horizontal paths, each consisting of four nodes. + * Each path leads to a respective endpoint, demonstrating how algorithms may explore potentially incorrect paths + * before finding the correct one, and showing the efficiency of A* in finding the correct path quickly. + * + * @return Directed graph instance for example 4. + */ public DirectedGraph example4() { /* - * Beispiel 3 zeigt ein Labyrinth mit vier horizontalen Wegen, die jeweils aus vier Knoten bestehen. - * Jeder Weg führt zum Endpunkt E1, E2, E3 bzw. E4. Ziel ist es zu zeigen, dass die Algorithmen auch - * potenziell falsche Wege erkunden können, bevor sie den richtigen Endpunkt erreichen. + * Beispiel 4 zeigt ein Labyrinth mit vier horizontalen Wegen, die jeweils aus vier Knoten bestehen. + * Jeder Weg führt zum Endpunkt E1, E2, E3 bzw. Ende. Ziel ist es zu zeigen, dass die Algorithmen auch + * potenziell falsche Wege erkunden können, bevor sie den Endknoten erreichen. Zudem wird gezeigt, + * wie A* schnell den richtigen Weg findet, während Djkstra alle Wege durchsucht. * */ - DirectedGraph example3 = new DirectedGraph<>(); + DirectedGraph example4 = new DirectedGraph<>(); // Startpunkt A in der Mitte der Y-Koordinate MarkedVertex A = new MarkedVertex<>(100, 250, "Start", null, null); @@ -194,46 +211,59 @@ public class ExampleGraphs { MarkedVertex D4 = new MarkedVertex<>(400, 400, "D4", null, null); MarkedVertex E4 = new MarkedVertex<>(500, 400, "Ende", null, null); // Endpunkt des vierten Weges - example3.addVertex(A); - example3.addVertex(B1); - example3.addVertex(C1); - example3.addVertex(D1); - example3.addVertex(B2); - example3.addVertex(C2); - example3.addVertex(D2); - example3.addVertex(B3); - example3.addVertex(C3); - example3.addVertex(D3); - example3.addVertex(B4); - example3.addVertex(C4); - example3.addVertex(D4); - example3.addVertex(E1); - example3.addVertex(E2); - example3.addVertex(E3); - example3.addVertex(E4); + example4.addVertex(A); + example4.addVertex(B1); + example4.addVertex(C1); + example4.addVertex(D1); + example4.addVertex(B2); + example4.addVertex(C2); + example4.addVertex(D2); + example4.addVertex(B3); + example4.addVertex(C3); + example4.addVertex(D3); + example4.addVertex(B4); + example4.addVertex(C4); + example4.addVertex(D4); + example4.addVertex(E1); + example4.addVertex(E2); + example4.addVertex(E3); + example4.addVertex(E4); - example3.addEdge(new MarkedEdge<>("AB1", A, B1, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("AB2", A, B2, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("AB3", A, B3, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("AB4", A, B4, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("AB1", A, B1, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("AB2", A, B2, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("AB3", A, B3, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("AB4", A, B4, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("B1C1", B1, C1, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("B2C2", B2, C2, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("B3C3", B3, C3, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("B4C4", B4, C4, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("B1C1", B1, C1, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("B2C2", B2, C2, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("B3C3", B3, C3, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("B4C4", B4, C4, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("C1D1", C1, D1, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("C2D2", C2, D2, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("C3D3", C3, D3, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("C4D4", C4, D4, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("C1D1", C1, D1, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("C2D2", C2, D2, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("C3D3", C3, D3, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("C4D4", C4, D4, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("D1E1", D1, E1, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("D2E2", D2, E2, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("D3E3", D3, E3, new EdgeWeightMarking(1))); - example3.addEdge(new MarkedEdge<>("D4E4", D4, E4, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("D1E1", D1, E1, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("D2E2", D2, E2, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("D3E3", D3, E3, new EdgeWeightMarking(1))); + example4.addEdge(new MarkedEdge<>("D4E4", D4, E4, new EdgeWeightMarking(1))); - return example3; + return example4; + } + + /** + * Helper method to add a bidirectional edge between two vertices in a graph. + * + * @param graph The graph instance where the edge should be added. + * @param from The starting vertex of the edge. + * @param to The ending vertex of the edge. + * @param weight The weight marking of the edge. + */ + private void addBidirectionalEdge(DirectedGraph graph, MarkedVertex from, MarkedVertex to, EdgeWeightMarking weight) { + MarkedEdge forwardEdge = new MarkedEdge<>("edge" + from.getName() + "_" + to.getName(), from, to, weight); + MarkedEdge backwardEdge = new MarkedEdge<>("edge" + to.getName() + "_" + from.getName(), to, from, weight); + graph.addEdge(forwardEdge); + graph.addEdge(backwardEdge); } } - - diff --git a/out/production/ProjektGraph/OurApplication/OurApplication.class b/out/production/ProjektGraph/OurApplication/OurApplication.class index e4a10fa2fd9b652d99272f3cf8b0db56b76bc1ec..289c516d8e59cfc2d6ccf2107deb1de5aa8d0771 100644 GIT binary patch delta 1023 zcmXYwTW=d>5Qd+%*Is+Q&?bR|H3@MYC*{wr^R;XT0ov~}htw!<6vghe&_`^gnG#)W{ltTyKr9&D$2EFth{FR72 zPQS*0!4sH{rdXp-D)g6kN+r8eO0Djc7R$wJ#Y$tiiRo#zTxL^maPP+4bE*+1@WS?463v2;&9;CY*nj8Fk9z-w#D~ok^xW z{HSxm7gL^buKQv}iWv_|D=dyXzX$uAd%m=KOkvQO2oFm2S+C^06Y-CPGFTqE)rBwtA(v?oeVDE%DNFDsl!U+bH)t;VWYG4mp9!C`Iv&E{S(2i5KQ7b~l0Yvv?7~ z?z(9CHsRF==u<5Yw|LAYD#+lP%TT`EWO&^rCP3U$T}JZB-qAKsTLG8Je6mf_3c957 z)27?Y)fEk=NwWJyHqQ|YUOE%y8e4CS&ZtB4nr%b)Yk{NDscEh_~ z@UE9UlQZ?6z*3Jt)@+eCb+yGC-e3Ch{&Jl@u}2A!l8sKwip~<}7*ov2bTaZb=2_!7 zIV`q0$(|q|af&ZF&DXL92P|@%C4OR=JFIk+s&>`jUHJmZ{3B(qiB`=h-%?>mgpG5H zD%YinDQ-}sE;47tZ?G$qSrCc$cuyv@CcE%HAIK}r$tLadp`_d9gtTx&MBihEk7>%N fK9NH5gdP_AREl+LeI~WK{LcyN0)HVyA25XOIpz0Bgay{!CBb-E zjqw^$sqr~^uu846EK9B0wH%E;T0U6%T$MiHOCv+W3bm|AB|f-xoW>3Qw`B3ePpxW zu9{;9wR?}E(f`G4l%0ok-0uIOYW>Zq88YegZ>l=8jV_xA3IAKwqwW*9G2TtDPW34o z{O^@xw#^ybuY;eX4VFbe4{CV8zfdu$2K`Se_Qza(_F=_7|8HZTP=-0GDI@-$73G14 z6g7Gb8;SfCZ*?g#IhISUq)m<~Vsl=8J(cnDX^TqN*bCMa~ z33tXH;k3aSn@5@TPlYFoqnx#QjHn`P7?Fl1{j$qs+ao5zs9`nI6{+=ubKkCtBtK zHx}Rud&so{hLeurn1aNduw!Zbh#LHSaqnW#8ZwPF0r65A3|S#j#{x@m~>M`k9>uG4lqCmE`1D&+C%bihMDCs^Bj=@ z9pxHhY%-3|ac(lf2g3N66MV`PUop+?A~V~QyuLFnvOFV2Ov>cQ%Pgz-i~{R2_j*3! zGFPOT4&G;jXGMiRZg7?7M7Uuo^*k?#fRn<0k)nL{S!w$vUY675IWPDtqRFy6-|M_8 vN?wyauQB{Oap|y!H+WOzd`pVUH~zQm4Jo@*>}@Hwvtd*Cig$!p!MpzesyE-| diff --git a/out/production/ProjektGraph/graph/ExampleGraphs.class b/out/production/ProjektGraph/graph/ExampleGraphs.class index ed65523276ef30de0162973a84782a5e6dc9ea07..e9feef10ed5ef0a03e7b71787661a0c3bb2eac20 100644 GIT binary patch literal 6300 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 B?xO$z literal 6300 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