Skip to content
Snippets Groups Projects
Commit b7c70010 authored by kraleva's avatar kraleva
Browse files

add the largest connected component code

parent b9ec71b2
Branches
No related tags found
1 merge request!26Add LLC
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
<dependency> <dependency>
<groupId>de.fuberlin.navigator</groupId> <groupId>de.fuberlin.navigator</groupId>
<artifactId>proto</artifactId> <artifactId>proto</artifactId>
<version>1.00.06</version> <version>1.00.08</version>
</dependency> </dependency>
</dependencies> </dependencies>
......
package map.builder; package map.builder;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import org.json.JSONArray; import org.json.JSONArray;
import de.fuberlin.navigator.protos.map_builder.RoadNetwork; import de.fuberlin.navigator.protos.map_builder.RoadNetwork;
import map.builder.osm.OSMConnectedComponentParser;
import map.builder.osm.OSMFetcher; import map.builder.osm.OSMFetcher;
import map.builder.osm.OSMParser; import map.builder.osm.OSMParser;
import map.builder.utilities.BoundingBox; import map.builder.utilities.BoundingBox;
import map.builder.utilities.ConnectedComponentGraph;
import map.builder.utilities.FileHandler; import map.builder.utilities.FileHandler;
public class App { public class App {
...@@ -46,6 +49,23 @@ public class App { ...@@ -46,6 +49,23 @@ public class App {
parser.parseTurnRestrictions(restrictions); parser.parseTurnRestrictions(restrictions);
parser.parseRoads(roads); parser.parseRoads(roads);
// set it to 0 so that it can be collected by garbage collector
restrictions = null;
roads = null;
bbox = null;
parser = null;
// create the nodes graph in order to run LCC on it
ConnectedComponentGraph graph = new ConnectedComponentGraph();
OSMConnectedComponentParser.addNodes(roadNetworkBuilder, graph);
OSMConnectedComponentParser.addEdges(roadNetworkBuilder, graph);
ArrayList<Long> component = graph.getSCCs();
System.out.println(component.toString());
// cleanup
graph = null;
RoadNetwork roadNetwork = roadNetworkBuilder.build(); RoadNetwork roadNetwork = roadNetworkBuilder.build();
System.out.println("Turn restrictions count: " + roadNetwork.getTurnRestrictionsCount()); System.out.println("Turn restrictions count: " + roadNetwork.getTurnRestrictionsCount());
System.out.println("Nodes count: " + roadNetwork.getNodesCount()); System.out.println("Nodes count: " + roadNetwork.getNodesCount());
......
package map.builder.osm;
import de.fuberlin.navigator.protos.map_builder.RoadNetwork;
import de.fuberlin.navigator.protos.map_builder.Segment;
import map.builder.utilities.ConnectedComponentGraph;
public class OSMConnectedComponentParser {
public static void addNodes(RoadNetwork.Builder roadnetwowrBuilder, ConnectedComponentGraph graph) {
for (Long nodeId : roadnetwowrBuilder.getNodesMap().keySet()) {
graph.addNode(nodeId);
}
}
public static void addEdges(RoadNetwork.Builder roadnetworkbuilder, ConnectedComponentGraph graph) {
for (Long edgeId : roadnetworkbuilder.getSegmentsMap().keySet()) {
Segment segment = roadnetworkbuilder.getSegmentsMap().get(edgeId);
Long startNode = segment.getStartNode();
Long endNode = segment.getEndNode();
graph.addEdge(startNode, endNode);
if (!segment.getOneWay()) {
graph.addEdge(endNode, startNode);
}
}
}
}
\ No newline at end of file
...@@ -2,8 +2,6 @@ package map.builder.osm; ...@@ -2,8 +2,6 @@ package map.builder.osm;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
...@@ -18,7 +16,7 @@ import map.builder.utilities.ComputationalUtils; ...@@ -18,7 +16,7 @@ import map.builder.utilities.ComputationalUtils;
public class OSMParser { public class OSMParser {
private final Coordinates.Builder coordinatesBuilder; private final Coordinates.Builder coordinatesBuilder;
private final HashMap<Long, Node> nodesDump; private final HashMap<Long, Node> nodesDump;
RoadNetwork.Builder roadNetworkBuilder; public RoadNetwork.Builder roadNetworkBuilder;
public OSMParser(RoadNetwork.Builder roadNetworkBuilder) { public OSMParser(RoadNetwork.Builder roadNetworkBuilder) {
this.roadNetworkBuilder = roadNetworkBuilder; this.roadNetworkBuilder = roadNetworkBuilder;
...@@ -49,6 +47,7 @@ public class OSMParser { ...@@ -49,6 +47,7 @@ public class OSMParser {
this.splitSegment(element); this.splitSegment(element);
} }
} }
} }
private void splitSegment(JSONObject element) { private void splitSegment(JSONObject element) {
...@@ -72,8 +71,7 @@ public class OSMParser { ...@@ -72,8 +71,7 @@ public class OSMParser {
try { try {
line = this.findNodePositions(geometry); line = this.findNodePositions(geometry);
} } catch (NullPointerException e) {
catch (NullPointerException e) {
System.out.println("Dropping segment with ID " + osmId); System.out.println("Dropping segment with ID " + osmId);
System.out.println(e.getMessage()); System.out.println(e.getMessage());
return; return;
...@@ -86,7 +84,9 @@ public class OSMParser { ...@@ -86,7 +84,9 @@ public class OSMParser {
int maxSpeed = SegmentUtils.getMaxSpeed(element); int maxSpeed = SegmentUtils.getMaxSpeed(element);
System.out.printf("Max speed: %d \n", maxSpeed); System.out.printf("Max speed: %d \n", maxSpeed);
System.out.printf("Way id: %d, Start node id : %d, End node id: %d \n", osmId, startNodeId, endNodeId); System.out.printf("Way id: %d, Start node id : %d, End node id: %d \n", osmId,
this.roadNetworkBuilder.getNodesMap().get(startNodeId).getId(),
this.roadNetworkBuilder.getNodesMap().get(endNodeId).getId());
long internalId = this.roadNetworkBuilder.getSegmentsCount(); long internalId = this.roadNetworkBuilder.getSegmentsCount();
...@@ -113,7 +113,7 @@ public class OSMParser { ...@@ -113,7 +113,7 @@ public class OSMParser {
private void moveNodeToProto(Node node) { private void moveNodeToProto(Node node) {
long osmId = node.getOsmId(); long osmId = node.getOsmId();
this.roadNetworkBuilder.putNodes(osmId, node); this.roadNetworkBuilder.putNodes(node.getOsmId(), node);
} }
private void createNode(JSONObject element) { private void createNode(JSONObject element) {
...@@ -121,7 +121,7 @@ public class OSMParser { ...@@ -121,7 +121,7 @@ public class OSMParser {
long osmId = element.getLong(OSMKey.id.name()); long osmId = element.getLong(OSMKey.id.name());
Node node = Node.newBuilder() Node node = Node.newBuilder()
.setId(this.roadNetworkBuilder.getNodesCount()) .setId(this.roadNetworkBuilder.getNodesCount() + this.nodesDump.size())
.setOsmId(osmId) .setOsmId(osmId)
.setPosition(position) .setPosition(position)
.build(); .build();
...@@ -143,8 +143,10 @@ public class OSMParser { ...@@ -143,8 +143,10 @@ public class OSMParser {
} }
/** /**
* Returns an array list of array lists of geometries. If the outer list has only one entry, it means the segment * Returns an array list of array lists of geometries. If the outer list has
* only one entry, it means the segment
* doesn't need to be split, otherwise it needs to. * doesn't need to be split, otherwise it needs to.
*
* @param nodeIds * @param nodeIds
* @return * @return
* @throws NullPointerException * @throws NullPointerException
...@@ -176,7 +178,6 @@ public class OSMParser { ...@@ -176,7 +178,6 @@ public class OSMParser {
private Node findParsedNodeById(long osmId) throws NullPointerException { private Node findParsedNodeById(long osmId) throws NullPointerException {
if (this.nodesDump.containsKey(osmId)) { if (this.nodesDump.containsKey(osmId)) {
Node node = this.nodesDump.get(osmId); Node node = this.nodesDump.get(osmId);
return node; return node;
} }
......
...@@ -3,8 +3,6 @@ package map.builder.utilities; ...@@ -3,8 +3,6 @@ package map.builder.utilities;
import de.fuberlin.navigator.protos.map_builder.Coordinates; import de.fuberlin.navigator.protos.map_builder.Coordinates;
public class ComputationalUtils { public class ComputationalUtils {
private ComputationalUtils() {
}
public static double haversine(Coordinates position_0, public static double haversine(Coordinates position_0,
de.fuberlin.navigator.protos.map_builder.Coordinates position_1) { de.fuberlin.navigator.protos.map_builder.Coordinates position_1) {
......
package map.builder.utilities; package map.builder.utilities;
import java.util.ArrayList;
import java.util.HashMap;
// Code from : https://www.geeksforgeeks.org/strongly-connected-components/ // Code from : https://www.geeksforgeeks.org/strongly-connected-components/
// Java implementation of Kosaraju's algorithm to print all SCCs // Java implementation of Kosaraju's algorithm to print all SCCs
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Stack; import java.util.Stack;
//TODO: change data structure here to be more appropriate
// This class represents a directed ConnectedComponentGraph using adjacency list // This class represents a directed ConnectedComponentGraph using adjacency list
// representation // representation
class ConnectedComponentGraph { public class ConnectedComponentGraph {
private int V; // No. of vertices private HashMap<Long, LinkedList<Long>> adj; // Adjacency List
private LinkedList<Integer> adj[]; // Adjacency List
// Constructor // Constructor
ConnectedComponentGraph(int v) { public ConnectedComponentGraph() {
V = v; adj = new HashMap<Long, LinkedList<Long>>();
adj = new LinkedList[v]; }
for (int i = 0; i < v; ++i)
adj[i] = new LinkedList<Integer>(); public void addNode(Long v) {
adj.put(v, new LinkedList<Long>());
} }
// Function to add an edge into the ConnectedComponentGraph // Function to add an edge into the ConnectedComponentGraph
public void addEdge(int v, int w) { public void addEdge(Long v, Long w) {
adj[v].add(w); adj.get(v).add(w);
} }
// A recursive function to print DFS starting from v // A recursive function to print DFS starting from v
public void DFSUtil(int v, boolean visited[]) { public ArrayList<Long> DFSUtil(Long v, HashMap<Long, Boolean> visited) {
// Mark the current node as visited and print it // Mark the current node as visited and print it
visited[v] = true; visited.put(v, true);
System.out.print(v + " ");
int n; ArrayList<Long> component = new ArrayList<Long>();
Long n;
// Recur for all the vertices adjacent to this vertex // Recur for all the vertices adjacent to this vertex
Iterator<Integer> i = adj[v].iterator(); Iterator<Long> i = adj.get(v).iterator();
while (i.hasNext()) { while (i.hasNext()) {
n = i.next(); n = i.next();
if (!visited[n]) if (!visited.get(n))
DFSUtil(n, visited); component = DFSUtil(n, visited, component);
} }
component.add(v);
return component;
}
public ArrayList<Long> DFSUtil(Long v, HashMap<Long, Boolean> visited, ArrayList<Long> list) {
// Mark the current node as visited and print it
visited.put(v, true);
Long n;
// Recur for all the vertices adjacent to this vertex
Iterator<Long> i = adj.get(v).iterator();
while (i.hasNext()) {
n = i.next();
if (!visited.get(n))
DFSUtil(n, visited, list);
}
list.add(v);
return list;
} }
// Function that returns reverse (or transpose) of this ConnectedComponentGraph // Function that returns reverse (or transpose) of this ConnectedComponentGraph
public ConnectedComponentGraph getTranspose() { public ConnectedComponentGraph getTranspose() {
ConnectedComponentGraph g = new ConnectedComponentGraph(V); ConnectedComponentGraph g = new ConnectedComponentGraph();
for (int v = 0; v < V; v++) { for (Long v : adj.keySet()) {
g.addNode(v);
}
for (Long v : adj.keySet()) {
// Recur for all the vertices adjacent to this vertex // Recur for all the vertices adjacent to this vertex
Iterator<Integer> i = adj[v].listIterator(); Iterator<Long> i = adj.get(v).listIterator();
while (i.hasNext()) while (i.hasNext()) {
g.adj[i.next()].add(v); Long next = i.next();
g.adj.get(next).add(v);
}
} }
return g; return g;
} }
public void fillOrder(int v, boolean visited[], Stack<Integer> stack) { public void fillOrder(Long v, HashMap<Long, Boolean> visited, Stack<Long> stack) {
// Mark the current node as visited and print it // Mark the current node as visited and print it
visited[v] = true; visited.put(v, true);
// Recur for all the vertices adjacent to this vertex // Recur for all the vertices adjacent to this vertex
Iterator<Integer> i = adj[v].iterator(); Iterator<Long> i = adj.get(v).iterator();
while (i.hasNext()) { while (i.hasNext()) {
int n = i.next(); Long n = i.next();
if (!visited[n]) if (!visited.get(n))
fillOrder(n, visited, stack); fillOrder(n, visited, stack);
} }
...@@ -73,53 +99,67 @@ class ConnectedComponentGraph { ...@@ -73,53 +99,67 @@ class ConnectedComponentGraph {
// The main function that finds and prints all strongly // The main function that finds and prints all strongly
// connected components // connected components
public void printSCCs() { public ArrayList<Long> getSCCs() {
Stack<Integer> stack = new Stack<Integer>(); Stack<Long> stack = new Stack<Long>();
// Mark all the vertices as not visited (For first DFS) // Mark all the vertices as not visited (For first DFS)
boolean visited[] = new boolean[V]; HashMap<Long, Boolean> visited = new HashMap<Long, Boolean>();
for (int i = 0; i < V; i++) for (Long i : this.adj.keySet()) {
visited[i] = false; visited.put(i, false);
}
// Fill vertices in stack according to their finishing // Fill vertices in stack according to their finishing
// times // times
for (int i = 0; i < V; i++) for (Long i : this.adj.keySet())
if (visited[i] == false) if (visited.get(i) == false)
fillOrder(i, visited, stack); fillOrder(i, visited, stack);
// Create a reversed ConnectedComponentGraph // Create a reversed ConnectedComponentGraph
ConnectedComponentGraph gr = getTranspose(); ConnectedComponentGraph gr = getTranspose();
// Mark all the vertices as not visited (For second DFS) // Mark all the vertices as not visited (For second DFS)
for (int i = 0; i < V; i++) for (Long i : this.adj.keySet())
visited[i] = false; visited.put(i, false);
// Now process all vertices in order defined by Stack // Now process all vertices in order defined by Stack
ArrayList<Long> largestComponent = new ArrayList<Long>();
int maxLength = 0;
while (stack.empty() == false) { while (stack.empty() == false) {
// Pop a vertex from stack // Pop a vertex from stack
int v = (int) stack.pop(); Long v = stack.pop();
// Print Strongly connected component of the popped vertex // Print Strongly connected component of the popped vertex
if (visited[v] == false) { if (visited.get(v) == false) {
gr.DFSUtil(v, visited); ArrayList<Long> component = gr.DFSUtil(v, visited);
System.out.println(); if (maxLength < component.size()) {
maxLength = component.size();
largestComponent = component;
}
} }
} }
return largestComponent;
} }
// Driver method // Driver method
public static void main(String args[]) { public static void main(String args[]) {
// Create a ConnectedComponentGraph given in the above diagram // Create a ConnectedComponentGraph given in the above diagram
ConnectedComponentGraph g = new ConnectedComponentGraph(5); ConnectedComponentGraph g = new ConnectedComponentGraph();
g.addEdge(1, 0); // add nodes
g.addEdge(0, 2); g.addNode((long) 0);
g.addEdge(2, 1); g.addNode((long) 1);
g.addEdge(0, 3); g.addNode((long) 2);
g.addEdge(3, 4); g.addNode((long) 3);
g.addNode((long) 4);
g.addEdge((long) 1, (long) 0);
g.addEdge((long) 0, (long) 2);
g.addEdge((long) 2, (long) 1);
g.addEdge((long) 0, (long) 3);
g.addEdge((long) 3, (long) 4);
System.out.println("Following are strongly connected components " + System.out.println("Following are strongly connected components " +
"in given ConnectedComponentGraph "); "in given ConnectedComponentGraph ");
g.printSCCs(); g.getSCCs();
} }
} }
// This code is contributed by Aakash Hasija // This code is contributed by Aakash Hasija
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment