package GKA.Graph; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; public class MSTHeuristic { private final GKAGraphInterface dupGraph; private final GKAGraphInterface tour; private List<String> way = new ArrayList<>(); private double length = 0.0; private long runTime = 0; public List<String> getWay() { return way; } public double getLength() { return length; } public long getRunTime() { return runTime; } public MSTHeuristic(GKAGraphInterface graph, String startNode){ long startTime = System.nanoTime(); if(graph.getjGraph().vertexSet().size() < 2 ){ way = new ArrayList<>(graph.getjGraph().vertexSet().size()); dupGraph = graph; tour = graph; }else{ dupGraph = generateDuplicatedGraph(graph.getMinimumSpanningTree()); tour = generateTour(graph, dupGraph,startNode); } runTime = System.nanoTime() - startTime; } private GKAGraphInterface generateTour(GKAGraphInterface graph, GKAGraphInterface dupGraph, String startnode) { GKAGraphInterface tour = GKAGraphInterface.newGraph(GraphType.UndirectedWeighted); List<String> way = new ArrayList<>(); way.add(startnode); Set<GKAEdge> movedEdges = new HashSet<>(); Set<GKAEdge> movableEdges = findMovableEdges(startnode, movedEdges, dupGraph); while(!movableEdges.isEmpty()){ GKAEdge nextEdge = null; for(GKAEdge edge: movableEdges){ nextEdge = edge; if(!way.contains(nextEdge.getTarget())){ break; } } movedEdges.add(nextEdge); String nextnode = nextEdge.getTarget().toString(); way.add(nextnode); movableEdges = findMovableEdges(nextnode, movedEdges, dupGraph); startnode = nextnode; } Iterator<String> it = way.iterator(); String currentNode = it.next(); this.way.add(currentNode); while(it.hasNext()){ String nextNode = it.next(); if(!this.way.contains(nextNode)){ this.way.add(nextNode); double currentWayLength = 0.0; for(GKAEdge edge: graph.dijkstra(currentNode, nextNode)){ currentWayLength += edge.getWeight(); } tour.addEdge(currentNode, nextNode, null, currentWayLength); this.length += currentWayLength; currentNode = nextNode; } } this.way.add(startnode); double currentWayLength = 0.0; for(GKAEdge edge: graph.dijkstra(currentNode, startnode)){ currentWayLength += edge.getWeight(); } tour.addEdge(currentNode, startnode, null, currentWayLength); this.length += currentWayLength; return tour; } private Set<GKAEdge> findMovableEdges(String node, Set<GKAEdge> movedEdges, GKAGraphInterface dupGraph){ Set<GKAEdge> retVal = new HashSet<>(dupGraph.getjGraph().edgesOf(node)); Set<GKAEdge> removeEdges = new HashSet<>(movedEdges); for(GKAEdge edge: retVal){ if(!edge.getSource().equals(node)){ removeEdges.add(edge); } } retVal.removeAll(removeEdges); return retVal; } private GKAGraphInterface generateDuplicatedGraph(MinimumSpanningTree graph){ GKAGraphInterface dupGraph = GKAGraphInterface.newGraph(GraphType.DirectedWeighted); for(GKAEdge edge: graph.getEdgeSet()){ dupGraph.addEdge(edge.getSource().toString(), edge.getTarget().toString(), null, edge.getWeight()); dupGraph.addEdge(edge.getTarget().toString(), edge.getSource().toString(), null, edge.getWeight()); } return dupGraph; } public GKAGraphInterface getTour(){ return tour; } }