diff --git a/dg/src/main/jastadd/DependencyGraphReachability.jrag b/dg/src/main/jastadd/DependencyGraphReachability.jrag index abf2783c94cb6dc048f18b97b8a220ff7e6d2e30..75063308c553bdae9066e9411e18835fbfb87c73 100644 --- a/dg/src/main/jastadd/DependencyGraphReachability.jrag +++ b/dg/src/main/jastadd/DependencyGraphReachability.jrag @@ -1,102 +1,81 @@ -import java.util.Collections; -import java.util.Deque; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; + +aspect Naviagation { + inh DependencyGraph Component.dg(); + eq DependencyGraph.getComponent().dg() = this; +} + aspect Reachability { -// syn Set<Component> Component.successors() circular [new HashSet<>()] { -// Set<Component> result = new HashSet<>(); -// for (Component c: getFromList()) { -// result.add(c); -// result.addAll(c.successors()); -// } -// return result; -// } +// old, dependency-based algorithm for SCC -// syn Set<Component> Component.predecessors() circular [new HashSet<>()] { -// Set<Component> result = new HashSet<>(); -// for (Component c: getToList()) { -// result.add(c); -// result.addAll(c.predecessors()); -// } -// return result; -// } +// coll Set<Component> Component.successors() circular [new HashSet<>()] with add root DependencyGraph; +// Component contributes this to Component.successors() for each getToList(); +// Component contributes each this.successors() to Component.successors() for each getToList(); -// inh DependencyGraph Component.dg(); -// eq DependencyGraph.getComponent().dg() = this; -// -// syn lazy Map<Component,Set<Component>> DependencyGraph.componentPredecessorMap() { -// Map<Component,Set<Component>> result = new HashMap<>(); -// for (Component c: getComponentList()) { -// result.put(c, new HashSet<>()); -// } -// -// for (Component from: getComponentList()) { -// for (Component to: from.successors()){ -// result.get(to).add(from); -// } -// } -// return result; -// } +// coll Set<Component> Component.predecessors() [new HashSet<>()] with add root DependencyGraph; +// Component contributes this to Component.predecessors() for each successors(); - syn lazy Set<Component> Component.predecessors() = new HashSet<>(); - syn lazy Set<Component> Component.successors() = new HashSet<>(); - syn lazy Set<Component> Component.SCC() = new HashSet<>(); -// syn lazy Set<Component> Component.SCC() { -// Set<Component> result = new HashSet<>(successors()); -// result.retainAll(predecessors()); -// return result; -// } +// coll HashSet<Component> Component.SCC() with add root DependencyGraph; +// Component contributes each predecessors() when (successors().contains(this)) to Component.SCC() for this; // coll HashSet<Set<Component>> DependencyGraph.SCC() with add root DependencyGraph; // Component contributes SCC() when SCC().size() > 0 to DependencyGraph.SCC(); - - syn Set<Set<Component>> DependencyGraph.SCC() { //Kosaraju's algorithm - System.out.println("Kosaraju's algorithm"); - Map<Component,Integer> visited=new HashMap<>(); - Deque<Component> locked=new LinkedList<>(); - //Visit nodes forward - long startVisit = System.nanoTime(); - for (Component n:getComponentList()) - visit(n,visited,locked); - //Assign nodes to SCCs backward - long startAssign = System.nanoTime(); - int scc=0; - for (Component n:locked) { - assign(n,visited,scc); - scc++; - } - long stop = System.nanoTime(); - //Map visited Map[Node,int]-> result Map[int,Set[Node]] - - System.out.println("visit : "+(startAssign-startVisit)); - System.out.println("assign: "+(stop-startAssign)); - System.out.println("sum: "+(stop-startVisit)); - - Map<Integer,Set<Component>> result=visited.entrySet().stream() - .collect(Collectors.groupingBy(e->e.getValue(), - Collectors.mapping(e->e.getKey(), - Collectors.toSet()))); - return result.values().stream().collect(Collectors.toSet()); + + + // stubs for tests that use old algorithm + syn lazy Set<Component> Component.predecessors() = new HashSet<>(); + syn lazy Set<Component> Component.successors() = new HashSet<>(); + syn lazy Set<Component> Component.SCC() = new HashSet<>(); + + /** + * Kosaraju's algorithm + */ + syn Set<Set<Component>> DependencyGraph.SCC() { +// System.out.println("Kosaraju's algorithm"); + Map<Component, Integer> visited = new HashMap<>(); + Deque<Component> locked = new LinkedList<>(); + //Visit nodes forward +// long startVisit = System.nanoTime(); + for (Component n : getComponentList()) + visit(n, visited, locked); + //Assign nodes to SCCs backward +// long startAssign = System.nanoTime(); + int scc = 0; + for (Component n : locked) { + assign(n, visited, scc); + scc++; + } +// long stop = System.nanoTime(); + //Map visited Map[Node,int]-> result Map[int,Set[Node]] + +// System.out.println("visit : " + (startAssign - startVisit)); +// System.out.println("assign: " + (stop - startAssign)); +// System.out.println("sum: " + (stop - startVisit)); + + Map<Integer, Set<Component>> result = visited.entrySet().stream().collect( + Collectors.groupingBy( + e -> e.getValue(), + Collectors.mapping(e -> e.getKey(), Collectors.toSet()) + ) + ); + return result.values().stream().collect(Collectors.toSet()); } - - public void DependencyGraph.visit(Component n, Map<Component, Integer> visited, Deque<Component> locked){ - if (visited.containsKey(n)) return; - visited.put(n,-1); - for (Component s:n.getFromList()) - visit(s,visited,locked); - locked.addFirst(n); + + private void DependencyGraph.visit(Component n, Map<Component, Integer> visited, Deque<Component> locked) { + if (visited.containsKey(n)) return; + visited.put(n, -1); + for (Component s : n.getFromList()) + visit(s, visited, locked); + locked.addFirst(n); } - - public void DependencyGraph.assign(Component n, Map<Component, Integer> visited, int root) { - if (visited.get(n)>-1) return; - visited.put(n,root); - for (Component p:n.getToList()) - assign(p,visited,root); + + private void DependencyGraph.assign(Component n, Map<Component, Integer> visited, int root) { + if (visited.get(n) > -1) return; + visited.put(n, root); + for (Component p : n.getToList()) + assign(p, visited, root); } - + } diff --git a/extendj b/extendj index 1b26decca78b3cdbfa3a9ba9666fbd75e2bdd436..bab01c7e6df0d3e6aa2a0bc0ba7dc9f6f2ee3184 160000 --- a/extendj +++ b/extendj @@ -1 +1 @@ -Subproject commit 1b26decca78b3cdbfa3a9ba9666fbd75e2bdd436 +Subproject commit bab01c7e6df0d3e6aa2a0bc0ba7dc9f6f2ee3184