Commit 3b366dce authored by Sebastian Vollbrecht's avatar Sebastian Vollbrecht

Fixed a bug which caused the problematic nodes to not be problematic at all.

The culprit was the way the remaining delay had been distributed over the edges connecting them with each other.
parent fcb6b038
......@@ -328,11 +328,16 @@ public class InfeasibilityInspector {
return possibleTimeSlots;
}
int firstSlot = destinationNode.getDelay();
int lastSlot = firstSlot + Objects.requireNonNull(suffixCfg).getRemainingInnerDelay();
if (Objects.requireNonNull(suffixCfg).getSuffixNodes().isEmpty()) {
possibleTimeSlots.add(suffixCfg.getRemainingInnerDelay());
return possibleTimeSlots;
} else {
return JavaUtils.asSet(IntStream.rangeClosed(firstSlot, lastSlot).boxed());
int firstSlot = destinationNode.getDelay();
int lastSlot = firstSlot + suffixCfg.getRemainingInnerDelay();
return JavaUtils.asSet(IntStream.rangeClosed(firstSlot, lastSlot).boxed());
}
}
}
......@@ -28,6 +28,7 @@ import graphgen.util.JavaUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
......@@ -195,7 +196,7 @@ public class InfeasibleEdgeInspector implements Initializable {
problematicEdges.add(new PlannedEdge(fixedNode, firstSuffixNode, edgeDelay, 0));
} else {
suffixCfg.getBackedgeSources().add(fixedNode);
suffixCfg.addBackedgeSource(fixedNode);
}
}
......@@ -215,6 +216,10 @@ public class InfeasibleEdgeInspector implements Initializable {
if (problematicTimeslot < 0) {
throw new IllegalArgumentException("The problematic nodes' timeslot cannot be negative.");
} else if (problematicTimeslot + infeasibleCfg.getProblematicResource().delay > infeasibleCfg
.getMaxInnerDelay()) {
throw new IllegalArgumentException(
"Placing the nodes in the specified timeslot would exceed the maximum inner delay.");
}
Map<ResourceNode, PlannedEdge> incomingEdgesByNode = getIncomingEdgesMap(edges, infeasibleCfg.getFixedNodes());
......@@ -233,7 +238,15 @@ public class InfeasibleEdgeInspector implements Initializable {
/* The set of edges whose delay must not change anymore to not destroy the infeasibility. */
Set<PlannedEdge> fixedEdges = new HashSet<>();
for (ResourceNode node : infeasibleCfg.getProblematicNodes()) {
/*
* Make every problematic node's timeslot problematic (i.e. distribute the
* required delay over the edges leading to it). We must sort the nodes by their
* depth so that possible problematic zero nodes will be handled before their
* successors. Otherwise it might be possible for the summed delay (zero
* node plus the delay to the successor) to exceed the required delay.
*/
for (ResourceNode node : JavaUtils.asSortedList(infeasibleCfg.getProblematicNodes(), Comparator
.comparingInt(n -> infeasibleCfg.getLayers().getDepth(n.getId())))) {
makeNodeSlotProblematic(node, problematicEdgesDelay, incomingEdgesByNode, fixedEdges);
}
......
......@@ -31,7 +31,6 @@ import graphgen.util.JavaUtils;
import graphgen.util.SchedulingUtils;
import modsched.Edge;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
......@@ -164,6 +163,7 @@ public class InfeasibleMinIIProperty extends Property {
SuffixConfiguration suffixCfg = chooseSuffixConfiguration(startCfg, infeasibleCfg);
InfeasibleEdgeInspector edgeInspector = new InfeasibleEdgeInspector(startCfg, infeasibleCfg, suffixCfg);
edgeInspector.init(rng);
/*
* We need to create an incoming edge for all fixed nodes. The source node can
......@@ -395,8 +395,8 @@ public class InfeasibleMinIIProperty extends Property {
InfeasibleNodePlacer placer = new InfeasibleNodePlacer(startCfg, infeasibleCfg);
placer.init(rng);
for (ResourceNode problematicNode : JavaUtils
.asSortedList(infeasibleCfg.getProblematicNodes(), Comparator.comparingInt(layers::getDepth))) {
for (ResourceNode problematicNode : JavaUtils.asSortedList(infeasibleCfg.getProblematicNodes(), Comparator
.comparingInt(n -> layers.getDepth(n.getId())))) {
/*
* If a problematic node has been fixed already, we don't need to place it
......@@ -424,7 +424,7 @@ public class InfeasibleMinIIProperty extends Property {
private SuffixConfiguration chooseSuffixConfiguration(StartConfiguration startCfg,
InfeasibleConfiguration infeasibleCfg) {
List<ResourceNode> suffixNodes = new ArrayList<>();
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
int remainingInnerDelay = maxInnerDelay - startCfg.getProblematicResource().delay - startCfg
.getDestinationNode().getDelay();
......@@ -463,11 +463,13 @@ public class InfeasibleMinIIProperty extends Property {
* inner delay accordingly.
*/
ResourceNode candidate = JavaUtils.pickRandomElement(candidates, rng);
suffixNodes.add(candidate);
suffixCfg.appendSuffixNode(candidate);
remainingInnerDelay -= candidate.getDelay();
}
List<ResourceNode> suffix = suffixCfg.getSuffixNodes();
/*
* If no suffix has been created, all problematic end nodes must become backedge
* sources themselves. Otherwise, the very last suffix node will be used as the
......@@ -482,17 +484,17 @@ public class InfeasibleMinIIProperty extends Property {
*/
Set<ResourceNode> backedgeSources = new HashSet<>();
if (suffixNodes.isEmpty()) {
if (suffix.isEmpty()) {
if (infeasibleCfg.getProblematicResource().delay == 0) {
backedgeSources.addAll(infeasibleCfg.getLowestProblematicNodes());
} else {
backedgeSources.addAll(infeasibleCfg.getProblematicNodes());
}
} else {
backedgeSources.add(suffixNodes.get(suffixNodes.size() - 1));
backedgeSources.add(suffix.get(suffix.size() - 1));
}
return new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
return suffixCfg;
}
}
\ No newline at end of file
......@@ -21,8 +21,10 @@ import graphgen.generator.components.properties.util.PlannedEdge;
import graphgen.graph.ResourceNode;
import modsched.Node;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
......@@ -40,14 +42,15 @@ public class SuffixConfiguration extends Configuration {
*/
private final Map<ResourceNode, Integer> suffixOffsets;
private final StartConfiguration startCfg;
private final InfeasibleConfiguration infeasibleCfg;
public SuffixConfiguration(List<ResourceNode> suffixNodes, Set<ResourceNode> backedgeSources,
StartConfiguration startCfg) {
public SuffixConfiguration(StartConfiguration startCfg, InfeasibleConfiguration infeasibleCfg) {
super(Objects.requireNonNull(startCfg));
this.suffixNodes = Objects.requireNonNull(suffixNodes);
this.backedgeSources = Objects.requireNonNull(backedgeSources);
this.suffixNodes = new ArrayList<>();
this.backedgeSources = new HashSet<>();
this.suffixOffsets = new HashMap<>();
this.startCfg = startCfg;
this.infeasibleCfg = Objects.requireNonNull(infeasibleCfg);
}
......@@ -60,6 +63,24 @@ public class SuffixConfiguration extends Configuration {
suffixOffsets.put(suffixNodes.get(0), offset);
}
public void appendSuffixNode(ResourceNode suffixNode) {
if (getRemainingInnerDelay() - suffixNode.getDelay() < 0) {
throw new IllegalArgumentException(
"Appending node " + suffixNode + " to the suffix would exceed the maximum inner delay.");
}
suffixNodes.add(suffixNode);
}
public void addBackedgeSource(ResourceNode backedgeSource) {
if (!infeasibleCfg.getProblematicNodes().contains(backedgeSource)) {
if (suffixNodes.isEmpty() || backedgeSource != suffixNodes.get(suffixNodes.size() - 1)) {
throw new IllegalArgumentException(
"Only the last suffix node or problematic nodes themselves can be backedge sources.");
}
}
backedgeSources.add(backedgeSource);
}
public void addPlannedEdge(PlannedEdge edge) {
if (!suffixNodes.contains(Objects.requireNonNull(edge).src) || !suffixNodes.contains(edge.dst)) {
throw new IllegalArgumentException("The edge does not affect any suffix node.");
......
......@@ -37,9 +37,9 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class InfeasibilityInspectorTest {
......@@ -443,7 +443,9 @@ public class InfeasibilityInspectorTest {
List<ResourceNode> suffixNodes = Collections.singletonList(node9);
Set<ResourceNode> backedgeSources = new HashSet<>(suffixNodes);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
// Calculate possible timeslots for the problematic nodes (relative to the destination node).
Set<Integer> timeslots = InfeasibilityInspector.getProblematicTimeslots(startCfg, infeasibleCfg, suffixCfg);
......@@ -509,7 +511,9 @@ public class InfeasibilityInspectorTest {
List<ResourceNode> suffixNodes = Collections.singletonList(node9);
Set<ResourceNode> backedgeSources = new HashSet<>(suffixNodes);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
// Calculate possible timeslots for the problematic nodes (relative to the destination node).
Set<Integer> timeslots = InfeasibilityInspector.getProblematicTimeslots(startCfg, infeasibleCfg, suffixCfg);
......@@ -522,6 +526,62 @@ public class InfeasibilityInspectorTest {
}
@Test
public void getProblematicTimeSlots_ZeroDelay_NoSuffix() {
Resource problematic = new Resource("problematic", 0, 3);
Resource unlimited = new Resource("unlimited", 0);
Map<Integer, Integer> depthsByID = new HashMap<>();
depthsByID.put(2, 0);
depthsByID.put(3, 3);
depthsByID.put(4, 2);
depthsByID.put(5, 1);
depthsByID.put(6, 1);
LayerStructure layers = new LayerStructure(depthsByID);
ResourceNode node2 = new ResourceNode(2, unlimited);
ResourceNode node3 = new ResourceNode(3, problematic);
ResourceNode node4 = new ResourceNode(4, problematic);
ResourceNode node5 = new ResourceNode(5, problematic);
ResourceNode node6 = new ResourceNode(6, problematic);
Set<ResourceNode> nodes = JavaUtils.asSet(node2, node3, node4, node5, node6);
Map<Integer, ResourceNode> nodeTable = nodes.stream().collect(Collectors.toMap(Node::getId, n -> n));
/* Assume a MinII of 3 with the RecMinII-ensuring backedge having a delay of 1 and a distance of 1.*/
StartConfiguration startCfg = new StartConfiguration(layers, nodeTable, problematic, 2);
startCfg.setDestinationNode(node2);
startCfg.setDestinationNodeLayer(0);
InfeasibleConfiguration infeasibleCfg = new InfeasibleConfiguration(startCfg);
infeasibleCfg.addProblematicNode(node3);
infeasibleCfg.addProblematicNode(node4);
infeasibleCfg.addProblematicNode(node5);
infeasibleCfg.addProblematicNode(node6);
infeasibleCfg.fixateNode(node2);
infeasibleCfg.fixateNode(node3);
infeasibleCfg.fixateNode(node4);
infeasibleCfg.fixateNode(node5);
infeasibleCfg.fixateNode(node6);
List<ResourceNode> suffixNodes = Collections.emptyList();
Set<ResourceNode> backedgeSources = JavaUtils.asSet(node3);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
// The problematic timeslot cannot be anything else but 2.
assertEquals(JavaUtils.asSet(2),
InfeasibilityInspector.getProblematicTimeslots(startCfg, infeasibleCfg, suffixCfg)
);
}
@Test
public void getProblematicTimeslots_NonZeroDestinationNodeDelay() {
......@@ -574,7 +634,9 @@ public class InfeasibilityInspectorTest {
List<ResourceNode> suffixNodes = Collections.singletonList(node9);
Set<ResourceNode> backedgeSources = new HashSet<>(suffixNodes);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
// Calculate possible timeslots for the problematic nodes (relative to the destination node).
Set<Integer> timeslots = InfeasibilityInspector.getProblematicTimeslots(startCfg, infeasibleCfg, suffixCfg);
......@@ -636,7 +698,9 @@ public class InfeasibilityInspectorTest {
List<ResourceNode> suffixNodes = Collections.singletonList(node9);
Set<ResourceNode> backedgeSources = new HashSet<>(suffixNodes);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
// Calculate possible timeslots for the problematic nodes (relative to the destination node).
Set<Integer> timeslots = InfeasibilityInspector.getProblematicTimeslots(startCfg, infeasibleCfg, suffixCfg);
......
......@@ -39,6 +39,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class InfeasibleEdgeInspectorTest {
......@@ -93,7 +94,9 @@ public class InfeasibleEdgeInspectorTest {
List<ResourceNode> suffixNodes = new ArrayList<>();
Set<ResourceNode> backedgeSources = JavaUtils.asSet(node4, node6, node8);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
InfeasibleEdgeInspector inspector = new InfeasibleEdgeInspector(startCfg, infeasibleCfg, suffixCfg);
......@@ -164,7 +167,9 @@ public class InfeasibleEdgeInspectorTest {
List<ResourceNode> suffixNodes = Arrays.asList(node9, node10);
Set<ResourceNode> backedgeSources = JavaUtils.asSet(node10);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
InfeasibleEdgeInspector inspector = new InfeasibleEdgeInspector(startCfg, infeasibleCfg, suffixCfg);
......@@ -234,7 +239,9 @@ public class InfeasibleEdgeInspectorTest {
List<ResourceNode> suffixNodes = new ArrayList<>();
Set<ResourceNode> backedgeSources = JavaUtils.asSet(node8);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
InfeasibleEdgeInspector inspector = new InfeasibleEdgeInspector(startCfg, infeasibleCfg, suffixCfg);
......@@ -300,7 +307,9 @@ public class InfeasibleEdgeInspectorTest {
List<ResourceNode> suffixNodes = Collections.singletonList(node9);
Set<ResourceNode> backedgeSources = JavaUtils.asSet(node9);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
InfeasibleEdgeInspector inspector = new InfeasibleEdgeInspector(startCfg, infeasibleCfg, suffixCfg);
......@@ -370,7 +379,9 @@ public class InfeasibleEdgeInspectorTest {
List<ResourceNode> suffixNodes = Arrays.asList(node9, node10);
Set<ResourceNode> backedgeSources = JavaUtils.asSet(node10);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
InfeasibleEdgeInspector inspector = new InfeasibleEdgeInspector(startCfg, infeasibleCfg, suffixCfg);
......@@ -401,6 +412,88 @@ public class InfeasibleEdgeInspectorTest {
}
@Test
public void distributeDelay_ZeroDelay_NoSuffix() {
Resource problematic = new Resource("problematic", 0, 3);
Resource unlimited = new Resource("unlimited", 0);
Map<Integer, Integer> depthsByID = new HashMap<>();
depthsByID.put(2, 0);
depthsByID.put(3, 3);
depthsByID.put(4, 2);
depthsByID.put(5, 1);
depthsByID.put(6, 1);
LayerStructure layers = new LayerStructure(depthsByID);
ResourceNode node2 = new ResourceNode(2, unlimited);
ResourceNode node3 = new ResourceNode(3, problematic);
ResourceNode node4 = new ResourceNode(4, problematic);
ResourceNode node5 = new ResourceNode(5, problematic);
ResourceNode node6 = new ResourceNode(6, problematic);
Set<ResourceNode> nodes = JavaUtils.asSet(node2, node3, node4, node5, node6);
Map<Integer, ResourceNode> nodeTable = nodes.stream().collect(Collectors.toMap(Node::getId, n -> n));
/* Assume a MinII of 3 with the RecMinII-ensuring backedge having a delay of 1 and a distance of 1.*/
StartConfiguration startCfg = new StartConfiguration(layers, nodeTable, problematic, 2);
startCfg.setDestinationNode(node2);
startCfg.setDestinationNodeLayer(0);
InfeasibleConfiguration infeasibleCfg = new InfeasibleConfiguration(startCfg);
infeasibleCfg.addProblematicNode(node3);
infeasibleCfg.addProblematicNode(node4);
infeasibleCfg.addProblematicNode(node5);
infeasibleCfg.addProblematicNode(node6);
infeasibleCfg.fixateNode(node2);
infeasibleCfg.fixateNode(node3);
infeasibleCfg.fixateNode(node4);
infeasibleCfg.fixateNode(node5);
infeasibleCfg.fixateNode(node6);
List<ResourceNode> suffixNodes = Collections.emptyList();
Set<ResourceNode> backedgeSources = JavaUtils.asSet(node3);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
InfeasibleEdgeInspector inspector = new InfeasibleEdgeInspector(startCfg, infeasibleCfg, suffixCfg);
inspector.init(new SeededRandom(42));
PlannedEdge edge2_5 = new PlannedEdge(node2, node5, 0, 0);
PlannedEdge edge2_6 = new PlannedEdge(node2, node6, 0, 0);
PlannedEdge edge5_4 = new PlannedEdge(node5, node4, 0, 0);
PlannedEdge edge6_4 = new PlannedEdge(node6, node4, 0, 0);
PlannedEdge edge4_3 = new PlannedEdge(node4, node3, 0, 0);
Set<PlannedEdge> edges_using_5_4 = JavaUtils.asSet(edge2_5, edge2_6, edge5_4, edge4_3);
Set<PlannedEdge> edges_using_6_4 = JavaUtils.asSet(edge2_5, edge2_6, edge6_4, edge4_3);
Set<PlannedEdge> edges = inspector.getIncomingEdges();
boolean containsEdge5_4 = edges.equals(edges_using_5_4);
boolean containsEdge6_4 = edges.equals(edges_using_6_4);
assertTrue(containsEdge5_4 ^ containsEdge6_4);
// The problematic timeslot cannot be anything else but 2.
inspector.distributeDelay(2, containsEdge5_4 ? edges_using_5_4 : edges_using_6_4);
assertEquals(2, edge2_5.delay);
assertEquals(2, edge2_6.delay);
if (containsEdge5_4) {
assertEquals(2, edge2_5.delay + edge5_4.delay + edge4_3.delay);
} else {
assertEquals(2, edge2_6.delay + edge6_4.delay + edge4_3.delay);
}
}
@Test
public void distributeDelay_ProblematicDestinationNode_WithSuffix() {
......@@ -453,7 +546,9 @@ public class InfeasibleEdgeInspectorTest {
List<ResourceNode> suffixNodes = Arrays.asList(node9, node10);
Set<ResourceNode> backedgeSources = JavaUtils.asSet(node10);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
InfeasibleEdgeInspector inspector = new InfeasibleEdgeInspector(startCfg, infeasibleCfg, suffixCfg);
......@@ -531,7 +626,9 @@ public class InfeasibleEdgeInspectorTest {
List<ResourceNode> suffixNodes = Arrays.asList(node7, node9, node10);
Set<ResourceNode> backedgeSources = JavaUtils.asSet(node10);
SuffixConfiguration suffixCfg = new SuffixConfiguration(suffixNodes, backedgeSources, startCfg);
SuffixConfiguration suffixCfg = new SuffixConfiguration(startCfg, infeasibleCfg);
suffixNodes.forEach(suffixCfg::appendSuffixNode);
backedgeSources.forEach(suffixCfg::addBackedgeSource);
InfeasibleEdgeInspector inspector = new InfeasibleEdgeInspector(startCfg, infeasibleCfg, suffixCfg);
......
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 to comment