Commit a15a466e by Michael Schmid

added binary decomp tree and some changes on tests

parent cdffd7ee
package mvd.jester.model; package mvd.jester.model;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.jgrapht.Graphs; import org.jgrapht.Graphs;
import org.jgrapht.alg.shortestpath.AllDirectedPaths;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph; import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.traverse.BreadthFirstIterator; import mvd.jester.utils.BinaryDecompositionTree;
import mvd.jester.utils.BinaryDecompositionTree.Node;
import mvd.jester.utils.BinaryDecompositionTree.NodeType;
public class DagTask implements Task { public class DagTask implements Task {
...@@ -115,6 +122,10 @@ public class DagTask implements Task { ...@@ -115,6 +122,10 @@ public class DagTask implements Task {
public static long calculateCriticalPath(DirectedAcyclicGraph<Job, DefaultEdge> jobDag) { public static long calculateCriticalPath(DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
long criticalPath = 0; long criticalPath = 0;
// BreadthFirstIterator<Job, DefaultEdge> breadthFirstIterator =
// new BreadthFirstIterator<>(jobDag);
// while (breadthFirstIterator.hasNext()) {
// Job job = breadthFirstIterator.next();
for (Job job : jobDag) { for (Job job : jobDag) {
Set<DefaultEdge> edges = jobDag.incomingEdgesOf(job); Set<DefaultEdge> edges = jobDag.incomingEdgesOf(job);
long longestRelativeCompletionTime = 0; long longestRelativeCompletionTime = 0;
...@@ -161,25 +172,37 @@ public class DagTask implements Task { ...@@ -161,25 +172,37 @@ public class DagTask implements Task {
public static DirectedAcyclicGraph<Job, DefaultEdge> createNFJGraph( public static DirectedAcyclicGraph<Job, DefaultEdge> createNFJGraph(
DirectedAcyclicGraph<Job, DefaultEdge> jobDag) { DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
DirectedAcyclicGraph<Job, DefaultEdge> modifiedJobDag =
new DirectedAcyclicGraph<>(DefaultEdge.class);
Graphs.addGraph(modifiedJobDag, jobDag);
LinkedList<Job> joinNodes = new LinkedList<>(); LinkedList<Job> joinNodes = new LinkedList<>();
List<Job> forkNodes = new LinkedList<>(); LinkedList<Job> forkNodes = new LinkedList<>();
collectForksAndJoins(jobDag, forkNodes, joinNodes);
return createNFJGraph(jobDag, forkNodes, joinNodes);
}
BreadthFirstIterator<Job, DefaultEdge> breadthFirstIterator = public static void collectForksAndJoins(DirectedAcyclicGraph<Job, DefaultEdge> jobDag,
new BreadthFirstIterator<>(modifiedJobDag); LinkedList<Job> forkNodes, LinkedList<Job> joinNodes) {
while (breadthFirstIterator.hasNext()) { for (Job j : jobDag) {
Job j = breadthFirstIterator.next(); if (jobDag.inDegreeOf(j) > 1) {
if (modifiedJobDag.inDegreeOf(j) > 1) {
joinNodes.add(j); joinNodes.add(j);
} }
if (modifiedJobDag.outDegreeOf(j) > 1) { if (jobDag.outDegreeOf(j) > 1) {
forkNodes.add(j); forkNodes.add(j);
} }
} }
}
Job sink = joinNodes.getLast(); public static DirectedAcyclicGraph<Job, DefaultEdge> createNFJGraph(
DirectedAcyclicGraph<Job, DefaultEdge> jobDag, LinkedList<Job> forkNodes,
LinkedList<Job> joinNodes) {
DirectedAcyclicGraph<Job, DefaultEdge> modifiedJobDag =
new DirectedAcyclicGraph<>(DefaultEdge.class);
Graphs.addGraph(modifiedJobDag, jobDag);
if (!(joinNodes.size() > 1)) {
return modifiedJobDag;
}
final Job sink = joinNodes.getLast();
for (Job j : joinNodes) { for (Job j : joinNodes) {
Set<DefaultEdge> edgeSet = new HashSet<>(modifiedJobDag.incomingEdgesOf(j)); Set<DefaultEdge> edgeSet = new HashSet<>(modifiedJobDag.incomingEdgesOf(j));
...@@ -201,34 +224,107 @@ public class DagTask implements Task { ...@@ -201,34 +224,107 @@ public class DagTask implements Task {
break; break;
} }
} }
// Find fork node f following the path along this edge e
// if f has successor that is not ancestor of j -> e is conflicting edge
// get sorcetarget of e
// remove e
// if sourcetarget has no successor -> connect sourcetraget to sink
// if indegree = 1 -> break;
} }
// if (!DagUtils.checkProperty1(modifiedJobDag)) {
// throw new RuntimeException("abs");
// }
return modifiedJobDag; return modifiedJobDag;
} }
private static boolean checkProperty1(DirectedAcyclicGraph<Job, DefaultEdge> jobDag) { public static BinaryDecompositionTree<Job> createDecompositionTree(
DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
LinkedList<Job> joinNodes = new LinkedList<>(); LinkedList<Job> joinNodes = new LinkedList<>();
List<Job> forkNodes = new LinkedList<>(); LinkedList<Job> forkNodes = new LinkedList<>();
BreadthFirstIterator<Job, DefaultEdge> breadthFirstIterator = collectForksAndJoins(jobDag, forkNodes, joinNodes);
new BreadthFirstIterator<>(jobDag); return createDecompositionTree(jobDag, forkNodes, joinNodes);
while (breadthFirstIterator.hasNext()) { }
Job j = breadthFirstIterator.next();
if (jobDag.inDegreeOf(j) > 1) { public static BinaryDecompositionTree<Job> createDecompositionTree(
joinNodes.add(j); 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);
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!");
} }
if (jobDag.outDegreeOf(j) > 1) {
forkNodes.add(j); Node<Job> forkNode = new Node<Job>(parent, NodeType.SEQ);
if (tree.isEmpty()) {
tree.setRoot(forkNode);
} }
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();
} else {
forkNode.setRightNode(new Node<>(forkNode, NodeType.PAR));
continuationNode = forkNode.getRightNode();
}
Node<Job> successorParent = continuationNode;
List<Job> successors = Graphs.successorListOf(jobDag, current);
// 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, current);
}
}
public static boolean checkNFJProperty(DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
LinkedList<Job> joinNodes = new LinkedList<>();
LinkedList<Job> forkNodes = new LinkedList<>();
collectForksAndJoins(jobDag, forkNodes, joinNodes);
if (!(joinNodes.size() > 1)) {
return true;
} }
for (Job j : joinNodes) { for (Job j : joinNodes) {
...@@ -257,14 +353,29 @@ public class DagTask implements Task { ...@@ -257,14 +353,29 @@ public class DagTask implements Task {
return false; return false;
} }
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)) {
return j;
}
}
return sink;
}
private static boolean checkForFork(DirectedAcyclicGraph<Job, DefaultEdge> jobDag, private static boolean checkForFork(DirectedAcyclicGraph<Job, DefaultEdge> jobDag,
Job joinNode, List<Job> forkNodes, Job job) { Job joinNode, List<Job> forkNodes, Job job) {
List<Job> pred = Graphs.predecessorListOf(jobDag, job); List<Job> pred = Graphs.predecessorListOf(jobDag, job);
for (Job p : pred) { for (Job p : pred) {
if (forkNodes.contains(p)) { if (forkNodes.contains(p)) {
for (DefaultEdge successorEdge : jobDag.outgoingEdgesOf(p)) { for (Job successor : Graphs.successorListOf(jobDag, p)) {
Job successor = jobDag.getEdgeSource(successorEdge);
if (jobDag.getAncestors(jobDag, joinNode).contains(successor)) { if (jobDag.getAncestors(jobDag, joinNode).contains(successor)) {
return false; return false;
} }
...@@ -277,5 +388,81 @@ public class DagTask implements Task { ...@@ -277,5 +388,81 @@ public class DagTask implements Task {
return true; return true;
} }
public static DirectedAcyclicGraph<Job, DefaultEdge> createNFJfromDecompositionTree(
BinaryDecompositionTree<Job> tree) {
DirectedAcyclicGraph<Job, DefaultEdge> jobDag =
new DirectedAcyclicGraph<>(DefaultEdge.class);
traverseNodes(jobDag, tree.getRootNode(), TraversalOrder.LEFT);
return jobDag;
}
private static Set<Job> traverseNodes(DirectedAcyclicGraph<Job, DefaultEdge> jobDag,
Node<Job> node, TraversalOrder order) {
switch (node.getNodeType()) {
case LEAF: {
Job j = node.getObject();
jobDag.addVertex(j);
return new HashSet<Job>(Arrays.asList(j));
}
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);
}
for (Job d : jobDag.getDescendants(jobDag, j)) {
if (jobDag.outDegreeOf(d) == 0) {
openEndJobs.add(d);
}
}
}
return openEndJobs;
} else {
return left;
}
// return order == TraversalOrder.LEFT ? right : left; // left -> right; 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));
}
default:
break;
}
return new HashSet<>();
}
private class GraphEndPoints {
public Set<Job> left;
public Set<Job> right;
public GraphEndPoints(Set<Job> left, Set<Job> right) {
this.left = left;
this.right = right;
}
}
private enum TraversalOrder {
LEFT, RIGHT
}
} }
} }
...@@ -211,7 +211,7 @@ public class SystemSetup<T extends Task> { ...@@ -211,7 +211,7 @@ public class SystemSetup<T extends Task> {
private long p_par = 80; private long p_par = 80;
private long p_add = 20; private long p_add = 20;
private double getBeta() { public double getBeta() {
return 0.035 * numberOfProcessors; return 0.035 * numberOfProcessors;
} }
...@@ -253,7 +253,6 @@ public class SystemSetup<T extends Task> { ...@@ -253,7 +253,6 @@ public class SystemSetup<T extends Task> {
fork(jobDag, Optional.of(j), this.depth); fork(jobDag, Optional.of(j), this.depth);
randomEdges(jobDag); randomEdges(jobDag);
final long workload = DagUtils.calculateWorkload(jobDag); final long workload = DagUtils.calculateWorkload(jobDag);
final long criticalPath = DagUtils.calculateCriticalPath(jobDag); final long criticalPath = DagUtils.calculateCriticalPath(jobDag);
......
...@@ -4,6 +4,7 @@ import java.math.RoundingMode; ...@@ -4,6 +4,7 @@ import java.math.RoundingMode;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -11,6 +12,7 @@ import com.google.common.collect.Lists; ...@@ -11,6 +12,7 @@ import com.google.common.collect.Lists;
import com.google.common.math.LongMath; import com.google.common.math.LongMath;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph; import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.traverse.BreadthFirstIterator;
import mvd.jester.info.SchedulingInfo; import mvd.jester.info.SchedulingInfo;
import mvd.jester.info.TerminationInfo; import mvd.jester.info.TerminationInfo;
import mvd.jester.info.TerminationInfo.Level; import mvd.jester.info.TerminationInfo.Level;
...@@ -22,6 +24,7 @@ import mvd.jester.model.Task; ...@@ -22,6 +24,7 @@ import mvd.jester.model.Task;
import mvd.jester.model.DagTask.DagUtils; import mvd.jester.model.DagTask.DagUtils;
import mvd.jester.priority.PriorityManager; import mvd.jester.priority.PriorityManager;
import mvd.jester.priority.RateMonotonic; import mvd.jester.priority.RateMonotonic;
import mvd.jester.utils.BinaryDecompositionTree;
public class FonsecaNelis extends AbstractTest<DagTask> { public class FonsecaNelis extends AbstractTest<DagTask> {
...@@ -57,14 +60,25 @@ public class FonsecaNelis extends AbstractTest<DagTask> { ...@@ -57,14 +60,25 @@ public class FonsecaNelis extends AbstractTest<DagTask> {
private void createNFJandDecompositionTree(SortedTaskSet<DagTask> tasks) { private void createNFJandDecompositionTree(SortedTaskSet<DagTask> tasks) {
for (DagTask t : tasks) { for (DagTask t : tasks) {
DirectedAcyclicGraph<Job, DefaultEdge> jobDag = t.getJobDag();
LinkedList<Job> joinNodes = new LinkedList<>();
LinkedList<Job> forkNodes = new LinkedList<>();
BreadthFirstIterator<Job, DefaultEdge> breadthFirstIterator =
new BreadthFirstIterator<>(jobDag);
while (breadthFirstIterator.hasNext()) {
Job j = breadthFirstIterator.next();
if (jobDag.inDegreeOf(j) > 1) {
joinNodes.add(j);
}
if (jobDag.outDegreeOf(j) > 1) {
forkNodes.add(j);
}
}
DirectedAcyclicGraph<Job, DefaultEdge> modifiedJobDag = DirectedAcyclicGraph<Job, DefaultEdge> modifiedJobDag =
DagUtils.createNFJGraph(t.getJobDag()); DagUtils.createNFJGraph(jobDag, forkNodes, joinNodes);
// List<Segment> sortedSegment = new LinkedList<>(t.getWorkloadDistribution()); BinaryDecompositionTree<Job> tree =
// Collections.sort(sortedSegment, DagUtils.createDecompositionTree(modifiedJobDag, forkNodes, joinNodes);
// (s1, s2) -> (int) (s2.getNumberOfJobs() - s1.getNumberOfJobs()));
// Set<Segment> sortedSet = new LinkedHashSet<>(sortedSegment);
// sortedSegments.put(t, sortedSet);
} }
} }
......
package mvd.jester.utils;
public class BinaryDecompositionTree<N> {
private Node<N> root;
public BinaryDecompositionTree() {
}
public Node<N> getRootNode() {
return root;
}
public boolean contains(N object) {
return root.contains(object);
}
public boolean isEmpty() {
return root == null;
}
public void setRoot(Node<N> root) {
this.root = root;
}
public static class Node<T> {
private final Node<T> parentNode;
private Node<T> leftNode;
private Node<T> rightNode;
private NodeType nodeType;
private T object;
public Node(Node<T> parentNode, NodeType nodeType) {
this.parentNode = parentNode;
this.nodeType = nodeType;
}
public boolean contains(T object) {
if (nodeType.equals(NodeType.LEAF)) {
return this.object == object;
} else {
boolean leftContains = false;
boolean rightContains = false;
if (leftNode != null) {
leftContains = leftNode.contains(object);
}
if (rightNode != null) {
rightContains = rightNode.contains(object);
}
return leftContains || rightContains;
}
}
public Node(Node<T> parentNode, T object) {
this.parentNode = parentNode;
this.nodeType = NodeType.LEAF;
this.object = object;
}
/**
* @return the parentNode
*/
public Node<T> getParentNode() {
return parentNode;
}
public NodeType getNodeType() {
return nodeType;
}
public T getObject() {
return object;
}
/**
* @param leftNode the leftNode to set
*/
public void setLeftNode(Node<T> leftNode) {
this.leftNode = leftNode;
}
/**
* @return the leftNode
*/
public Node<T> getLeftNode() {
return leftNode;
}
/**
* @param rightNode the rightNode to set
*/
public void setRightNode(Node<T> rightNode) {
this.rightNode = rightNode;
}
/**
* @return the rightNode
*/
public Node<T> getRightNode() {
return rightNode;
}
}
public enum NodeType {
SEQ, PAR, LEAF
}
}
package mvd.jester.model;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import mvd.jester.model.DagTask.DagUtils;
import mvd.jester.model.SystemSetup.DagTaskBuilder;
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();
long criticalPath = DagUtils.calculateCriticalPath(jobDag);
for (Job j : jobDag) {
assertTrue(j.getRelativeCompletionTime() <= criticalPath);
}
for (DefaultEdge e : jobDag.edgeSet()) {
Job source = jobDag.getEdgeSource(e);
Job target = jobDag.getEdgeTarget(e);
assertTrue(source.getRelativeCompletionTime() < target.getRelativeCompletionTime());
}
assertTrue(criticalPath == 155);
}
@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);
assertTrue(jobDag.equals(jobDagFromTree));
}
private DirectedAcyclicGraph<Job, DefaultEdge> createJobDag() {
DirectedAcyclicGraph<Job, DefaultEdge> jobDag =
new DirectedAcyclicGraph<>(DefaultEdge.class);
Job source = new Job(20);
Job pathA = new Job(10);
Job pathB = new Job(30);
Job pathC = new Job(40);
Job child1OfA = new Job(5);
Job child2OfA = new Job(15);
Job child3OfA = new Job(5);
Job childsOfAJoin = new Job(10);
Job child1OfC = new Job(5);
Job child2OfC = new Job(10);
Job child3OfC = new Job(15);
Job child4OfC = new Job(20);
Job firstJoin = new Job(20);
Job intermediateFork = new Job(10);
Job forkChild1 = new Job(5);
Job forkChild2 = new Job(10);
Job forkChild3 = new Job(15);
Job sink = new Job(30);
try {
jobDag.addVertex(source);
jobDag.addVertex(pathA);
jobDag.addVertex(pathB);
jobDag.addVertex(pathC);
jobDag.addVertex(child1OfA);
jobDag.addVertex(child2OfA);
jobDag.addVertex(child3OfA);
jobDag.addVertex(childsOfAJoin);
jobDag.addVertex(child1OfC);
jobDag.addVertex(child2OfC);
jobDag.addVertex(child3OfC);
jobDag.addVertex(child4OfC);
jobDag.addVertex(firstJoin);
jobDag.addVertex(intermediateFork);
jobDag.addVertex(forkChild1);
jobDag.addVertex(forkChild2);
jobDag.addVertex(forkChild3);
jobDag.addVertex(sink);
jobDag.addDagEdge(source, pathA);
jobDag.addDagEdge(pathA, child1OfA);
jobDag.addDagEdge(pathA, child2OfA);
jobDag.addDagEdge(pathA, child3OfA);
jobDag.addDagEdge(child1OfA, childsOfAJoin);
jobDag.addDagEdge(child2OfA, childsOfAJoin);
jobDag.addDagEdge(child3OfA, childsOfAJoin);
jobDag.addDagEdge(childsOfAJoin, firstJoin);
jobDag.addDagEdge(source, pathB);
jobDag.addDagEdge(pathB, firstJoin);
jobDag.addDagEdge(source, pathC);
jobDag.addDagEdge(pathC, child1OfC);
jobDag.addDagEdge(pathC, child2OfC);
jobDag.addDagEdge(pathC, child3OfC);
jobDag.addDagEdge(pathC, child4OfC);
jobDag.addDagEdge(child1OfC, firstJoin);
jobDag.addDagEdge(child2OfC, firstJoin);
jobDag.addDagEdge(child3OfC, firstJoin);
jobDag.addDagEdge(child4OfC, firstJoin);
jobDag.addDagEdge(firstJoin, intermediateFork);
jobDag.addDagEdge(intermediateFork, forkChild1);
jobDag.addDagEdge(intermediateFork, forkChild2);
jobDag.addDagEdge(intermediateFork, forkChild3);
jobDag.addDagEdge(forkChild1, sink);
jobDag.addDagEdge(forkChild2, sink);
jobDag.addDagEdge(forkChild3, sink);
} catch (Exception e) {
}
return jobDag;
}
}
package mvd.jester.model; package mvd.jester.model;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import com.google.common.math.LongMath;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
......
...@@ -2,18 +2,10 @@ package mvd.jester.model; ...@@ -2,18 +2,10 @@ package mvd.jester.model;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import javax.imageio.ImageIO;
import com.google.common.math.DoubleMath; import com.google.common.math.DoubleMath;
import com.mxgraph.layout.mxCircleLayout;
import com.mxgraph.layout.mxIGraphLayout;
import com.mxgraph.util.mxCellRenderer;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph; import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.ext.JGraphXAdapter;
import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.DefaultEdge;
import org.junit.Rule; import org.junit.Rule;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
...@@ -86,40 +78,45 @@ public class TestSystemSetup { ...@@ -86,40 +78,45 @@ public class TestSystemSetup {
@Test @Test
@DisplayName("Check if DagTaskBuilder works correctly") @DisplayName("Check if DagTaskBuilder works correctly")
void testDagTaskBuilder() { void testDagTaskBuilder() {
DagTaskBuilder builder = new DagTaskBuilder(); for (int i = 0; i < 100; ++i) {
DirectedAcyclicGraph<Job, DefaultEdge> j = builder.generateTask().getJobDag(); DagTaskBuilder builder = new DagTaskBuilder();
DagTask task = builder.generateTask();
JGraphXAdapter<Job, DefaultEdge> graphAdapter = new JGraphXAdapter<Job, DefaultEdge>(j); DirectedAcyclicGraph<Job, DefaultEdge> jobDag = task.getJobDag();
mxIGraphLayout layout = new mxCircleLayout(graphAdapter);
layout.execute(graphAdapter.getDefaultParent());
BufferedImage image = assertTrue(task.getCriticalPath() <= task.getPeriod());
mxCellRenderer.createBufferedImage(graphAdapter, null, 2, Color.WHITE, true, null); assertTrue(task.getPeriod() <= (long) (task.getWorkload() / builder.getBeta()));
File imgFile = new File("src/test/resources/graph.png"); for (Job j : jobDag) {
try { assertTrue(1 <= j.getWcet() && j.getWcet() <= 100);
ImageIO.write(image, "PNG", imgFile); assertTrue(j.getRelativeCompletionTime() <= task.getCriticalPath());
} catch (Exception e) { if (jobDag.outDegreeOf(j) == 0) {
assertTrue(j.getRelativeCompletionTime() == task.getCriticalPath());
}
}
for (DefaultEdge e : jobDag.edgeSet()) {
Job source = jobDag.getEdgeSource(e);
Job target = jobDag.getEdgeTarget(e);
assertTrue(source.getRelativeCompletionTime() < target.getRelativeCompletionTime());
}
} }
assertTrue(imgFile.exists());
} }
@Test @Test
@DisplayName("Check if utilization works correctly.") @DisplayName("Check if utilization works correctly.")
void testUtil() { void testUtil() {
for (double d = 0.25; d < 4; d += 0.25) { for (int i = 0; i < 5; ++i) {
DagTaskBuilder builder = new DagTaskBuilder(); for (double d = 0.25; d < 4; d += 0.25) {
Set<DagTask> taskSet = builder.generateTaskSet(d); DagTaskBuilder builder = new DagTaskBuilder();
double taskSetUtil = 0; Set<DagTask> taskSet = builder.generateTaskSet(d);
for (DagTask t : taskSet) { double taskSetUtil = 0;
taskSetUtil += t.getUtilization(); for (DagTask t : taskSet) {
} taskSetUtil += t.getUtilization();
}
assertTrue(DoubleMath.fuzzyEquals(taskSetUtil, d, 0.002)); assertTrue(DoubleMath.fuzzyEquals(taskSetUtil, d, 0.002));
}
} }
} }
......
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