Commit b7ee28b1 authored by Sebastian Vollbrecht's avatar Sebastian Vollbrecht

Some renaming, some code movements.

parent 4ab510cb
......@@ -17,9 +17,7 @@
package graphgen.generator.components.properties.infeasibleMinII;
import graphgen.generator.components.properties.infeasibleMinII.configuration.InfeasibleConfiguration;
import graphgen.generator.components.properties.infeasibleMinII.configuration.StartConfiguration;
import graphgen.generator.components.properties.infeasibleMinII.configuration.SuffixConfiguration;
import graphgen.graph.Resource;
import graphgen.graph.ResourceNode;
import graphgen.util.JavaUtils;
......@@ -30,7 +28,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.stream.IntStream;
public class InfeasibilityInspector {
......@@ -315,29 +312,4 @@ public class InfeasibilityInspector {
return remainingDelays;
}
public static Set<Integer> getProblematicTimeslots(StartConfiguration startCfg,
InfeasibleConfiguration infeasibleCfg,
SuffixConfiguration suffixCfg) {
Set<Integer> possibleTimeSlots = new HashSet<>();
ResourceNode destinationNode = Objects.requireNonNull(startCfg).getDestinationNode();
if (Objects.requireNonNull(infeasibleCfg).getProblematicNodes().contains(destinationNode)) {
possibleTimeSlots.add(0);
return possibleTimeSlots;
}
if (Objects.requireNonNull(suffixCfg).getSuffixNodes().isEmpty()) {
possibleTimeSlots.add(destinationNode.getDelay() + suffixCfg.getRemainingInnerDelay());
return possibleTimeSlots;
} else {
int firstSlot = destinationNode.getDelay();
int lastSlot = firstSlot + suffixCfg.getRemainingInnerDelay();
return JavaUtils.asSet(IntStream.rangeClosed(firstSlot, lastSlot).boxed());
}
}
}
......@@ -38,8 +38,9 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.IntStream;
public class InfeasibleEdgeInspector implements Initializable {
public class InfeasibleCycleEdgePlanner implements Initializable {
private final StartConfiguration startCfg;
private final InfeasibleConfiguration infeasibleCfg;
......@@ -47,13 +48,36 @@ public class InfeasibleEdgeInspector implements Initializable {
private SeededRandom rng;
public InfeasibleEdgeInspector(StartConfiguration startCfg, InfeasibleConfiguration infeasibleCfg,
SuffixConfiguration suffixCfg) {
public InfeasibleCycleEdgePlanner(StartConfiguration startCfg, InfeasibleConfiguration infeasibleCfg,
SuffixConfiguration suffixCfg) {
this.startCfg = startCfg;
this.infeasibleCfg = infeasibleCfg;
this.suffixCfg = suffixCfg;
}
public Set<Integer> getProblematicTimeslots() {
Set<Integer> possibleTimeSlots = new HashSet<>();
ResourceNode destinationNode = Objects.requireNonNull(startCfg).getDestinationNode();
if (Objects.requireNonNull(infeasibleCfg).getProblematicNodes().contains(destinationNode)) {
possibleTimeSlots.add(0);
return possibleTimeSlots;
}
if (Objects.requireNonNull(suffixCfg).getSuffixNodes().isEmpty()) {
possibleTimeSlots.add(destinationNode.getDelay() + suffixCfg.getRemainingInnerDelay());
return possibleTimeSlots;
} else {
int firstSlot = destinationNode.getDelay();
int lastSlot = firstSlot + suffixCfg.getRemainingInnerDelay();
return JavaUtils.asSet(IntStream.rangeClosed(firstSlot, lastSlot).boxed());
}
}
public Set<PlannedEdge> getIncomingEdges() {
Set<PlannedEdge> edges = new HashSet<>();
......@@ -121,6 +145,19 @@ public class InfeasibleEdgeInspector implements Initializable {
}
private static Set<ResourceNode> getPossiblePredecessors(ResourceNode node, StartConfiguration startCfg,
InfeasibleConfiguration infeasibleCfg) {
int nodeDepth = infeasibleCfg.getLayers().getDepth(node.getId());
if (nodeDepth == startCfg.getDestinationNodeLayer() + 1) {
return JavaUtils.asSet(startCfg.getDestinationNode());
} else {
return infeasibleCfg.getZeroNodesByLayer().get(nodeDepth - 1);
}
}
public Set<PlannedEdge> getOutgoingEdges(int problematicTimeslot, Predicate<ResourceNode> nodeNeedsOutgoingEdge,
BiFunction<ResourceNode, ResourceNode, Integer> delayComputer) {
......@@ -196,6 +233,16 @@ public class InfeasibleEdgeInspector implements Initializable {
problematicEdges.add(new PlannedEdge(fixedNode, firstSuffixNode, edgeDelay, 0));
} else {
/*
* A problematic node can only become a backedge source if its ASAP time plus
* its delay exactly matches the maximum inner delay. Otherwise the node would
* introduce slack which would destroy the infeasibility. We need to make sure
* that this does not happen.
*/
if (problematicTimeslot + fixedNode.getDelay() != startCfg.getMaxInnerDelay()) {
throw new IllegalStateException("Node " + fixedNode + " cannot be a backedge source node.");
}
suffixCfg.addBackedgeSource(fixedNode);
}
}
......@@ -345,20 +392,6 @@ public class InfeasibleEdgeInspector implements Initializable {
// Do nothing.
}
public static Set<ResourceNode> getPossiblePredecessors(ResourceNode node, StartConfiguration startCfg,
InfeasibleConfiguration infeasibleCfg) {
int nodeDepth = infeasibleCfg.getLayers().getDepth(node.getId());
if (nodeDepth == startCfg.getDestinationNodeLayer() + 1) {
return JavaUtils.asSet(startCfg.getDestinationNode());
} else {
return infeasibleCfg.getZeroNodesByLayer().get(nodeDepth - 1);
}
}
public static Map<ResourceNode, PlannedEdge> getIncomingEdgesMap(Set<PlannedEdge> edges,
Collection<ResourceNode> relevantNodes) {
Map<ResourceNode, PlannedEdge> incomingEdgesByNode = new HashMap<>();
......
......@@ -31,14 +31,14 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
public class InfeasibleNodePlacer implements Initializable {
public class InfeasibleCycleNodePlacer implements Initializable {
private final StartConfiguration startCfg;
private final InfeasibleConfiguration infeasibleCfg;
private SeededRandom rng;
public InfeasibleNodePlacer(StartConfiguration startCfg, InfeasibleConfiguration infeasibleCfg) {
public InfeasibleCycleNodePlacer(StartConfiguration startCfg, InfeasibleConfiguration infeasibleCfg) {
this.startCfg = startCfg;
this.infeasibleCfg = infeasibleCfg;
}
......
......@@ -35,7 +35,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
......@@ -93,7 +92,6 @@ public class InfeasibleMinIIProperty extends Property {
*/
public InfeasibleMinIIProperty(int minII, int backedgeDelay, int backedgeDistance) {
// TODO: test MinII == 0
if (minII <= 0) {
throw new IllegalArgumentException("The MinII must be greater than zero.");
}
......@@ -135,8 +133,7 @@ public class InfeasibleMinIIProperty extends Property {
Set<Edge<ResourceNode>> tmpEdges = new HashSet<>(edgeCreator.edgeView());
tmpEdges.add(new Edge<>(src, dst, delay, distance));
// TODO: test == instead of <=
return SchedulingUtils.getRecMinII(nodes, tmpEdges) <= minII;
return SchedulingUtils.getRecMinII(nodes, tmpEdges) == minII;
}
......@@ -162,19 +159,18 @@ 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
* either be the destination node or a zero node of the previous layer.
* Also create an incoming edge for every suffix node.
*/
Set<PlannedEdge> plannedEdges = edgeInspector.getIncomingEdges();
InfeasibleCycleEdgePlanner edgePlanner = new InfeasibleCycleEdgePlanner(startCfg, infeasibleCfg, suffixCfg);
edgePlanner.init(rng);
Set<PlannedEdge> plannedEdges = edgePlanner.getIncomingEdges();
/* Choose the timeslot of the problematic nodes (relative to the destination node). */
Set<Integer> possibleTimeslots = InfeasibilityInspector
.getProblematicTimeslots(startCfg, infeasibleCfg, suffixCfg);
Set<Integer> possibleTimeslots = edgePlanner.getProblematicTimeslots();
int problematicTimeslot = JavaUtils.pickRandomElement(possibleTimeslots, rng);
/*
......@@ -182,17 +178,18 @@ public class InfeasibleMinIIProperty extends Property {
* the chosen timeslot. The remaining inner delay will also be distributed over the
* non-problematic edges (e.g. the suffix edges).
*/
Optional<PlannedEdge> lastEdgeRepresentative = edgeInspector.distributeDelay(problematicTimeslot, plannedEdges);
Optional<PlannedEdge> lastEdgeRepresentative = edgePlanner.distributeDelay(problematicTimeslot, plannedEdges);
/*
* Adjust the suffix nodes' offsets (i.e. ASAP-wise from the destination node)
* based on the freshly distributed delay of the edges among them. These are
* useful for the creation of the cycle's required outgoing edges below.
*/
if (lastEdgeRepresentative.isPresent()) {
Map<ResourceNode, PlannedEdge> outgoingEdgesByNode = InfeasibleEdgeInspector
Map<ResourceNode, PlannedEdge> outgoingEdgesByNode = InfeasibleCycleEdgePlanner
.getOutgoingEdgesMap(plannedEdges, suffixCfg.getSuffixNodes());
/*
* Adjust the suffix nodes' offsets (i.e. ASAP-wise from the destination node)
* based on the freshly distributed delay of the edges among them.
*/
int firstSuffixSlot = problematicTimeslot + infeasibleCfg
.getProblematicResource().delay + lastEdgeRepresentative.get().delay;
suffixCfg.setInitialOffset(firstSuffixSlot);
......@@ -207,12 +204,11 @@ public class InfeasibleMinIIProperty extends Property {
* Create the required outgoing edges.
* Note that there is no need to create edges for problematic nodes which have
* been connected to other nodes already (this can happen if they are zero
* nodes themselves) or which will be used as backedge sources.
* nodes themselves).
*/
Predicate<ResourceNode> nodeNeedsOutgoingEdge = n -> plannedEdges.stream()
.noneMatch(e -> e.src == n && e.distance == 0) && !suffixCfg.getBackedgeSources().contains(n);
Set<PlannedEdge> outgoingEdges = edgeInspector
.getOutgoingEdges(problematicTimeslot, nodeNeedsOutgoingEdge, edgeCreator::computeEdgeDelay);
Predicate<ResourceNode> needsOutgoingEdge = n -> plannedEdges.stream().noneMatch(e -> e.src == n);
Set<PlannedEdge> outgoingEdges = edgePlanner
.getOutgoingEdges(problematicTimeslot, needsOutgoingEdge, edgeCreator::computeEdgeDelay);
plannedEdges.addAll(outgoingEdges);
/*
......@@ -221,8 +217,8 @@ public class InfeasibleMinIIProperty extends Property {
plannedEdges.forEach(e -> edgeCreator.createEdge(e.src, e.dst, e.delay));
/*
* Finally, create the backedges going to the destination node, depending on
* whether or not a suffix exists.
* Finally, create the backedges going to the destination node. The backedge
* source selection depends on whether or not a suffix exists.
*/
if (suffixCfg.getSuffixNodes().isEmpty()) {
for (ResourceNode endNode : suffixCfg.getBackedgeSources()) {
......@@ -392,7 +388,7 @@ public class InfeasibleMinIIProperty extends Property {
* could be replaced by zero nodes if a lower problematic node required one to
* be placed in the respective layer.
*/
InfeasibleNodePlacer placer = new InfeasibleNodePlacer(startCfg, infeasibleCfg);
InfeasibleCycleNodePlacer placer = new InfeasibleCycleNodePlacer(startCfg, infeasibleCfg);
placer.init(rng);
for (ResourceNode problematicNode : JavaUtils.asSortedList(infeasibleCfg.getProblematicNodes(), Comparator
......@@ -462,32 +458,6 @@ public class InfeasibleMinIIProperty extends Property {
}
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
* only backedge's source node.
*
* Special care needs to be taken when the suffix is empty and the problematic
* resource's delay is not zero. In this case, every problematic node needs to
* be the source node of a backedge, as they aren't able to connect to any other
* node without exceeding the RecMinII. If the delay is zero however, the
* 'inner' problematic nodes can still connect to each other, hence only the
* lowest problematic nodes need to become backedge sources.
*/
Set<ResourceNode> backedgeSources = new HashSet<>();
if (suffix.isEmpty()) {
if (infeasibleCfg.getProblematicResource().delay == 0) {
backedgeSources.addAll(infeasibleCfg.getLowestProblematicNodes());
} else {
backedgeSources.addAll(infeasibleCfg.getProblematicNodes());
}
} else {
backedgeSources.add(suffix.get(suffix.size() - 1));
}
return suffixCfg;
}
......
......@@ -19,7 +19,6 @@ package graphgen.generator.components.properties.infeasibleMinII;
import graphgen.generator.components.properties.infeasibleMinII.configuration.InfeasibleConfiguration;
import graphgen.generator.components.properties.infeasibleMinII.configuration.StartConfiguration;
import graphgen.generator.components.properties.infeasibleMinII.configuration.SuffixConfiguration;
import graphgen.generator.exceptions.InfeasibilityImpossibleException;
import graphgen.graph.LayerStructure;
import graphgen.graph.Resource;
......@@ -29,10 +28,8 @@ import modsched.Node;
import org.junit.Assert;
import org.junit.Test;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
......@@ -45,7 +42,7 @@ import static org.junit.Assert.fail;
public class InfeasibilityInspectorTest {
@Test
public void getPossibleLayers_ZeroDelay() {
public void possibleLayers_ZeroDelay() {
Map<Integer, Integer> depthsByID = new HashMap<>();
depthsByID.put(2, 0);
depthsByID.put(3, 1);
......@@ -85,7 +82,7 @@ public class InfeasibilityInspectorTest {
infeasibleCfg.fixateNode(node2);
// Now try to place node 6 in different target layers.
InfeasibleNodePlacer placer = new InfeasibleNodePlacer(startCfg, infeasibleCfg);
InfeasibleCycleNodePlacer placer = new InfeasibleCycleNodePlacer(startCfg, infeasibleCfg);
assertEquals(JavaUtils.asSet(1, 2, 3, 4), placer.getPossibleLayers(node6));
// Now assume that node 6 has been fixed already - locking zero nodes 3 and 4 in place as well.
......@@ -103,7 +100,7 @@ public class InfeasibilityInspectorTest {
}
@Test
public void getPossibleLayers_NonZeroDelay_Possible() {
public void possibleLayers_NonZeroDelay_Possible() {
Map<Integer, Integer> depthsByID = new HashMap<>();
depthsByID.put(2, 0);
depthsByID.put(3, 1);
......@@ -142,7 +139,7 @@ public class InfeasibilityInspectorTest {
infeasibleCfg.fixateNode(node3);
// Now try to place node 2 in different target layers.
InfeasibleNodePlacer placer = new InfeasibleNodePlacer(startCfg, infeasibleCfg);
InfeasibleCycleNodePlacer placer = new InfeasibleCycleNodePlacer(startCfg, infeasibleCfg);
assertEquals(JavaUtils.asSet(2, 3, 4), placer.getPossibleLayers(node2));
// Now assume that node 6 has been fixed again - locking zero node 4 in place as well.
......@@ -160,7 +157,7 @@ public class InfeasibilityInspectorTest {
}
@Test
public void getPossibleLayers_NonZeroDelay_Impossible() {
public void possibleLayers_NonZeroDelay_Impossible() {
Map<Integer, Integer> depthsByID = new HashMap<>();
depthsByID.put(2, 0);
depthsByID.put(3, 1);
......@@ -200,7 +197,7 @@ public class InfeasibilityInspectorTest {
infeasibleCfg.fixateNode(node3);
// Now try to place node 2 in different target layers.
InfeasibleNodePlacer placer = new InfeasibleNodePlacer(startCfg, infeasibleCfg);
InfeasibleCycleNodePlacer placer = new InfeasibleCycleNodePlacer(startCfg, infeasibleCfg);
assertTrue(placer.getPossibleLayers(node2).isEmpty());
// Now assume that node 6 has been fixed again - locking zero node 4 in place as well.
......@@ -225,7 +222,7 @@ public class InfeasibilityInspectorTest {
}
@Test
public void getPossibleLayers_BogusArguments() {
public void possibleLayers_BogusArguments() {
Map<Integer, Integer> depthsByID = new HashMap<>();
depthsByID.put(2, 0);
depthsByID.put(3, 1);
......@@ -264,7 +261,7 @@ public class InfeasibilityInspectorTest {
// Assume that node 3 is a problematic destination node.
infeasibleCfg.fixateNode(node3);
InfeasibleNodePlacer placer = new InfeasibleNodePlacer(startCfg, infeasibleCfg);
InfeasibleCycleNodePlacer placer = new InfeasibleCycleNodePlacer(startCfg, infeasibleCfg);
try {
placer.getPossibleLayers(null);
......@@ -281,7 +278,7 @@ public class InfeasibilityInspectorTest {
}
@Test
public void getProblematicResources_Limits() {
public void problematicResources_Limits() {
Resource problematic1 = new Resource("problematic1", 0, 1);
Resource problematic2 = new Resource("problematic2", 0, 5);
Resource unproblematic1 = new Resource("unproblematic1", 0);
......@@ -335,7 +332,7 @@ public class InfeasibilityInspectorTest {
}
@Test
public void getProblematicResources_Delays() {
public void problematicResources_Delays() {
int limit = 2;
......@@ -372,7 +369,7 @@ public class InfeasibilityInspectorTest {
}
@Test
public void getProblematicResources_BogusArguments() {
public void problematicResources_BogusArguments() {
int limit = 2;
......@@ -394,321 +391,4 @@ public class InfeasibilityInspectorTest {
}
@Test
public void getProblematicTimeslots_ZeroDelay() {
Resource problematic = new Resource("problematic", 0, 2);
Resource unlimited = new Resource("unlimited", 0);
Map<Integer, Integer> depthsByID = new HashMap<>();
depthsByID.put(2, 0);
depthsByID.put(3, 1);
depthsByID.put(4, 2);
depthsByID.put(5, 2);
depthsByID.put(6, 3);
depthsByID.put(7, 3);
depthsByID.put(8, 4);
depthsByID.put(9, 5);
LayerStructure layers = new LayerStructure(depthsByID);
ResourceNode node2 = new ResourceNode(2, unlimited);
ResourceNode node3 = new ResourceNode(3, unlimited);
ResourceNode node4 = new ResourceNode(4, problematic);
ResourceNode node5 = new ResourceNode(5, unlimited);
ResourceNode node6 = new ResourceNode(6, problematic);
ResourceNode node7 = new ResourceNode(7, unlimited);
ResourceNode node8 = new ResourceNode(8, problematic);
ResourceNode node9 = new ResourceNode(9, unlimited);
Set<ResourceNode> nodes = JavaUtils.asSet(node2, node3, node4, node5, node6, node7, node8, node9);
Map<Integer, ResourceNode> nodeTable = nodes.stream().collect(Collectors.toMap(Node::getId, n -> n));
/* Assume a MinII of 5 with the RecMinII-ensuring backedge having a delay of 1 and a distance of 1.*/
StartConfiguration startCfg = new StartConfiguration(layers, nodeTable, problematic, 4);
startCfg.setDestinationNode(node3);
startCfg.setDestinationNodeLayer(1);
InfeasibleConfiguration infeasibleCfg = new InfeasibleConfiguration(startCfg);
infeasibleCfg.addProblematicNode(node4);
infeasibleCfg.addProblematicNode(node6);
infeasibleCfg.addProblematicNode(node8);
infeasibleCfg.fixateNode(node3);
infeasibleCfg.fixateNode(node4);
infeasibleCfg.fixateNode(node6);
infeasibleCfg.fixateNode(node8);
List<ResourceNode> suffixNodes = Collections.singletonList(node9);
Set<ResourceNode> backedgeSources = new HashSet<>(suffixNodes);
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);
assertTrue(timeslots.contains(0));
assertTrue(timeslots.contains(1));
assertTrue(timeslots.contains(2));
assertTrue(timeslots.contains(3));
assertTrue(timeslots.contains(4));
assertEquals(5, timeslots.size());
}
@Test
public void getProblematicTimeslots_NonZeroDelay() {
Resource problematic = new Resource("problematic", 2, 2);
Resource unlimited = new Resource("unlimited", 0);
Map<Integer, Integer> depthsByID = new HashMap<>();
depthsByID.put(2, 0);
depthsByID.put(3, 1);
depthsByID.put(4, 2);
depthsByID.put(5, 2);
depthsByID.put(6, 3);
depthsByID.put(7, 3);
depthsByID.put(8, 4);
depthsByID.put(9, 5);
LayerStructure layers = new LayerStructure(depthsByID);
ResourceNode node2 = new ResourceNode(2, unlimited);
ResourceNode node3 = new ResourceNode(3, unlimited);
ResourceNode node4 = new ResourceNode(4, problematic);
ResourceNode node5 = new ResourceNode(5, unlimited);
ResourceNode node6 = new ResourceNode(6, problematic);
ResourceNode node7 = new ResourceNode(7, unlimited);
ResourceNode node8 = new ResourceNode(8, problematic);
ResourceNode node9 = new ResourceNode(9, unlimited);
Set<ResourceNode> nodes = JavaUtils.asSet(node2, node3, node4, node5, node6, node7, node8, node9);
Map<Integer, ResourceNode> nodeTable = nodes.stream().collect(Collectors.toMap(Node::getId, n -> n));
/* Assume a MinII of 5 with the RecMinII-ensuring backedge having a delay of 1 and a distance of 1.*/
StartConfiguration startCfg = new StartConfiguration(layers, nodeTable, problematic, 4);
startCfg.setDestinationNode(node3);
startCfg.setDestinationNodeLayer(1);
InfeasibleConfiguration infeasibleCfg = new InfeasibleConfiguration(startCfg);
infeasibleCfg.addProblematicNode(node4);
infeasibleCfg.addProblematicNode(node6);
infeasibleCfg.addProblematicNode(node8);
infeasibleCfg.fixateNode(node3);
infeasibleCfg.fixateNode(node4);
infeasibleCfg.fixateNode(node5);
infeasibleCfg.fixateNode(node6);
infeasibleCfg.fixateNode(node7);
infeasibleCfg.fixateNode(node8);
List<ResourceNode> suffixNodes = Collections.singletonList(node9);
Set<ResourceNode> backedgeSources = new HashSet<>(suffixNodes);
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);
assertTrue(timeslots.contains(0));
assertTrue(timeslots.contains(1));
assertTrue(timeslots.contains(2));
assertEquals(3, timeslots.size());
}
@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(