Skip to content

Commit

Permalink
#28 drastically increased performance of sort-based algorithms
Browse files Browse the repository at this point in the history
this covers both the sort-based isomorphism checks themselves and the
sort-based reachability graph calculation, too - making this variant the
most effective one for the full-size RoadworkExample (and every bigger
reachability graph)
  • Loading branch information
hoechp committed Feb 25, 2017
1 parent db6f64e commit 8185973
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 21 deletions.
64 changes: 50 additions & 14 deletions src/main/java/org/fujaba/graphengine/PatternEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,16 @@ public static Graph calculateReachabilityGraph(Graph graph, ArrayList<ArrayList<
*/

// the first rg-node is the base-graph:
if (GraphEngine.getMainIsomorphismHandler() instanceof IsomorphismHandlerSorting) {
graph = GraphEngine.getMainIsomorphismHandler().normalized(graph);
}
Graph rg = new Graph().addNode(new Node().setAttribute("graph", graph.toString()));
ArrayList<Graph> added = new ArrayList<Graph>(); // a list with graphs that were added
ArrayList<Graph> unprocessed = new ArrayList<Graph>(); // a list with currently unprocessed graphs
added.add(graph);
unprocessed.add(graph);

if (GraphEngine.getMainIsomorphismHandler() instanceof IsomorphismHandlerSorting) {
return calculateReachabilityGraphWithNormalForm(graph, patterns);
}

// as long as a single graph wasn't checked for successors, the search continues:
while (unprocessed.size() > 0) {
// looking for matches:
Expand All @@ -108,13 +109,7 @@ public static Graph calculateReachabilityGraph(Graph graph, ArrayList<ArrayList<
// construct the graph, that's the result of this match:
Graph successor = applyMatch(match);
// check if the graph was previously added:
int index = -1;
if (GraphEngine.getMainIsomorphismHandler() instanceof IsomorphismHandlerSorting) {
successor = GraphEngine.getMainIsomorphismHandler().normalized(successor);
index = normalizedIndexOf(added, successor);
} else {
index = indexOf(added, successor);
}
int index = indexOf(added, successor);
if (index != -1) {
// yes, the graph already did exist => just build edge to an existing node
Node target = findGraphInReachabilityGraph(rg, successor);
Expand All @@ -133,6 +128,47 @@ public static Graph calculateReachabilityGraph(Graph graph, ArrayList<ArrayList<
// done
return rg;
}

public static Graph calculateReachabilityGraphWithNormalForm(Graph graph, ArrayList<ArrayList<PatternGraph>> patterns) {
// the first rg-node is the base-graph:
graph = GraphEngine.getMainIsomorphismHandler().normalized(graph);
Graph rg = new Graph().addNode(new Node().setAttribute("graph", graph.toString()));
ArrayList<Graph> added = new ArrayList<Graph>(); // a list with graphs that were added
ArrayList<Graph> unprocessed = new ArrayList<Graph>(); // a list with currently unprocessed graphs
added.add(graph);
unprocessed.add(graph);
// as long as a single graph wasn't checked for successors, the search continues:
while (unprocessed.size() > 0) {
// looking for matches:
ArrayList<Match> matches = calculateReachabilityNodeMatches(unprocessed.get(0), patterns);
// look up the rg-node, that represents the unprocessed graph:
Node source = findGraphInReachabilityGraph(rg, unprocessed.get(0));
unprocessed.remove(0);
// now handle matches:
for (Match match: matches) {
// construct the graph, that's the result of this match:
Graph successor = applyMatch(match);
// check if the graph was previously added:
successor = GraphEngine.getMainIsomorphismHandler().normalized(successor);
String serializedGraph = successor.toString();
int index = normalizedIndexOf(rg.getNodes(), serializedGraph);
if (index != -1) {
// yes, the graph already did exist => just build edge to an existing node
Node target = rg.getNodes().get(index);
source.addEdge(match.getPattern().toString(), target); // new edge
} else {
// no, the graph didn't exist before => add a new node
Node target = new Node().setAttribute("graph", serializedGraph); // new node
rg.addNode(target);
source.addEdge(match.getPattern().toString(), target); // edge to new node
added.add(successor);
unprocessed.add(successor);
}
}
}
// done
return rg;
}

/**
* Function to find a graph as a node inside of a reachability graph.
Expand Down Expand Up @@ -193,10 +229,10 @@ private static int indexOf(ArrayList<Graph> graphs, Graph graph) {
return -1;
}

private static int normalizedIndexOf(ArrayList<Graph> graphs, Graph graph) {
for (int i = 0; i < graphs.size(); ++i) {
Graph g = graphs.get(i);
if (g.toString().equals(graph.toString())) {
private static int normalizedIndexOf(ArrayList<Node> nodes, String serializedGraph) {
for (int i = 0; i < nodes.size(); ++i) {
Node n = nodes.get(i);
if (n.getAttribute("graph").equals(serializedGraph)) {
return i;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,43 @@ public Graph normalized(Graph graph) {
nodeSortTrees.add(new NodeSortTree(graph, node));
}
ArrayList<NodeSortTree> nodeSortTreesCopy = null;
// // sort the list of nodeSortTrees:
// while (!nodeSortTrees.equals(nodeSortTreesCopy)) {
// nodeSortTreesCopy = (ArrayList<NodeSortTree>)nodeSortTrees.clone();
// Collections.sort(nodeSortTrees);
// for (NodeSortTree nodeSortTree: nodeSortTrees) {
// nodeSortTree.doInnerSort(nodeSortTrees);
// }
// }
// sort the list of nodeSortTrees:
while (!nodeSortTrees.equals(nodeSortTreesCopy)) {
nodeSortTreesCopy = (ArrayList<NodeSortTree>)nodeSortTrees.clone();
Collections.sort(nodeSortTrees);
ArrayList<String> nodeSortTreesStrings = new ArrayList<String>();
for (NodeSortTree nst: nodeSortTrees) {
nodeSortTreesStrings.add(GraphEngine.getGson().toJson(nst));
}
ArrayList<String> nodeSortTreesCopyStrings = null;
while (!nodeSortTreesStrings.equals(nodeSortTreesCopyStrings)) {
nodeSortTreesCopyStrings = (ArrayList<String>)nodeSortTreesStrings.clone();
HashMap<String, NodeSortTree> mapping = new HashMap<String, NodeSortTree>();
for (NodeSortTree nst: nodeSortTrees) {
mapping.put(GraphEngine.getGson().toJson(nst), nst);
}
Collections.sort(nodeSortTreesStrings);
nodeSortTreesCopy = new ArrayList<NodeSortTree>();
for (String s: nodeSortTreesStrings) {
nodeSortTreesCopy.add(mapping.get(s));
}
nodeSortTrees = nodeSortTreesCopy;
for (NodeSortTree nodeSortTree: nodeSortTrees) {
nodeSortTree.doInnerSort(nodeSortTrees);
}
nodeSortTreesStrings = new ArrayList<String>();
for (NodeSortTree nst: nodeSortTrees) {
nodeSortTreesStrings.add(GraphEngine.getGson().toJson(nst));
}
}
//
//
//
nf.getNodes().clear();
for (int i = 0; i < nodeSortTrees.size(); ++i) {
Node node = nodeSortTrees.get(i).getRootNode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,16 +379,16 @@ private double testRoadworkExample(boolean debug, IsomorphismHandler ih, int fro
public void testRoadworkExample() {

ArrayList<IsomorphismHandler> toTest = new ArrayList<IsomorphismHandler>();
toTest.add(new IsomorphismHandlerParallel());
toTest.add(new IsomorphismHandlerCombinatorial());
toTest.add(new IsomorphismHandlerCSPHighHeuristics());
toTest.add(new IsomorphismHandlerCSPLowHeuristics());
toTest.add(new IsomorphismHandlerDepthFirstBacktracking());
toTest.add(new IsomorphismHandlerCombinatorial());
toTest.add(new IsomorphismHandlerParallel());
toTest.add(new IsomorphismHandlerSorting());

boolean debug = false;
int fromLevel = 1;
int toLevel = 1;
int fromLevel = 2;
int toLevel = 2;
boolean drawSigmaJs = false;
boolean drawAlchemyJs = false;

Expand Down

0 comments on commit 8185973

Please sign in to comment.