Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
las3_pub
/
jester
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
a15a466e
authored
4 years ago
by
Michael Schmid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added binary decomp tree and some changes on tests
parent
cdffd7ee
master
…
scheduler
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
515 additions
and
74 deletions
+515
-74
src/main/java/mvd/jester/model/DagTask.java
+220
-33
src/main/java/mvd/jester/model/SystemSetup.java
+1
-2
src/main/java/mvd/jester/tests/FonsecaNelis.java
+21
-7
src/main/java/mvd/jester/utils/BinaryDecompositionTree.java
+107
-0
src/test/java/mvd/jester/model/TestDagUtils.java
+138
-0
src/test/java/mvd/jester/model/TestSegment.java
+0
-1
src/test/java/mvd/jester/model/TestSystemSetup.java
+28
-31
No files found.
src/main/java/mvd/jester/model/DagTask.java
View file @
a15a466e
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.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
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
{
...
...
@@ -115,6 +122,10 @@ public class DagTask implements Task {
public
static
long
calculateCriticalPath
(
DirectedAcyclicGraph
<
Job
,
DefaultEdge
>
jobDag
)
{
long
criticalPath
=
0
;
// BreadthFirstIterator<Job, DefaultEdge> breadthFirstIterator =
// new BreadthFirstIterator<>(jobDag);
// while (breadthFirstIterator.hasNext()) {
// Job job = breadthFirstIterator.next();
for
(
Job
job
:
jobDag
)
{
Set
<
DefaultEdge
>
edges
=
jobDag
.
incomingEdgesOf
(
job
);
long
longestRelativeCompletionTime
=
0
;
...
...
@@ -161,25 +172,37 @@ public class DagTask implements Task {
public
static
DirectedAcyclicGraph
<
Job
,
DefaultEdge
>
createNFJGraph
(
DirectedAcyclicGraph
<
Job
,
DefaultEdge
>
jobDag
)
{
DirectedAcyclicGraph
<
Job
,
DefaultEdge
>
modifiedJobDag
=
new
DirectedAcyclicGraph
<>(
DefaultEdge
.
class
);
Graphs
.
addGraph
(
modifiedJobDag
,
jobDag
);
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
=
new
BreadthFirstIterator
<>(
modifiedJobDag
);
while
(
breadthFirstIterator
.
hasNext
())
{
Job
j
=
breadthFirstIterator
.
next
();
if
(
modifiedJobDag
.
inDegreeOf
(
j
)
>
1
)
{
public
static
void
collectForksAndJoins
(
DirectedAcyclicGraph
<
Job
,
DefaultEdge
>
jobDag
,
LinkedList
<
Job
>
forkNodes
,
LinkedList
<
Job
>
joinNodes
)
{
for
(
Job
j
:
jobDag
)
{
if
(
jobDag
.
inDegreeOf
(
j
)
>
1
)
{
joinNodes
.
add
(
j
);
}
if
(
modifiedJ
obDag
.
outDegreeOf
(
j
)
>
1
)
{
if
(
j
obDag
.
outDegreeOf
(
j
)
>
1
)
{
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
)
{
Set
<
DefaultEdge
>
edgeSet
=
new
HashSet
<>(
modifiedJobDag
.
incomingEdgesOf
(
j
));
...
...
@@ -201,34 +224,107 @@ public class DagTask implements Task {
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
;
}
private
static
boolean
checkProperty1
(
DirectedAcyclicGraph
<
Job
,
DefaultEdge
>
jobDag
)
{
public
static
BinaryDecompositionTree
<
Job
>
createDecompositionTree
(
DirectedAcyclicGraph
<
Job
,
DefaultEdge
>
jobDag
)
{
LinkedList
<
Job
>
joinNodes
=
new
LinkedList
<>();
List
<
Job
>
forkNodes
=
new
LinkedList
<>();
Li
nkedLi
st
<
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
);
collectForksAndJoins
(
jobDag
,
forkNodes
,
joinNodes
);
return
createDecompositionTree
(
jobDag
,
forkNodes
,
joinNodes
);
}
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
);
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
)
{
...
...
@@ -257,14 +353,29 @@ public class DagTask implements Task {
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
,
Job
joinNode
,
List
<
Job
>
forkNodes
,
Job
job
)
{
List
<
Job
>
pred
=
Graphs
.
predecessorListOf
(
jobDag
,
job
);
for
(
Job
p
:
pred
)
{
if
(
forkNodes
.
contains
(
p
))
{
for
(
DefaultEdge
successorEdge
:
jobDag
.
outgoingEdgesOf
(
p
))
{
Job
successor
=
jobDag
.
getEdgeSource
(
successorEdge
);
for
(
Job
successor
:
Graphs
.
successorListOf
(
jobDag
,
p
))
{
if
(
jobDag
.
getAncestors
(
jobDag
,
joinNode
).
contains
(
successor
))
{
return
false
;
}
...
...
@@ -277,5 +388,81 @@ public class DagTask implements Task {
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
}
}
}
This diff is collapsed.
Click to expand it.
src/main/java/mvd/jester/model/SystemSetup.java
View file @
a15a466e
...
...
@@ -211,7 +211,7 @@ public class SystemSetup<T extends Task> {
private
long
p_par
=
80
;
private
long
p_add
=
20
;
p
rivate
double
getBeta
()
{
p
ublic
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
);
...
...
This diff is collapsed.
Click to expand it.
src/main/java/mvd/jester/tests/FonsecaNelis.java
View file @
a15a466e
...
...
@@ -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
);
}
}
...
...
This diff is collapsed.
Click to expand it.
src/main/java/mvd/jester/utils/BinaryDecompositionTree.java
0 → 100644
View file @
a15a466e
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
}
}
This diff is collapsed.
Click to expand it.
src/test/java/mvd/jester/model/TestDagUtils.java
0 → 100644
View file @
a15a466e
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
;
}
}
This diff is collapsed.
Click to expand it.
src/test/java/mvd/jester/model/TestSegment.java
View file @
a15a466e
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
;
...
...
This diff is collapsed.
Click to expand it.
src/test/java/mvd/jester/model/TestSystemSetup.java
View file @
a15a466e
...
...
@@ -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
));
}
}
}
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment