Commit a15a466e by Michael Schmid

added binary decomp tree and some changes on tests

parent cdffd7ee
......@@ -211,7 +211,7 @@ public class SystemSetup<T extends Task> {
private long p_par = 80;
private long p_add = 20;
private double getBeta() {
public double getBeta() {
return 0.035 * numberOfProcessors;
}
......@@ -253,7 +253,6 @@ public class SystemSetup<T extends Task> {
fork(jobDag, Optional.of(j), this.depth);
randomEdges(jobDag);
final long workload = DagUtils.calculateWorkload(jobDag);
final long criticalPath = DagUtils.calculateCriticalPath(jobDag);
......
......@@ -4,6 +4,7 @@ import java.math.RoundingMode;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
......@@ -11,6 +12,7 @@ import com.google.common.collect.Lists;
import com.google.common.math.LongMath;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.traverse.BreadthFirstIterator;
import mvd.jester.info.SchedulingInfo;
import mvd.jester.info.TerminationInfo;
import mvd.jester.info.TerminationInfo.Level;
......@@ -22,6 +24,7 @@ import mvd.jester.model.Task;
import mvd.jester.model.DagTask.DagUtils;
import mvd.jester.priority.PriorityManager;
import mvd.jester.priority.RateMonotonic;
import mvd.jester.utils.BinaryDecompositionTree;
public class FonsecaNelis extends AbstractTest<DagTask> {
......@@ -57,14 +60,25 @@ public class FonsecaNelis extends AbstractTest<DagTask> {
private void createNFJandDecompositionTree(SortedTaskSet<DagTask> 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 =
DagUtils.createNFJGraph(t.getJobDag());
// List<Segment> sortedSegment = new LinkedList<>(t.getWorkloadDistribution());
// Collections.sort(sortedSegment,
// (s1, s2) -> (int) (s2.getNumberOfJobs() - s1.getNumberOfJobs()));
// Set<Segment> sortedSet = new LinkedHashSet<>(sortedSegment);
// sortedSegments.put(t, sortedSet);
DagUtils.createNFJGraph(jobDag, forkNodes, joinNodes);
BinaryDecompositionTree<Job> tree =
DagUtils.createDecompositionTree(modifiedJobDag, forkNodes, joinNodes);
}
}
......
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;
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.Test;
......
......@@ -2,18 +2,10 @@ package mvd.jester.model;
import static org.junit.jupiter.api.Assertions.assertTrue;
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.concurrent.ThreadLocalRandom;
import javax.imageio.ImageIO;
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.ext.JGraphXAdapter;
import org.jgrapht.graph.DefaultEdge;
import org.junit.Rule;
import org.junit.jupiter.api.DisplayName;
......@@ -86,40 +78,45 @@ public class TestSystemSetup {
@Test
@DisplayName("Check if DagTaskBuilder works correctly")
void testDagTaskBuilder() {
DagTaskBuilder builder = new DagTaskBuilder();
DirectedAcyclicGraph<Job, DefaultEdge> j = builder.generateTask().getJobDag();
JGraphXAdapter<Job, DefaultEdge> graphAdapter = new JGraphXAdapter<Job, DefaultEdge>(j);
mxIGraphLayout layout = new mxCircleLayout(graphAdapter);
layout.execute(graphAdapter.getDefaultParent());
for (int i = 0; i < 100; ++i) {
DagTaskBuilder builder = new DagTaskBuilder();
DagTask task = builder.generateTask();
DirectedAcyclicGraph<Job, DefaultEdge> jobDag = task.getJobDag();
BufferedImage image =
mxCellRenderer.createBufferedImage(graphAdapter, null, 2, Color.WHITE, true, null);
assertTrue(task.getCriticalPath() <= task.getPeriod());
assertTrue(task.getPeriod() <= (long) (task.getWorkload() / builder.getBeta()));
File imgFile = new File("src/test/resources/graph.png");
try {
ImageIO.write(image, "PNG", imgFile);
} catch (Exception e) {
for (Job j : jobDag) {
assertTrue(1 <= j.getWcet() && j.getWcet() <= 100);
assertTrue(j.getRelativeCompletionTime() <= task.getCriticalPath());
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
@DisplayName("Check if utilization works correctly.")
void testUtil() {
for (double d = 0.25; d < 4; d += 0.25) {
DagTaskBuilder builder = new DagTaskBuilder();
Set<DagTask> taskSet = builder.generateTaskSet(d);
double taskSetUtil = 0;
for (DagTask t : taskSet) {
taskSetUtil += t.getUtilization();
}
for (int i = 0; i < 5; ++i) {
for (double d = 0.25; d < 4; d += 0.25) {
DagTaskBuilder builder = new DagTaskBuilder();
Set<DagTask> taskSet = builder.generateTaskSet(d);
double taskSetUtil = 0;
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