Commit 24eebe3e by Michael Schmid

Binary dec tree and nfj creation finished

parent a15a466e
......@@ -2,15 +2,14 @@ package mvd.jester.model;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.jgrapht.Graphs;
import org.jgrapht.alg.shortestpath.AllDirectedPaths;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge;
import mvd.jester.utils.BinaryDecompositionTree;
......@@ -241,65 +240,67 @@ public class DagTask implements Task {
public static BinaryDecompositionTree<Job> createDecompositionTree(
DirectedAcyclicGraph<Job, DefaultEdge> jobDag, LinkedList<Job> forkNodes,
LinkedList<Job> joinNodes) {
Job source = forkNodes.getFirst();
Job sink = joinNodes.getLast();
Job current = source;
BinaryDecompositionTree<Job> tree = new BinaryDecompositionTree<>();
DagUtils.constructTree(jobDag, null, current, tree, forkNodes, joinNodes, sink);
Optional<Job> source = Optional.empty();
Optional<Job> sink = Optional.empty();
if (forkNodes.size() > 0) {
source = Optional.of(forkNodes.getFirst());
sink = Optional.of(joinNodes.getLast());
} else {
boolean firstRun = true;
for (Job j : jobDag) {
if (firstRun) {
firstRun = false;
source = Optional.of(j);
}
sink = Optional.of(j);
}
}
if (source.isPresent() && sink.isPresent()) {
Job current = source.get();
DagUtils.treeDec(jobDag, null, current, tree, forkNodes, joinNodes, sink.get());
}
return tree;
}
private static Node<Job> constructTree(DirectedAcyclicGraph<Job, DefaultEdge> jobDag,
Node<Job> parent, Job current, BinaryDecompositionTree<Job> tree,
LinkedList<Job> forkVertices, LinkedList<Job> joinVertices, Job sink) {
if (forkVertices.contains(current)) {
Job join = findJoin(jobDag, current, sink, joinVertices);
if (jobDag.outDegreeOf(join) > 1) {
throw new RuntimeException("Join und Fork in Einem! Ohoh!");
}
private static Node<Job> treeDec(DirectedAcyclicGraph<Job, DefaultEdge> jobDag,
Node<Job> parentNode, Job currentJob, BinaryDecompositionTree<Job> tree,
LinkedList<Job> forkVertices, LinkedList<Job> joinVertices, Job sinkJob) {
if (forkVertices.contains(currentJob)) {
Job forkJob = currentJob;
Job joinJob = findJoin(jobDag, forkJob, sinkJob, joinVertices);
Node<Job> forkNode = new Node<Job>(parent, NodeType.SEQ);
Node<Job> seqForkNode = new Node<Job>(parentNode, NodeType.SEQ);
seqForkNode.setLeftNode(new Node<Job>(seqForkNode, forkJob));
if (tree.isEmpty()) {
tree.setRoot(forkNode);
tree.setRoot(seqForkNode);
}
forkNode.setLeftNode(new Node<Job>(forkNode, current));
final Node<Job> continuationNode;
if (!tree.contains(join)) {
forkNode.setRightNode(new Node<Job>(forkNode, NodeType.SEQ));
Node<Job> joinNode = forkNode.getRightNode();
Iterator<Job> successorIterator =
Graphs.successorListOf(jobDag, join).iterator();
if (successorIterator.hasNext()) {
Job successor = successorIterator.next();
if (!tree.contains(successor)) {
joinNode.setRightNode(new Node<>(joinNode, NodeType.SEQ));
Node<Job> successorNode = joinNode.getRightNode();
successorNode.setLeftNode(new Node<>(successorNode, join));
Node<Job> subTree = constructTree(jobDag, successorNode, successor,
tree, forkVertices, joinVertices, sink);
successorNode.setRightNode(subTree);
} else {
joinNode.setRightNode(new Node<>(joinNode, join));
}
} else {
joinNode.setRightNode(new Node<>(joinNode, join));
}
joinNode.setLeftNode(new Node<>(joinNode, NodeType.PAR));
continuationNode = joinNode.getLeftNode();
final Node<Job> parContinuationNode;
if (!tree.contains(joinJob)) {
Node<Job> seqJoinNode =
seqForkNode.setRightNode(new Node<Job>(seqForkNode, NodeType.SEQ));
Node<Job> subTreeOfJoin = treeDec(jobDag, seqJoinNode, joinJob, tree,
forkVertices, joinVertices, sinkJob);
seqJoinNode.setRightNode(subTreeOfJoin);
parContinuationNode =
seqJoinNode.setLeftNode(new Node<Job>(seqJoinNode, NodeType.PAR));
} else {
forkNode.setRightNode(new Node<>(forkNode, NodeType.PAR));
continuationNode = forkNode.getRightNode();
parContinuationNode =
seqForkNode.setRightNode(new Node<Job>(seqForkNode, NodeType.PAR));
}
Node<Job> successorParent = continuationNode;
List<Job> successors = Graphs.successorListOf(jobDag, current);
Node<Job> successorParent = parContinuationNode;
List<Job> successors = Graphs.successorListOf(jobDag, currentJob);
// create leftSide of joinNode
for (int i = 0; i < successors.size(); ++i) {
Job succ = successors.get(i);
Node<Job> thisNode = constructTree(jobDag, successorParent, succ, tree,
forkVertices, joinVertices, sink);
Node<Job> thisNode = treeDec(jobDag, successorParent, succ, tree, forkVertices,
joinVertices, sinkJob);
if (i == successors.size() - 1) {
successorParent.setRightNode(thisNode);
} else if (i == successors.size() - 2) {
......@@ -311,12 +312,94 @@ public class DagTask implements Task {
}
}
return forkNode;
return seqForkNode;
} else {
return new Node<>(parent, current);
List<Job> successorList = Graphs.successorListOf(jobDag, currentJob);
if (successorList.size() > 0) {
Job successor = successorList.get(0);
if (!tree.contains(successor)) {
Node<Job> seqJobNode = new Node<Job>(parentNode, NodeType.SEQ);
if (tree.isEmpty()) {
tree.setRoot(seqJobNode);
}
seqJobNode.setLeftNode(new Node<Job>(seqJobNode, currentJob));
Node<Job> contNode = treeDec(jobDag, seqJobNode, successor, tree,
forkVertices, joinVertices, sinkJob);
seqJobNode.setRightNode(contNode);
return seqJobNode;
}
}
Node<Job> jobNode = new Node<Job>(parentNode, currentJob);
if (tree.isEmpty()) {
tree.setRoot(jobNode);
}
return jobNode;
}
}
// private static Node<Job> constructTree(DirectedAcyclicGraph<Job, DefaultEdge> jobDag,
// Node<Job> parent, Job currentFork, BinaryDecompositionTree<Job> tree,
// LinkedList<Job> forkVertices, LinkedList<Job> joinVertices, Job sink) {
// if (forkVertices.contains(currentFork)) {
// Job join = findJoin(jobDag, currentFork, sink, joinVertices);
// Node<Job> forkNode = new Node<Job>(parent, NodeType.SEQ);
// if (tree.isEmpty()) {
// tree.setRoot(forkNode);
// }
// forkNode.setLeftNode(new Node<Job>(forkNode, currentFork));
// final Node<Job> continuationNode;
// if (!tree.contains(join)) {
// forkNode.setRightNode(new Node<Job>(forkNode, NodeType.SEQ));
// Node<Job> joinNode = forkNode.getRightNode();
// Iterator<Job> successorIterator =
// Graphs.successorListOf(jobDag, join).iterator();
// if (successorIterator.hasNext()) {
// Job successor = successorIterator.next();
// if (!tree.contains(successor)) {
// joinNode.setRightNode(new Node<>(joinNode, NodeType.SEQ));
// Node<Job> successorNode = joinNode.getRightNode();
// successorNode.setLeftNode(new Node<>(successorNode, join));
// Node<Job> subTree = constructTree(jobDag, successorNode, successor,
// tree, forkVertices, joinVertices, sink);
// successorNode.setRightNode(subTree);
// } else {
// joinNode.setRightNode(new Node<>(joinNode, join));
// }
// } else {
// joinNode.setRightNode(new Node<>(joinNode, join));
// }
// joinNode.setLeftNode(new Node<>(joinNode, NodeType.PAR));
// continuationNode = joinNode.getLeftNode();
// } else {
// forkNode.setRightNode(new Node<>(forkNode, NodeType.PAR));
// continuationNode = forkNode.getRightNode();
// }
// Node<Job> successorParent = continuationNode;
// List<Job> successors = Graphs.successorListOf(jobDag, currentFork);
// // create leftSide of joinNode
// for (int i = 0; i < successors.size(); ++i) {
// Job succ = successors.get(i);
// Node<Job> thisNode = constructTree(jobDag, successorParent, succ, tree,
// forkVertices, joinVertices, sink);
// if (i == successors.size() - 1) {
// successorParent.setRightNode(thisNode);
// } else if (i == successors.size() - 2) {
// successorParent.setLeftNode(thisNode);
// } else {
// successorParent.setLeftNode(thisNode);
// successorParent.setRightNode(new Node<>(successorParent, NodeType.PAR));
// successorParent = successorParent.getRightNode();
// }
// }
// return forkNode;
// } else {
// return new Node<>(parent, currentFork);
// }
// }
public static boolean checkNFJProperty(DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
LinkedList<Job> joinNodes = new LinkedList<>();
LinkedList<Job> forkNodes = new LinkedList<>();
......@@ -327,43 +410,58 @@ public class DagTask implements Task {
return true;
}
for (Job j : joinNodes) {
nextFork: for (Job f : forkNodes) {
Set<DefaultEdge> edgeSet = jobDag.getAllEdges(f, j);
for (DefaultEdge e : edgeSet) {
Job a = jobDag.getEdgeSource(e);
if (a != f) {
Set<Job> succAndPred = new HashSet<>();
succAndPred.addAll(Graphs.predecessorListOf(jobDag, a));
succAndPred.addAll(Graphs.successorListOf(jobDag, a));
for (Job b : succAndPred) {
if (!((jobDag.getAncestors(jobDag, j).contains(b) || b == j)
&& (jobDag.getDescendants(jobDag, f).contains(b)
|| b == f))) {
continue nextFork;
}
nextJoin: for (Job j : joinNodes) {
for (Job f : forkNodes) {
Set<Job> ancestorsOfJ = jobDag.getAncestors(jobDag, j);
Set<Job> ancesotorsOfF = jobDag.getAncestors(jobDag, f);
ancesotorsOfF.add(f);
Set<Job> inbetweenJobs = new HashSet<>(ancestorsOfJ);
inbetweenJobs.removeAll(ancesotorsOfF);
if (inbetweenJobs.isEmpty()) {
continue;
}
for (Job a : inbetweenJobs) {
List<Job> neighboursOfA = Graphs.neighborListOf(jobDag, a);
for (Job b : neighboursOfA) {
if ((jobDag.getAncestors(jobDag, j).contains(b) || b == j)
&& (jobDag.getDescendants(jobDag, f).contains(b) || b == f)) {
continue nextJoin;
}
}
}
return true;
}
return false;
}
return false;
return true;
}
private static Job findJoin(DirectedAcyclicGraph<Job, DefaultEdge> jobDag, Job forkNode,
Job sink, List<Job> joinNodes) {
for (Job j : joinNodes) {
final Set<DefaultEdge> edgeSet = new HashSet<>();
AllDirectedPaths<Job, DefaultEdge> finder = new AllDirectedPaths<>(jobDag);
finder.getAllPaths(forkNode, j, true, null)
.forEach(g -> edgeSet.addAll(g.getEdgeList()));
Set<DefaultEdge> outgoingEdges = jobDag.outgoingEdgesOf(forkNode);
if (edgeSet.containsAll(outgoingEdges)) {
Set<Job> ancestorsOfJ = jobDag.getAncestors(jobDag, j);
Set<Job> ancesotorsOfFork = jobDag.getAncestors(jobDag, forkNode);
ancesotorsOfFork.add(forkNode);
Set<Job> inbetweenJobs = new HashSet<>(ancestorsOfJ);
inbetweenJobs.removeAll(ancesotorsOfFork);
if (inbetweenJobs.isEmpty()) {
continue;
}
List<Job> successorOfFork = Graphs.successorListOf(jobDag, forkNode);
if (inbetweenJobs.containsAll(successorOfFork)) {
return j;
}
// final Set<DefaultEdge> edgeSet = new HashSet<>();
// AllDirectedPaths<Job, DefaultEdge> finder = new AllDirectedPaths<>(jobDag);
// finder.getAllPaths(forkNode, j, true, null)
// .forEach(g -> edgeSet.addAll(g.getEdgeList()));
// Set<DefaultEdge> outgoingEdges = jobDag.outgoingEdgesOf(forkNode);
// if (edgeSet.containsAll(outgoingEdges)) {
// return j;
// }
}
return sink;
......@@ -394,63 +492,57 @@ public class DagTask implements Task {
DirectedAcyclicGraph<Job, DefaultEdge> jobDag =
new DirectedAcyclicGraph<>(DefaultEdge.class);
traverseNodes(jobDag, tree.getRootNode(), TraversalOrder.LEFT);
if (tree.getRootNode() != null) {
traverseNodes(jobDag, tree.getRootNode());
}
return jobDag;
}
private static Set<Job> traverseNodes(DirectedAcyclicGraph<Job, DefaultEdge> jobDag,
Node<Job> node, TraversalOrder order) {
private static GraphEndPoints traverseNodes(DirectedAcyclicGraph<Job, DefaultEdge> jobDag,
Node<Job> node) {
switch (node.getNodeType()) {
case LEAF: {
Job j = node.getObject();
jobDag.addVertex(j);
return new HashSet<Job>(Arrays.asList(j));
Set<Job> endPoints = new HashSet<Job>(Arrays.asList(j));
return new GraphEndPoints(endPoints, endPoints);
}
case SEQ: {
Set<Job> left = traverseNodes(jobDag, node.getLeftNode(), TraversalOrder.LEFT);
Set<Job> right =
traverseNodes(jobDag, node.getRightNode(), TraversalOrder.RIGHT);
try {
for (Job l : left) {
for (Job r : right) {
jobDag.addDagEdge(l, r);
}
}
} catch (Exception e) {
}
if (order == TraversalOrder.LEFT) {
Set<Job> openEndJobs = new HashSet<>();
for (Job j : right) {
if (jobDag.outDegreeOf(j) == 0) {
openEndJobs.add(j);
GraphEndPoints leftEndPoints = traverseNodes(jobDag, node.getLeftNode());
GraphEndPoints rightEndPoints = traverseNodes(jobDag, node.getRightNode());
for (Job l : leftEndPoints.right) {
for (Job r : rightEndPoints.left) {
if (r == l) {
continue;
}
for (Job d : jobDag.getDescendants(jobDag, j)) {
if (jobDag.outDegreeOf(d) == 0) {
openEndJobs.add(d);
}
try {
jobDag.addDagEdge(l, r);
} catch (Exception e) {
int test = 3;
}
}
return openEndJobs;
} else {
return left;
}
// return order == TraversalOrder.LEFT ? right : left; // left -> right; right
// ->
return new GraphEndPoints(leftEndPoints.left, rightEndPoints.right);
}
case PAR: {
Set<Job> left = traverseNodes(jobDag, node.getLeftNode(), order);
Set<Job> right = traverseNodes(jobDag, node.getRightNode(), order);
return Sets.newHashSet(Iterables.concat(left, right));
GraphEndPoints leftEndPoints = traverseNodes(jobDag, node.getLeftNode());
GraphEndPoints rightEndPoints = traverseNodes(jobDag, node.getRightNode());
Set<Job> leftEndPointJobs = Sets
.newHashSet(Iterables.concat(leftEndPoints.left, rightEndPoints.left));
Set<Job> rightEndPointJobs = Sets.newHashSet(
Iterables.concat(leftEndPoints.right, rightEndPoints.right));
return new GraphEndPoints(leftEndPointJobs, rightEndPointJobs);
}
default:
break;
}
return new HashSet<>();
return new GraphEndPoints(new HashSet<>(), new HashSet<>());
}
private class GraphEndPoints {
public static class GraphEndPoints {
public Set<Job> left;
public Set<Job> right;
......
package mvd.jester.utils;
public class BinaryDecompositionTree<N> {
private Node<N> root;
......@@ -12,6 +13,9 @@ public class BinaryDecompositionTree<N> {
}
public boolean contains(N object) {
if (root == null) {
return false;
}
return root.contains(object);
}
......@@ -75,8 +79,9 @@ public class BinaryDecompositionTree<N> {
/**
* @param leftNode the leftNode to set
*/
public void setLeftNode(Node<T> leftNode) {
public Node<T> setLeftNode(Node<T> leftNode) {
this.leftNode = leftNode;
return this.leftNode;
}
/**
......@@ -89,8 +94,9 @@ public class BinaryDecompositionTree<N> {
/**
* @param rightNode the rightNode to set
*/
public void setRightNode(Node<T> rightNode) {
public Node<T> setRightNode(Node<T> rightNode) {
this.rightNode = rightNode;
return this.rightNode;
}
/**
......
package mvd.jester.model;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.jgrapht.Graphs;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge;
import org.junit.jupiter.api.DisplayName;
......@@ -12,20 +13,6 @@ import mvd.jester.utils.BinaryDecompositionTree;
public class TestDagUtils {
@Test
@DisplayName("Test if a NFJ Graph is created correctly.")
public void checkNFJCreation() {
for (int i = 0; i < 100; ++i) {
DagTaskBuilder builder = new DagTaskBuilder();
DirectedAcyclicGraph<Job, DefaultEdge> jobDag = builder.generateTask().getJobDag();
DirectedAcyclicGraph<Job, DefaultEdge> modifiedJobDag = DagUtils.createNFJGraph(jobDag);
assertTrue(DagUtils.checkNFJProperty(modifiedJobDag));
}
}
@Test
@DisplayName("Test if dynamic segments are constructed correctly.")
public void checkPathLength() {
DirectedAcyclicGraph<Job, DefaultEdge> jobDag = createJobDag();
......@@ -45,15 +32,73 @@ public class TestDagUtils {
@Test
@DisplayName("Check if NFJ DAGs are created correctly.")
void checkNfjDagCreation() {
for (int i = 0; i < 100; ++i) {
DagTaskBuilder b = new DagTaskBuilder();
DagTask t = b.generateTask();
DirectedAcyclicGraph<Job, DefaultEdge> nfjDag = DagUtils.createNFJGraph(t.getJobDag());
assertTrue(DagUtils.checkNFJProperty(nfjDag));
}
}
@Test
@DisplayName("Check if Decomposition Tree is created correctly for NFJ Dag.")
void checkDecompositionTreeCreation() {
DirectedAcyclicGraph<Job, DefaultEdge> jobDag = createJobDag();
BinaryDecompositionTree<Job> tree = DagUtils.createDecompositionTree(jobDag);
DirectedAcyclicGraph<Job, DefaultEdge> jobDagFromTree =
DagUtils.createNFJfromDecompositionTree(tree);
for (int i = 0; i < 100; ++i) {
DagTaskBuilder b = new DagTaskBuilder();
DagTask t = b.generateTask();
DirectedAcyclicGraph<Job, DefaultEdge> jobDag = t.getJobDag();
DirectedAcyclicGraph<Job, DefaultEdge> nfjJobDag = DagUtils.createNFJGraph(jobDag);
BinaryDecompositionTree<Job> tree = DagUtils.createDecompositionTree(nfjJobDag);
DirectedAcyclicGraph<Job, DefaultEdge> jobDagFromTree =
DagUtils.createNFJfromDecompositionTree(tree);
assertTrue(jobDag.vertexSet().equals(nfjJobDag.vertexSet()));
assertTrue(jobDag.vertexSet().equals(jobDagFromTree.vertexSet()));
assertTrue(jobDagFromTree.edgeSet().size() == nfjJobDag.edgeSet().size());
for (DefaultEdge e : nfjJobDag.edgeSet()) {
Job target = nfjJobDag.getEdgeTarget(e);
Job source = nfjJobDag.getEdgeSource(e);
assertTrue(jobDagFromTree.containsEdge(source, target));
}
for (Job j : nfjJobDag) {
for (Job n : nfjJobDag) {
if (n == j) {
continue;
}
if (nfjJobDag.containsEdge(n, j)) {
assertTrue(jobDagFromTree.containsEdge(n, j));
}
}
assertTrue(nfjJobDag.inDegreeOf(j) == jobDagFromTree.inDegreeOf(j));
assertTrue(nfjJobDag.outDegreeOf(j) == jobDagFromTree.outDegreeOf(j));
for (Job p : Graphs.predecessorListOf(nfjJobDag, j)) {
assertTrue(Graphs.predecessorListOf(jobDagFromTree, j).contains(p));
}
for (Job s : Graphs.successorListOf(jobDagFromTree, j)) {
assertTrue(Graphs.successorListOf(jobDagFromTree, j).contains(s));
}
for (Job a : nfjJobDag.getAncestors(nfjJobDag, j)) {
assertTrue(jobDagFromTree.getAncestors(jobDagFromTree, j).contains(a));
}
for (Job d : nfjJobDag.getDescendants(nfjJobDag, j)) {
assertTrue(jobDagFromTree.getDescendants(jobDagFromTree, j).contains(d));
}
}
assertTrue(jobDag.equals(jobDagFromTree));
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment