package GKA.Graph; import static GKA.FileHandling.Checks.PreChecks.checkExistingFile; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Queue; import java.util.Set; import org.jgraph.JGraph; import org.jgraph.graph.Edge; //import org.jgraph.graph.DefaultEdge; //import org.jgrapht.Graph; import org.jgrapht.ListenableGraph; import org.jgrapht.ext.JGraphXAdapter; import org.jgrapht.graph.DirectedPseudograph; import org.jgrapht.graph.ListenableDirectedGraph; import org.jgrapht.graph.ListenableUndirectedGraph; import org.jgrapht.graph.Pseudograph; import GKA.Controler.MainControler; import GKA.Controler.MessageReceiver; import GKA.FileHandling.Errors.FileNotExists; import GKA.FileHandling.Errors.IncorrectFileFormat; import com.mxgraph.layout.mxCircleLayout; import com.mxgraph.layout.mxParallelEdgeLayout; import com.mxgraph.util.mxConstants; import com.mxgraph.view.mxGraph; class GKAGraph implements GKAGraphInterface { /** * Creates a new Graph * * @param type - specifies the type of the Graph * @return */ static final String DIRECTED_SIGN = "->"; static final String UNDIRECTED_SIGN = "--"; static GKAGraphInterface newGraph(GraphType type){ return new GKAGraph(type); } static GKAGraphInterface newGraph(File file){ ArrayList<String> linedFile; GKAGraphInterface returnValue = null; try { linedFile = readFile(file); ArrayList<HashMap<String,String>> parsedGraph = parse(linedFile); Double weight; String edgeName; boolean isDirectedGraph = false; boolean isWeightedGraph = false; for(HashMap<String,String> line : parsedGraph) { if(line.get("vertexOnly").equals("false")) { isDirectedGraph = line.get("isDirected").equals("true"); isWeightedGraph = isWeightedGraph || line.get("weight") != null; } } for(HashMap<String,String> line : parsedGraph) { if(line.get("vertexOnly").equals("false")) { if(isDirectedGraph != (line.get("isDirected").equals("true"))) { MainControler.sendMessage("Graph beinhaltet sowohl gerichtete als auch ungerichtete Kanten"); throw new IncorrectFileFormat(); } } } if(isDirectedGraph && isWeightedGraph) { returnValue = newGraph(GraphType.DirectedWeighted); } else if(isDirectedGraph && !isWeightedGraph) { returnValue = newGraph(GraphType.Directed); } else if(!isDirectedGraph && isWeightedGraph) { returnValue = newGraph(GraphType.UndirectedWeighted); } else if(!isDirectedGraph && !isWeightedGraph) { returnValue = newGraph(GraphType.Undirected); } for(HashMap<String,String> line : parsedGraph) { if(line.get("vertexOnly") == "true") { returnValue.addVertex(line.get("node1")); } else { if(line.containsKey("weight")) { weight = Double.parseDouble(line.get("weight")); } else { weight = (isWeightedGraph != (line.get("weight") != null)) ? 1.0 : null; } if(line.containsKey("edgeName")) { edgeName = line.get("edgeName"); } else { edgeName = null; } returnValue.addEdge(line.get("node1"), line.get("node2"), edgeName, weight); } } } catch (IOException | FileNotExists e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IncorrectFileFormat e) { // TODO Auto-generated catch block e.printStackTrace(); } return returnValue; } static GKAGraphInterface newGraph(int vertexAnzahl, int edgeAnzahl){ GKAGraphInterface retval = GKAGraphInterface.newGraph(GraphType.DirectedWeighted); for(int i = 0; i < vertexAnzahl; i++) { retval.addVertex(String.valueOf(i)); } for(int i = 0; i < vertexAnzahl - 1; i++) { retval.addEdge(String.valueOf(i), String.valueOf(i+1), null, (double)((int) (Math.random() * edgeAnzahl))); } retval.addEdge(String.valueOf(vertexAnzahl - 1), String.valueOf(0), null, (double)((int) (Math.random() * edgeAnzahl))); for(int i = 0 ; i < (edgeAnzahl - vertexAnzahl); i++) { int edgeTarget = (int) (Math.random() * (vertexAnzahl)); int edgeSource = (int) (Math.random() * (vertexAnzahl)); retval.addEdge(String.valueOf(edgeSource), String.valueOf(edgeTarget), null,(double)((int) (Math.random() * edgeAnzahl))); } return retval; } static GKAGraphInterface newRundReiseGraph(int vertexAnzahl) { GKAGraphInterface retval = GKAGraphInterface.newGraph(GraphType.UndirectedWeighted); List<String> vertexList = new ArrayList<>(); int edgeAnzahl = (((vertexAnzahl * vertexAnzahl)/2 - (vertexAnzahl/2))); for(int i = 0; i < vertexAnzahl; i++) { retval.addVertex(String.valueOf(i)); vertexList.add(String.valueOf(i)); } for(int i = 0; i < vertexAnzahl-1; i++) { String source = "" + i; String target = "" + (i + 1); retval.addEdge(source, target, null, Math.random() * edgeAnzahl); if(target == "" + (vertexAnzahl - 1)) { source = "" + 0; target = "" + (vertexAnzahl - 1); Double wholeWeight = 0.0; for(GKAEdge edge : retval.getjGraph().getAllEdges(source, target)) { wholeWeight = wholeWeight + edge.getWeight(); } Double weight = Math.random() * wholeWeight; retval.addEdge(source, target, null, weight); } } Set<String> touched = new HashSet<>(); while(edgeAnzahl != 0) { for(String vertex : vertexList) { if(!touched.contains(vertex)) { touched.add(vertex); for(String nextVertex : vertexList) { if(!touched.contains(nextVertex)) { String source = vertex; String target = nextVertex; if(!retval.getjGraph().containsEdge(source, target)) { if(!retval.getjGraph().containsEdge(target, source)) { List<GKAEdge> shortestPath = retval.dijkstra(source, target); Double wholeWeight = 0.0; for(GKAEdge edge : shortestPath) { Double edgeWeight = edge.getWeight(); wholeWeight = wholeWeight + edgeWeight; } Double weight = Math.random() * wholeWeight; retval.addEdge(source, target, null, weight); } } } } } } edgeAnzahl = edgeAnzahl - 1; } return retval; } private static ArrayList<HashMap<String, String>> parse(ArrayList<String> linedFile) throws IncorrectFileFormat { ArrayList<HashMap<String, String>> retVal = new ArrayList<>(); for (String line : linedFile){ if(!line.isEmpty()) { HashMap<String, String> lineHash = new HashMap<>(); if(line.matches("[\\p{L}|[0-9]]+")) { lineHash.put("vertexOnly","true"); lineHash.put("node1", line); retVal.add(lineHash); //direkt zur Ausgabe } else if(line.matches("[\\p{L}|[0-9]]+" + DIRECTED_SIGN + "[\\p{L}|[0-9]]+(\\([\\p{L}|[0-9]]+\\))?(:\\d+(.\\d+)?)?")) { //Methode für gerichtete Graphen lineHash = getHashedLine(line, DIRECTED_SIGN); lineHash.put("isDirected", "true"); retVal.add(lineHash); } else if(line.matches("[\\p{L}|[0-9]]+" + UNDIRECTED_SIGN + "[\\p{L}|[0-9]]+(\\([\\p{L}|[0-9]]+\\))?(:\\d+(.\\d+)?)?")) { //Methode für ungerichtete Graphen lineHash = getHashedLine(line, UNDIRECTED_SIGN); lineHash.put("isDirected", "false"); retVal.add(lineHash); } else { throw new IncorrectFileFormat(); } } } return retVal; } private static HashMap<String, String> getHashedLine(String line, String sign) { HashMap<String,String> retVal = new HashMap<>(); retVal.put("vertexOnly","false"); String[] splitedLine = line.split(sign); retVal.put("node1", splitedLine[0]); if(splitedLine[1].contains("(")) { splitedLine = splitedLine[1].split("\\("); } else { splitedLine = splitedLine[1].split(":"); } retVal.put("node2", splitedLine[0]); if (splitedLine.length > 1){ if(splitedLine[1].contains(")")){ splitedLine = splitedLine[1].split("\\)|\\):"); retVal.put("edgeName", splitedLine[0]); if(splitedLine.length > 1){ retVal.put("weight", splitedLine[1].replace(":", "")); } } else{ retVal.put("weight", splitedLine[1]); } } return retVal; } //* Wenn der file existiert, werden die " " entfernt und an dem ";" aufgeteilt und in einem Array heraus gegeben private static ArrayList<String> readFile(File file) throws IOException, FileNotExists { CharsetDecoder decoder = Charset.forName("ISO-8859-1").newDecoder(); //decoder.onMalformedInput(CodingErrorAction.IGNORE); InputStreamReader reader2 = new InputStreamReader(new FileInputStream(checkExistingFile(file)), decoder); BufferedReader reader = new BufferedReader(reader2); String line = null; ArrayList<String> returnValue = new ArrayList<>(); while ((line = reader.readLine()) != null) { returnValue.addAll(Arrays.asList(line.replace(" ","").replace("\t","").split(";"))); } return returnValue; } private final ListenableGraph<String, GKAEdge> jGraph; private final JGraphXAdapter<String,GKAEdge> mxgraph; private final GraphType type; private final Set<MessageReceiver> messageReceivers = new HashSet<>(); private Matrix<String, Set<GKAEdge>> warschallMatrix = null; private long edgecount = 0; private GKAGraph(GraphType type){ this.type = type; // Choose if it will be directed or undirected if (isDirected()){ jGraph = new ListenableDirectedGraph<>(new DirectedPseudograph<>(GKAEdge.class)); }else{ jGraph = new ListenableUndirectedGraph<>(new Pseudograph<>(GKAEdge.class)); } // JGXAdapter for showing the Graph in Swing mxgraph = new JGraphXAdapter<>(getjGraph()); // Changing EdgeStyle when is undirected if (!isDirected()){ getMxgraph().getStylesheet().getDefaultEdgeStyle().put(mxConstants.STYLE_ENDARROW, "none"); } setGraphConfig(); } /* (non-Javadoc) * @see GKA.Graph.GKAGraphInterface#getjGraph() */ @Override public ListenableGraph<String, GKAEdge> getjGraph() { return jGraph; } /* (non-Javadoc) * @see GKA.Graph.GKAGraphInterface#getMxgraph() */ @Override public mxGraph getMxgraph() { return mxgraph; } public GraphType getType() { return type; } /* (non-Javadoc) * @see GKA.Graph.GKAGraphInterface#isDirected() */ @Override public boolean isDirected(){ return getType().isDirected(); } /* (non-Javadoc) * @see GKA.Graph.GKAGraphInterface#isWeighted() */ @Override public boolean isWeighted(){ return getType().isWeighted(); } /* (non-Javadoc) * @see GKA.Graph.GKAGraphInterface#addVertex(java.lang.String) */ @Override public boolean addVertex(String vertexName){ if(vertexName == null){ sendMessage("Null is not exepted as VertexName!"); return false; } if(!getjGraph().addVertex(vertexName)){ sendMessage("Vertex \"" + vertexName + "\" already exists!"); return false; } sendMessage("Vertex \"" + vertexName + "\" created."); graphChanged(); return true; } /* (non-Javadoc) * @see GKA.Graph.GKAGraphInterface#addEdge(java.lang.String, java.lang.String, java.lang.String, java.lang.Double) */ @Override public boolean addEdge(String source, String target, String name, Double weight){ if (source == null){ sendMessage("Please add a SourceVertex!"); return false; }else if(target == null){ sendMessage("Please add a TargetVertex!"); return false; } if (weight == null && isWeighted()){ sendMessage("Please add a Weight for weighted Graphs!"); return false; } else if( isWeighted() && weight < 0.0){ sendMessage("A weight below 0 is not allowed!"); return false; } if (weight != null && !isWeighted()){ sendMessage("Weights have no effects to unweighted Graphs!"); } if(!getjGraph().containsVertex(source)){ addVertex(source); } if (!getjGraph().containsVertex(target)){ addVertex(target); } GKAEdge edge; try { edge = new GKAEdge(name, weight, edgecount++); jGraph.addEdge(source, target,edge); sendMessage("Edge \"" + edge.toString() + "\" was set."); } catch (Exception e) { sendMessage("Adding edge from \"" + source + "\" to \"" + target + "\" failed by \n" + e.toString()); return false; } graphChanged(); return true; } @Override public boolean addEdgeUnsave(String source, String target, String name, Double weight){ /*if (source == null){ sendMessage("Please add a SourceVertex!"); return false; }else if(target == null){ sendMessage("Please add a TargetVertex!"); return false; } if (weight == null && isWeighted()){ sendMessage("Please add a Weight for weighted Graphs!"); return false; } else if( isWeighted() && weight < 0.0){ sendMessage("A weight below 0 is not allowed!"); return false; } if (weight != null && !isWeighted()){ sendMessage("Weights have no effects to unweighted Graphs!"); } if(!getjGraph().containsVertex(source)){ addVertex(source); } if (!getjGraph().containsVertex(target)){ addVertex(target); } */ GKAEdge edge; try { edge = new GKAEdge(name, weight, edgecount++); jGraph.addEdge(source, target,edge); sendMessage("Edge \"" + edge.toString() + "\" was set."); } catch (Exception e) { sendMessage("Adding edge from \"" + source + "\" to \"" + target + "\" failed by \n" + e.toString()); return false; } graphChanged(); return true; } private void graphChanged(){ warschallMatrix = null; } @Override public void setLayout(){ mxCircleLayout layout1 = new mxCircleLayout(getMxgraph(),200); layout1.execute(getMxgraph().getDefaultParent()); mxParallelEdgeLayout layout = new mxParallelEdgeLayout(getMxgraph(), 50); layout.execute(getMxgraph().getDefaultParent()); } private void setGraphConfig(){ getMxgraph().setAllowDanglingEdges(false); getMxgraph().setCellsDisconnectable(false); getMxgraph().setDisconnectOnMove(false); getMxgraph().setCellsEditable(false); getMxgraph().setVertexLabelsMovable(false); getMxgraph().setEdgeLabelsMovable(false); getMxgraph().setConnectableEdges(false); } @Override public boolean removeVertex(String vertexName) { return getjGraph().removeVertex(vertexName); } @Override public boolean removeEdge(String source, String target) { return getjGraph().removeEdge(getjGraph().getEdge(source, target)); } @Override public void saveGraph(File file, boolean decreaped){ //Writer fw = null; System.out.println(decreaped); OutputStreamWriter bw = null; if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { //fw = new FileWriter( file ); bw = new OutputStreamWriter(new FileOutputStream(file), "ISO-8859-1"); //bw = new BufferedWriter(fw); bw.write( "" ); for(String vertex :getjGraph().vertexSet()){ bw.append(vertex + ";" + System.getProperty("line.separator")); } String connector = isDirected() ? DIRECTED_SIGN : UNDIRECTED_SIGN; for(GKAEdge edge:getjGraph().edgeSet()){ String saveVal = edge.getSource() + " " + connector + " " + edge.getTarget(); if(edge.getName() != null){ saveVal += " (" + edge.getName() + ")"; } if(isWeighted()){ saveVal += " : " + (decreaped ? (String.valueOf(edge.getWeight().intValue())) : edge.getWeight()); } saveVal += ";" + System.getProperty("line.separator"); bw.append(saveVal); } sendMessage("Graph is saved to: \"" + file.getAbsolutePath() + "\"."); } catch ( IOException e ) { sendMessage( "Konnte Datei nicht erstellen" ); } finally { if ( bw != null ) try { bw.close(); } catch ( IOException e ) { e.printStackTrace();} } } @Override public void colorEdge(GKAEdge edge) { if(edge != null){ getMxgraph().getModel().setStyle( mxgraph.getEdgeToCellMap().get(edge), "strokeColor=FF0000"); } } @Override public void resetColor(){ for(GKAEdge edge : getjGraph().edgeSet()){ getMxgraph().getModel().setStyle(mxgraph.getEdgeToCellMap().get(edge), ""); } } @Override public void colorEdge(Collection<GKAEdge> edges) { if(edges != null){ for(GKAEdge edge: edges){ colorEdge(edge); } } } @Override public List<GKAEdge> shortesPathBroad(String source, String target) { List<String> shortestPath = shortesPathBroadStringList(source, target); if(shortestPath == null){ return null; } else{ ArrayList<GKAEdge> retVal = new ArrayList<>(); ListIterator<String> it = shortestPath.listIterator(); if(it.hasNext()){ String sourceErg = it.next();; while (it.hasNext()){ String targetErg = it.next(); retVal.add(getjGraph().getEdge(sourceErg, targetErg)); sourceErg = targetErg; } }else{ return null; } return retVal; } } /** * Finds the Shortest way from source to target, * returns null if not reachable, * else it returns the way from source to target */ public List<String> shortesPathBroadStringList(String source, String target) { ArrayList<ArrayList<String>> wayList = new ArrayList<>(); Set<String> visitedVertexes = new HashSet<>(); long startime = System.nanoTime(); int hops = 0; if (source.equals(target)){ sendMessage("Source == Target"); ArrayList<String> retVal = new ArrayList<>(); retVal.add(source); return retVal; } { ArrayList<String> actualWay = new ArrayList<>(); actualWay.add(source); wayList.add(actualWay); visitedVertexes.add(source); } while (!wayList.isEmpty()){ ArrayList<ArrayList<String>> tmpWaylist = new ArrayList<>(); for(ArrayList<String> actualWay : wayList){ String lastNode = actualWay.get(actualWay.size() - 1); for(GKAEdge edge : getAccessibleEdges(lastNode)){ ArrayList<String> tmpActualWay = new ArrayList<>(actualWay); String nextNode = moveEdge(edge, lastNode); tmpActualWay.add(nextNode); hops = hops + 1; if(nextNode.equals(target)){ long timeNeeded = (System.nanoTime() - startime); sendMessage("Found Way: " + tmpActualWay); sendMessage("Kantenzahl: " + (tmpActualWay.size() - 1)); sendMessage("Hops: " + hops); sendMessage("Time: " + timeNeeded + " NanoSec"); return tmpActualWay; } else{ if(!visitedVertexes.contains(nextNode)){ visitedVertexes.add(nextNode); tmpWaylist.add(tmpActualWay); } } } } wayList = tmpWaylist; } long timeNeeded = (System.nanoTime() - startime); sendMessage("Found no way!"); sendMessage("Hops: " + hops); sendMessage("Time: " + timeNeeded + " NanoSec"); return null; } /** * Returns the TargetVertex by moving an edge Starting at a Source * @param edge * @param source * @return */ private String moveEdge(GKAEdge edge, String source){ if(edge.getSource().equals(source)){ return edge.getTarget().toString(); }else{ return edge.getSource().toString(); } } /** * Returns a set of edges which are accessible from a specified * source * @param source * @return */ private Set<GKAEdge> getAccessibleEdges(String source){ Set<GKAEdge> edges = new HashSet<>(getjGraph().edgesOf(source)); Set<GKAEdge> notGoable = new HashSet<>(); for (GKAEdge edge : edges) { if(!isEdgeAccessible(edge, source)){ notGoable.add(edge); } } edges.removeAll(notGoable); return edges; } /** * Returns true or false if an Edge is accessible by Starting * from a specified source * @param edge * @param source * @return */ private boolean isEdgeAccessible(GKAEdge edge, String source){ if(edge.getSource().equals(source)){ return true; }else if(!isDirected() && edge.getTarget().equals(source)){ return true; }else{ return false; } } public boolean equals(Object object) { if(object == null){ return false; } else if(object == this){ return true; } else if(!(object instanceof GKAGraphInterface)){ return false; } else{ GKAGraphInterface graph = (GKAGraphInterface) object; return (graph.getType().equals(this.getType()) && graph.getjGraph().edgeSet().equals(this.getjGraph().edgeSet()) && graph.getjGraph().vertexSet().equals(this.getjGraph().vertexSet())); } } public int hashCode(){ return 31 + getjGraph().edgeSet().hashCode() + getjGraph().vertexSet().hashCode(); } public String toString() { return getjGraph().toString(); } @Override public void addMessageReceiver(MessageReceiver messageReceiver) { messageReceivers.add(messageReceiver); } private void sendMessage(String message){ for (MessageReceiver messageReceiver : messageReceivers){ messageReceiver.receiveMessage(message); } } @Override public List<GKAEdge> dijkstra(String source, String target) { List<String> shortestPath = dijkstraStringList(source, target); if(shortestPath == null || shortestPath.size() < 2){ return null; } else{ ArrayList<GKAEdge> retVal = new ArrayList<>(); ListIterator<String> it = shortestPath.listIterator(); if(it.hasNext()){ String sourceErg = it.next();; while (it.hasNext()){ String targetErg = it.next(); GKAEdge shortestesEdgeBetween = null; for (GKAEdge edge : getjGraph().getAllEdges(sourceErg, targetErg)){ if (shortestesEdgeBetween == null || shortestesEdgeBetween.getWeight() > edge.getWeight()) shortestesEdgeBetween = edge; } retVal.add(shortestesEdgeBetween); sourceErg = targetErg; } }else{ return null; } return retVal; } } // //public List<String> dijkstraStringList(String source, String target) { // ArrayList<ArrayList<String>> wayList = new ArrayList<>(); // Set<String> visitedVertexes = new HashSet<>(); // HashMap<ArrayList<String>, Double> actualWeight = new HashMap<>(); // Set<HashMap<ArrayList<String>, Double>> setOfWeights = new HashSet<>(); // // long startime = System.nanoTime(); // // int hops = 0; // // if (isWeighted() == false) // { // return shortesPathBroadStringList(source, target); // } // else // if (source.equals(target)){ // MainControler.sendMessage("Source == Target"); // ArrayList<String> retVal = new ArrayList<>(); // retVal.add(source); // return retVal; // } // // { // ArrayList<String> actualWay = new ArrayList<>(); // actualWay.add(source); // wayList.add(actualWay); // visitedVertexes.add(source); // actualWeight.put(actualWay, 0.0); // setOfWeights.add(actualWeight); // // } // // Double smallestWeight = 0.0; // // while (!wayList.isEmpty()){ // ArrayList<ArrayList<String>> tmpWaylist = new ArrayList<>(); // for(ArrayList<String> actualWay : wayList){ // String lastNode = actualWay.get(actualWay.size() - 1); // for(GKAEdge edge : getAccessibleEdges(lastNode)){ // ArrayList<String> tmpActualWay = new ArrayList<>(actualWay); // String nextNode = moveEdge(edge, lastNode); // actualWeight.put(tmpActualWay, edge.getWeight() + (actualWeight.get(actualWay) == null ? 0.0 : actualWeight.get(actualWay))); // setOfWeights.add(actualWeight); // for (HashMap<ArrayList<String>, Double> edgeWeights : setOfWeights) // { // for (ArrayList<String> path : edgeWeights.keySet()) // { // if ((path.get(path.size() - 1)) == nextNode) // { // smallestWeight = edgeWeights.get(path); // // if (smallestWeight <= actualWeight.get(tmpActualWay)) // { // actualWay = tmpActualWay; // } // // } // } // // } // // //hops = hops + 1; // if(tmpActualWay.get(tmpActualWay.size() - 1).equals(target)){ // long timeNeeded = (System.nanoTime() - startime); // MainControler.sendMessage("Weight of shortest way: " + smallestWeight); // MainControler.sendMessage("Found Way: " + tmpActualWay); // // MainControler.sendMessage("Hops: " + hops); // MainControler.sendMessage("Time: " + timeNeeded + " NanoSec"); // return tmpActualWay; // } // else{ // tmpActualWay.add(nextNode); // if(!visitedVertexes.contains(nextNode)){ // visitedVertexes.add(nextNode); // tmpWaylist.add(actualWay); // } // } // } // // } // wayList = tmpWaylist; // } // long timeNeeded = (System.nanoTime() - startime); // MainControler.sendMessage("Found no way!"); // // MainControler.sendMessage("Hops: " + hops); // MainControler.sendMessage("Time: " + timeNeeded + " NanoSec"); // return null; // } public List<String> dijkstraStringList(String source, String target) { HashMap<ArrayList<String>, Double> wayList = new HashMap<>(); HashMap<String, Double> visitedVertexes = new HashMap<>(); long startime = System.nanoTime(); int hops = 0; if (source.equals(target)){ MainControler.sendMessage("Source == Target"); ArrayList<String> retVal = new ArrayList<>(); retVal.add(source); return retVal; } { ArrayList<String> actualWay = new ArrayList<>(); actualWay.add(source); wayList.put(actualWay, 0.0); visitedVertexes.put(source, 0.0); } ArrayList<String> shortesPath = null; Double shortestWeight = Double.POSITIVE_INFINITY; while (!wayList.isEmpty()){ Map.Entry<ArrayList<String>, Double> actualWay = null; for(Map.Entry<ArrayList<String>, Double> shortestWay : wayList.entrySet()){ if(actualWay == null || actualWay.getValue() < shortestWay.getValue()) { actualWay = shortestWay; } } wayList.remove(actualWay.getKey()); String lastNode = actualWay.getKey().get(actualWay.getKey().size() - 1); for(GKAEdge edge : getAccessibleEdges(lastNode)){ ArrayList<String> tmpActualWay = new ArrayList<>(actualWay.getKey()); String nextNode = moveEdge(edge, lastNode); tmpActualWay.add(nextNode); hops = hops + 1; if(nextNode.equals(target)){ if((edge.getWeight() + actualWay.getValue()) < shortestWeight) { shortestWeight = edge.getWeight() + actualWay.getValue(); shortesPath = tmpActualWay; } } else{ if(edge.getWeight() + actualWay.getValue() < shortestWeight) { if(!visitedVertexes.containsKey(nextNode)){ visitedVertexes.put(nextNode, edge.getWeight() + actualWay.getValue()); wayList.put(tmpActualWay, edge.getWeight() + actualWay.getValue()); } else { if(visitedVertexes.get(nextNode) > (edge.getWeight() + actualWay.getValue())) { for (Map.Entry<ArrayList<String>, Double> path : wayList.entrySet()) { if ((path.getKey().get(path.getKey().size() - 1)) == nextNode) { wayList.remove(path.getKey()); break; } } visitedVertexes.put(nextNode, edge.getWeight() + actualWay.getValue()); wayList.put(tmpActualWay, edge.getWeight() + actualWay.getValue()); } } } } } } long timeNeeded = (System.nanoTime() - startime); // if (shortesPath == null || shortesPath.size() < 2){ // sendMessage("Found no way!"); // } // else { // sendMessage("Found way: " + shortesPath.toString()); // sendMessage("Weight of shortest way: " + shortestWeight); // } // sendMessage("Hops: " + hops); // sendMessage("Time: " + timeNeeded + " NanoSec"); return shortesPath; } @Override public List<GKAEdge> floydWarschall(String source, String target) { if (source == null || target == null || !getjGraph().containsVertex(source) || !getjGraph().containsVertex(target)){ throw new IllegalArgumentException(); } long startime = System.nanoTime(); if (warschallMatrix == null){ Matrix<String, Set<GKAEdge>> floydMatrix = generateFloydMatrix(); warschallMatrix = generateWarschalMatrix(floydMatrix); } sendMessage("Benoetigte Zeit: " + (System.nanoTime() - startime) + " nanosec." ); sendMessage("Anzahl der Kanten auf dem Weg: " + warschallMatrix.get(source, target).size()); if (warschallMatrix.get(source, target).equals(new HashSet<>(Arrays.asList(new GKAEdge(null, 0.0, 0))))){ return null; } return new ArrayList<>(warschallMatrix.get(source, target)); } private Matrix<String, Set<GKAEdge>> generateWarschalMatrix(Matrix<String, Set<GKAEdge>> floydMatrix) { Matrix<String, Set<GKAEdge>> retVal = new Matrix<>(floydMatrix); long hops = 0; for (String j : retVal.getColumns()){ for (String i : retVal.getRows()){ Set<GKAEdge> way1= retVal.get(i,j); if (way1 != null){ for(String k : retVal.getColumns()){ Set<GKAEdge> way2 = retVal.get(j, k); if(way2 != null){ Set<GKAEdge> newWay = addWays(way1, way2); if(retVal.get(i, k) == null || getWayLength(retVal.get(i, k)) > getWayLength(newWay)){ retVal.put(i, k, newWay); hops++; } } } } } } sendMessage("Created Warschall Matrix with: " + hops + " hops."); return retVal; } private Matrix<String, Set<GKAEdge>> generateFloydMatrix(){ Matrix<String, Set<GKAEdge>> retVal = new Matrix<>(getjGraph().vertexSet(), getjGraph().vertexSet()); long hops = 0 ; for(String row : retVal.getRows()){ for(String column : retVal.getColumns()){ if (row.equals(column)){ HashSet<GKAEdge> tmpSet = new HashSet<>(); tmpSet.add(new GKAEdge(null, 0.0, 0)); retVal.put(row, column, tmpSet); }else{ for(GKAEdge edge : getjGraph().getAllEdges(row, column)){ if (retVal.get(row, column) == null || getWayLength(retVal.get(row, column)) > edge.getWeight()){ HashSet<GKAEdge> tmpSet = new HashSet<>(); tmpSet.add(edge); retVal.put(row, column, tmpSet); if (row.equals(column) && getWayLength(tmpSet) < 0) throw new IllegalArgumentException("A negativ Circle is detected"); hops++; } } } } } sendMessage("Created Floyd Matrix with: " + hops + " hops."); return retVal; } private double getWayLength(Set<GKAEdge> way){ double retval = 0.0; for(GKAEdge edge : way){ retval += edge.getWeight(); } return retval; } private Set<GKAEdge> addWays(Set<GKAEdge> way1, Set<GKAEdge> way2){ HashSet<GKAEdge> retVal = new HashSet<>(way1); retVal.addAll(way2); return retVal; } @Override public void fordFulkerson(String source, String sink){ FordFulkerson fordFulkerson = new FordFulkerson(this); sendMessage("Max blow between \"" + source + "\" and \"" + sink +"\": " + fordFulkerson.maxFlow(source, sink)); sendMessage("Runtime: " + fordFulkerson.getRunTime()); sendMessage("Zugriffe: " + fordFulkerson.getHops()); } @Override public void edmondKarp(String source, String sink) { EdmondKarp edmondKarp = new EdmondKarp(this); sendMessage("Max blow between \"" + source + "\" and \"" + sink +"\": " + edmondKarp.maxFlow(source, sink)); sendMessage("Runtime: " + edmondKarp.getRunTime()); sendMessage("Zugriffe: " + edmondKarp.getHops()); } @Override public MinimumSpanningTree getMinimumSpanningTree() { return (new MinimumSpanningTree(this)); } @Override public MSTHeuristic getMSTHeuristic(String startNode) { MSTHeuristic heuristic = new MSTHeuristic(this,startNode); sendMessage("MSTHeuristic Tour: " + heuristic.getWay()); sendMessage("MSTHeuristic Size: " + heuristic.getLength()); sendMessage("MSTHeuristic Time: " + heuristic.getRunTime() + " NanoSekunden"); return (heuristic); } @Override public NearestNeighbour getNearestNeighbour(String startNode) { NearestNeighbour heuristic = new NearestNeighbour(this,startNode); sendMessage("NearestNeighbour Tour: " + heuristic.getWay()); sendMessage("NearestNeighbour Size: " + heuristic.getLength()); sendMessage("NearestNeighbour Time: " + heuristic.getRunTime() + " NanoSekunden"); return (heuristic); } }