Commit 2cd22311 authored by Sebastian Vollbrecht's avatar Sebastian Vollbrecht

Further refactoring of the InfeasibleMinIIProperty generation.

- removed unused distance parameter of planned edges
- restructured the configuration classes & added more useful methods
- renamed and restructured former InfeasibilityInspector and its methods
- fixed a bug which resulted in feasible MinIIs due to non-problematic zero nodes being used although problematic ones should have been used
- added many new test cases
parent b9924aeb
...@@ -481,7 +481,7 @@ public class FeasibleMinIIProperty extends Property { ...@@ -481,7 +481,7 @@ public class FeasibleMinIIProperty extends Property {
remainingPathDelay -= edgeDelay; remainingPathDelay -= edgeDelay;
path.appendEdge(new PlannedEdge(firstSrc, firstDst, edgeDelay, 0)); path.appendEdge(new PlannedEdge(firstSrc, firstDst, edgeDelay));
/* /*
* Pick the probability to stop appending more nodes with zero delay to the path * Pick the probability to stop appending more nodes with zero delay to the path
...@@ -737,7 +737,7 @@ public class FeasibleMinIIProperty extends Property { ...@@ -737,7 +737,7 @@ public class FeasibleMinIIProperty extends Property {
remainingPathDelay -= edgeDelay; remainingPathDelay -= edgeDelay;
path.appendEdge(new PlannedEdge(src, candidate, edgeDelay, 0)); path.appendEdge(new PlannedEdge(src, candidate, edgeDelay));
} else { } else {
...@@ -758,7 +758,7 @@ public class FeasibleMinIIProperty extends Property { ...@@ -758,7 +758,7 @@ public class FeasibleMinIIProperty extends Property {
remainingPathDelay -= edgeDelay; remainingPathDelay -= edgeDelay;
path.prependEdge(new PlannedEdge(candidate, dst, edgeDelay, 0)); path.prependEdge(new PlannedEdge(candidate, dst, edgeDelay));
} }
......
...@@ -34,7 +34,6 @@ import java.util.HashSet; ...@@ -34,7 +34,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Predicate; import java.util.function.Predicate;
...@@ -197,15 +196,12 @@ public class InfeasibleEdgePlanner { ...@@ -197,15 +196,12 @@ public class InfeasibleEdgePlanner {
* *
* @param problematicTimeslot the problematic nodes' timeslot, needed to compute slacks and offsets * @param problematicTimeslot the problematic nodes' timeslot, needed to compute slacks and offsets
* @param edges the existing set of planned edges * @param edges the existing set of planned edges
* @return an optional containing the delay of the lowest edges if a suffix has been created, otherwise an empty
* optional
*/ */
public Optional<Integer> distributeDelay(int problematicTimeslot, Set<PlannedEdge> edges) { public void distributeDelay(int problematicTimeslot, Set<PlannedEdge> edges) {
if (problematicTimeslot < 0) { if (problematicTimeslot < 0) {
throw new IllegalArgumentException("The problematic nodes' timeslot cannot be negative."); throw new IllegalArgumentException("The problematic nodes' timeslot cannot be negative.");
} else if (problematicTimeslot + infeasibleCfg.getProblematicResource().delay > infeasibleCfg } else if (problematicTimeslot + startCfg.getProblematicResource().delay > infeasibleCfg.getMaxInnerDelay()) {
.getMaxInnerDelay()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Placing the nodes in the specified timeslot would exceed the maximum inner delay."); "Placing the nodes in the specified timeslot would exceed the maximum inner delay.");
} }
...@@ -275,12 +271,8 @@ public class InfeasibleEdgePlanner { ...@@ -275,12 +271,8 @@ public class InfeasibleEdgePlanner {
outgoingEdgesByNode.get(lowestNode).delay = representative.delay; outgoingEdgesByNode.get(lowestNode).delay = representative.delay;
} }
return Optional.of(representative.delay);
} }
return Optional.empty();
} }
/** /**
...@@ -377,7 +369,7 @@ public class InfeasibleEdgePlanner { ...@@ -377,7 +369,7 @@ public class InfeasibleEdgePlanner {
int suffixNodeSlot = suffixCfg.getSuffixOffsets().get(firstSuffixNode); int suffixNodeSlot = suffixCfg.getSuffixOffsets().get(firstSuffixNode);
int edgeDelay = suffixNodeSlot - fixedNode.getDelay() - problematicTimeslot; int edgeDelay = suffixNodeSlot - fixedNode.getDelay() - problematicTimeslot;
problematicEdges.add(new PlannedEdge(fixedNode, firstSuffixNode, edgeDelay, 0)); problematicEdges.add(new PlannedEdge(fixedNode, firstSuffixNode, edgeDelay));
} else { } else {
/* /*
...@@ -399,7 +391,7 @@ public class InfeasibleEdgePlanner { ...@@ -399,7 +391,7 @@ public class InfeasibleEdgePlanner {
*/ */
else { else {
ResourceNode dst = JavaUtils.pickRandomElement(possibleDstsWithDelay.keySet(), rng); ResourceNode dst = JavaUtils.pickRandomElement(possibleDstsWithDelay.keySet(), rng);
problematicEdges.add(new PlannedEdge(fixedNode, dst, possibleDstsWithDelay.get(dst), 0)); problematicEdges.add(new PlannedEdge(fixedNode, dst, possibleDstsWithDelay.get(dst)));
} }
} }
return problematicEdges; return problematicEdges;
......
...@@ -37,8 +37,6 @@ import java.util.Comparator; ...@@ -37,8 +37,6 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
...@@ -130,11 +128,7 @@ public class InfeasibleMinIIProperty extends Property { ...@@ -130,11 +128,7 @@ public class InfeasibleMinIIProperty extends Property {
throw new MinIIImpossibleException(resMinII, minII); throw new MinIIImpossibleException(resMinII, minII);
} }
int maxInnerDelay = SchedulingUtils.getMaxInnerDelay(minII, backedgeDelay, backedgeDistance); StartConfiguration startCfg = chooseStartConfiguration();
Set<Resource> problematicResources = getProblematicResources(maxInnerDelay);
StartConfiguration startCfg = chooseStartConfiguration(problematicResources, maxInnerDelay);
InfeasibleConfiguration infeasibleCfg = chooseInfeasibleConfiguration(startCfg); InfeasibleConfiguration infeasibleCfg = chooseInfeasibleConfiguration(startCfg);
...@@ -154,44 +148,39 @@ public class InfeasibleMinIIProperty extends Property { ...@@ -154,44 +148,39 @@ public class InfeasibleMinIIProperty extends Property {
// Do nothing. // Do nothing.
} }
private Set<Resource> getProblematicResources(int maxInnerDelay) { /**
* Because there could potentially be massive amounts of start configurations (many destination node possibilities
* multiplied by the many destination node layer possibilities), listing them all before picking one would use way
* too much memory and take way too long. Therefore, we immediately choose one per possible destination node layer.
* It is important to note that valid possibilities/destination node combinations will NOT be disregarded in any way
* - every configuration still remains possible.
*/
private StartConfiguration chooseStartConfiguration() {
InfeasibleCycleInspector inspector = new InfeasibleCycleInspector(layers, nodes);
/* Determines possible problematic resources from the given set of nodes. */ int maxInnerDelay = SchedulingUtils.getMaxInnerDelay(minII, backedgeDelay, backedgeDistance);
Set<Resource> problematicResources = InfeasibilityInspector.getProblematicResources(nodes, maxInnerDelay);
/* Determine possible problematic resources from the given set of nodes. */
Set<Resource> problematicResources = inspector.getProblematicResources(maxInnerDelay);
if (problematicResources.isEmpty()) { if (problematicResources.isEmpty()) {
throw new InfeasibilityImpossibleException(InfeasibilityImpossibleCause.NO_PROBLEMATIC_RESOURCE); throw new InfeasibilityImpossibleException(InfeasibilityImpossibleCause.NO_PROBLEMATIC_RESOURCE);
} }
return problematicResources;
}
/**
* <i>Because there could potentially be massive amounts of start configurations (many destination node
* possibilities multiplied by the many destination node layer possibilities), listing them all before picking one
* would use way too much memory and take way too long. Therefore, we immediately choose one per possible
* destination node layer. It is important to note that valid possibilities/destination node combinations will NOT
* be disregarded in any way - every configuration still remains possible.</i>
*/
private StartConfiguration chooseStartConfiguration(Set<Resource> problematicResources, int maxInnerDelay) {
/* /*
* Possible start configurations can be computed for every potential resource. * Possible start configurations can be computed for every potential resource.
*/ */
Map<Resource, Set<StartConfiguration>> startConfigurationsByResource = new HashMap<>(); Map<Resource, Set<StartConfiguration>> startConfigurationsByResource = new HashMap<>();
for (Resource problematicResource : Objects.requireNonNull(problematicResources)) { for (Resource problematicResource : problematicResources) {
Set<StartConfiguration> startConfigurations = new HashSet<>(); Set<StartConfiguration> startConfigurations = new HashSet<>();
for (int dstNodeLayer = 0; dstNodeLayer < layers.getHeight() - 1; dstNodeLayer++) { for (int dstNodeLayer = 0; dstNodeLayer < layers.getHeight() - 1; dstNodeLayer++) {
StartConfiguration startCfg = new StartConfiguration(layers, nodeTable, problematicResource, Set<ResourceNode> possibleDstNodes = inspector
maxInnerDelay .getPossibleDstNodes(dstNodeLayer, problematicResource, maxInnerDelay);
);
Set<ResourceNode> possibleDstNodes = InfeasibilityInspector.getPossibleDstNodes(dstNodeLayer, startCfg);
/* /*
* Continue with the next destination node layer if there are no valid * Continue with the next destination node layer if there are no valid
...@@ -219,8 +208,9 @@ public class InfeasibleMinIIProperty extends Property { ...@@ -219,8 +208,9 @@ public class InfeasibleMinIIProperty extends Property {
dstNode = JavaUtils.pickRandomElement(possibleDstNodes, rng); dstNode = JavaUtils.pickRandomElement(possibleDstNodes, rng);
} }
startCfg.setDestinationNode(dstNode); StartConfiguration startCfg = new StartConfiguration(layers, nodeTable, dstNode, dstNodeLayer,
startCfg.setDestinationNodeLayer(dstNodeLayer); maxInnerDelay, problematicResource
);
startConfigurations.add(startCfg); startConfigurations.add(startCfg);
...@@ -336,8 +326,9 @@ public class InfeasibleMinIIProperty extends Property { ...@@ -336,8 +326,9 @@ public class InfeasibleMinIIProperty extends Property {
Set<ResourceNode> candidates = new HashSet<>(); Set<ResourceNode> candidates = new HashSet<>();
if (remainingInnerDelay == 0 && rng.nextDouble() <= pToAppendMoreZeroNodes) if (remainingInnerDelay == 0 && rng.nextDouble() > pToAppendMoreZeroNodes) {
break; break;
}
for (int nodeID : layers.getLayer(layer)) { for (int nodeID : layers.getLayer(layer)) {
...@@ -378,7 +369,7 @@ public class InfeasibleMinIIProperty extends Property { ...@@ -378,7 +369,7 @@ public class InfeasibleMinIIProperty extends Property {
/* Stores pairs of source and destination nodes which need to be connected with an edge. */ /* Stores pairs of source and destination nodes which need to be connected with an edge. */
Set<Pair<ResourceNode, ResourceNode>> edgePairs = edgePlanner.getIncomingEdgePairs(); Set<Pair<ResourceNode, ResourceNode>> edgePairs = edgePlanner.getIncomingEdgePairs();
Set<PlannedEdge> plannedEdges = new HashSet<>(); Set<PlannedEdge> plannedEdges = new HashSet<>();
edgePairs.forEach(p -> plannedEdges.add(new PlannedEdge(p.first, p.second, 0, 0))); edgePairs.forEach(p -> plannedEdges.add(new PlannedEdge(p.first, p.second, 0)));
/* Choose the timeslot of the problematic nodes (relative to the destination node). */ /* Choose the timeslot of the problematic nodes (relative to the destination node). */
Set<Integer> possibleTimeslots = edgePlanner.getProblematicTimeslots(); Set<Integer> possibleTimeslots = edgePlanner.getProblematicTimeslots();
...@@ -389,28 +380,14 @@ public class InfeasibleMinIIProperty extends Property { ...@@ -389,28 +380,14 @@ public class InfeasibleMinIIProperty extends Property {
* the chosen timeslot. The remaining inner delay will also be distributed over the * the chosen timeslot. The remaining inner delay will also be distributed over the
* non-problematic edges (e.g. the suffix edges). * non-problematic edges (e.g. the suffix edges).
*/ */
Optional<Integer> lowestEdgesDelay = edgePlanner.distributeDelay(problematicTimeslot, plannedEdges); edgePlanner.distributeDelay(problematicTimeslot, plannedEdges);
/* /*
* Adjust the suffix nodes' offsets (i.e. ASAP-wise from the destination node) * 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 * 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. * useful for the creation of the cycle's required outgoing edges below.
*/ */
if (lowestEdgesDelay.isPresent()) { suffixCfg.updateSuffixOffsets(plannedEdges);
int lowestEdgeDelay = lowestEdgesDelay.get();
Map<ResourceNode, PlannedEdge> outgoingEdgesByNode = InfeasibleEdgePlanner
.getOutgoingEdgesMap(plannedEdges, suffixCfg.getSuffixNodes());
int firstSuffixSlot = problematicTimeslot + infeasibleCfg.getProblematicResource().delay + lowestEdgeDelay;
suffixCfg.setInitialOffset(firstSuffixSlot);
for (int i = 0; i < suffixCfg.getSuffixNodes().size() - 1; i++) {
ResourceNode src = suffixCfg.getSuffixNodes().get(i);
suffixCfg.updateSuffixOffsets(outgoingEdgesByNode.get(src));
}
}
/* /*
* Create the required outgoing edges. * Create the required outgoing edges.
......
...@@ -82,8 +82,6 @@ public class InfeasibleNodePlacer { ...@@ -82,8 +82,6 @@ public class InfeasibleNodePlacer {
remainingZeroNodes--; remainingZeroNodes--;
} }
boolean isDelayZero = problematicNode.getDelay() == 0;
int firstLayer = startCfg.getDestinationNodeLayer() + 1; int firstLayer = startCfg.getDestinationNodeLayer() + 1;
/* /*
...@@ -129,23 +127,19 @@ public class InfeasibleNodePlacer { ...@@ -129,23 +127,19 @@ public class InfeasibleNodePlacer {
/* /*
* If the problematic resource's delay is zero and if the destination node is * If the problematic resource's delay is zero and if the destination node is
* problematic as well, an additional subsequent end node is needed which the * problematic as well, an additional subsequent suffix node is needed which the
* RecMinII-ensuring backedge can then extend from, as the path does not have * RecMinII-ensuring backedge can then extend from, as the path does not have
* any delay so far (the destination node and the other problematic nodes all * any delay so far (the destination node and the other problematic nodes all
* share the same time slot). * share the same time slot).
* *
* If no additional end node can be appended (this is the case if the last * If no additional suffix node can be appended (this is the case if the last
* needed layer is the very last layer), a maximum inner delay greater than 0 * needed layer is the very last layer), the current layer and all its
* will be impossible to ensure and the current layer and all its subsequent * subsequent layers are invalid.
* layers are thus invalid.
*/ */
boolean isDstNodeProblematic = infeasibleCfg.getProblematicNodes() boolean isSuffixNecessary = infeasibleCfg.isSuffixNecessary();
.contains(startCfg.getDestinationNode());
if (isDelayZero && isDstNodeProblematic && lastLayerNeeded.get() == layers.getHeight() - 1) { if (isSuffixNecessary && lastLayerNeeded.get() == layers.getHeight() - 1) {
if (infeasibleCfg.getMaxInnerDelay() > 0) { break;
break;
}
} }
possibleLayers.add(currentLayer); possibleLayers.add(currentLayer);
...@@ -237,6 +231,28 @@ public class InfeasibleNodePlacer { ...@@ -237,6 +231,28 @@ public class InfeasibleNodePlacer {
continue; continue;
} }
/*
* If the problematic resource's delay is zero and if all remaining reachable
* spots must be filled with problematic nodes, only problematic zero nodes
* are allowed to be placed in the remaining spots.
*/
boolean mustUseProblematicZeroNodes = false;
if (startCfg.getProblematicResource().delay == 0) {
int remainingReachableSpots = infeasibleCfg.howManyReachableSpots();
int leftToPlace = infeasibleCfg.howManyLeftToPlace();
if (remainingReachableSpots < leftToPlace) {
throw new IllegalStateException("The remaining nodes cannot be arranged in an infeasible fashion.");
}
if (remainingReachableSpots == leftToPlace) {
remainingZeroNodes.removeIf(n -> !infeasibleCfg.getProblematicNodes().contains(n));
mustUseProblematicZeroNodes = true;
}
}
Set<ResourceNode> presentNodesWithZeroDelay = new HashSet<>(); Set<ResourceNode> presentNodesWithZeroDelay = new HashSet<>();
for (int id : infeasibleCfg.getLayers().getLayer(layer)) { for (int id : infeasibleCfg.getLayers().getLayer(layer)) {
...@@ -244,7 +260,9 @@ public class InfeasibleNodePlacer { ...@@ -244,7 +260,9 @@ public class InfeasibleNodePlacer {
ResourceNode node = infeasibleCfg.getNodeTable().get(id); ResourceNode node = infeasibleCfg.getNodeTable().get(id);
if (node.getDelay() == 0) { if (node.getDelay() == 0) {
presentNodesWithZeroDelay.add(node); if (!mustUseProblematicZeroNodes || infeasibleCfg.getProblematicNodes().contains(node)) {
presentNodesWithZeroDelay.add(node);
}
} }
} }
......
...@@ -19,7 +19,6 @@ package graphgen.generator.components.properties.infeasibleMinII.configuration; ...@@ -19,7 +19,6 @@ package graphgen.generator.components.properties.infeasibleMinII.configuration;
import graphgen.graph.ResourceNode; import graphgen.graph.ResourceNode;
import graphgen.util.JavaUtils; import graphgen.util.JavaUtils;
import graphgen.util.MathUtils;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
...@@ -115,17 +114,21 @@ public class InfeasibleConfiguration extends MinIICycleConfiguration { ...@@ -115,17 +114,21 @@ public class InfeasibleConfiguration extends MinIICycleConfiguration {
* *
* @param problematicNode the new problematic node * @param problematicNode the new problematic node
* @throws IllegalArgumentException if the set of problematic nodes contains enough nodes already (i.e. * @throws IllegalArgumentException if the set of problematic nodes contains enough nodes already (i.e.
* <i>problematic resource's limit + 1</i>), if the set contains the node already * <i>problematic resource's limit + 1</i>), if the node's resource doesn't match
* or if the node is the destination node with a delay greater than zero * the problematic resource, if the set contains the node already or if the node is
* the destination node with a delay greater than zero
* @throws NullPointerException if the problematic node is null
*/ */
public void addProblematicNode(ResourceNode problematicNode) { public void addProblematicNode(ResourceNode problematicNode) {
if (problematicNodes.size() == problematicResource.limit + 1) { if (Objects.requireNonNull(problematicNode).resource != startCfg.getProblematicResource()) {
throw new IllegalArgumentException("The set of problematic nodes contains enough nodes already."); throw new IllegalArgumentException("Node " + problematicNode + " doesn't use the problematic resource.");
} else if (problematicNodes.contains(Objects.requireNonNull(problematicNode))) { } else if (problematicNodes.contains(problematicNode)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The set of problematic nodes contains node " + problematicNode + " already."); "The set of problematic nodes contains node " + problematicNode + " already.");
} else if (problematicNode == startCfg.getDestinationNode() && startCfg.getDestinationNode().getDelay() > 0) { } else if (problematicNodes.size() == startCfg.getProblematicResource().limit + 1) {
throw new IllegalArgumentException("The set of problematic nodes contains enough nodes already.");
} else if (problematicNode == destinationNode && destinationNode.getDelay() > 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The destination node cannot be considered problematic with a delay > 0."); "The destination node cannot be considered problematic with a delay > 0.");
} }
...@@ -180,7 +183,23 @@ public class InfeasibleConfiguration extends MinIICycleConfiguration { ...@@ -180,7 +183,23 @@ public class InfeasibleConfiguration extends MinIICycleConfiguration {
* @return the amount of problematic nodes which still need to be placed * @return the amount of problematic nodes which still need to be placed
*/ */
public int howManyLeftToPlace() { public int howManyLeftToPlace() {
return problematicResource.limit + 1 - MathUtils.sumInteger(problematicNodesAtLayer.values()); return startCfg.getProblematicResource().limit + 1 - problematicNodesAtLayer.values().stream()
.mapToInt(Integer::intValue).sum();
}
/**
* Computes whether or not it is necessary to append a suffix to the infeasible part of the cycle. This is the case
* if the destination node is problematic (i.e. its delay is zero) and the maximum inner delay is not zero. In this
* case, at least one additional suffix node will be needed to ensure the maximum inner delay, since the problematic
* nodes cannot ensure it on their own (as all have a delay of 0).
*
* @return true if a suffix is necessary, otherwise false
*/
public boolean isSuffixNecessary() {
if (problematicNodes.contains(destinationNode)) {
return maxInnerDelay != 0;
}
return false;
} }
/** /**
...@@ -218,7 +237,47 @@ public class InfeasibleConfiguration extends MinIICycleConfiguration { ...@@ -218,7 +237,47 @@ public class InfeasibleConfiguration extends MinIICycleConfiguration {
} }
/** /**
* Returns the lowest problematic nodes, depth-wise (i.e. the nodes furthest from the graph's source node). * Computes how many spots where problematic nodes could still be placed are currently reachable with the current
* configuration of fixed nodes.
*
* @return the amount of remaining reachable spots
*/
public int howManyReachableSpots() {
int remainingSpots = 0;
int remainingZeros = getRemainingZeroNodes().size();
int lastLayer = isSuffixNecessary() ? layers.getHeight() - 2 : layers.getHeight() - 1;
for (int layer = destinationNodeLayer + 1; layer <= lastLayer; layer++) {
int spotsAvailable = getLooseNodesAtLayer(layer).size();
if (!zeroNodesByLayer.containsKey(layer)) {
if (startCfg.getProblematicResource().delay != 0) {
if (spotsAvailable > 0 && remainingZeros > 0 && layer < lastLayer) {
spotsAvailable--;
remainingZeros--;
} else {
remainingSpots += spotsAvailable;
break;
}
}
}
remainingSpots += spotsAvailable;
}
return remainingSpots;
}
/**
* Returns the lowest problematic nodes, depth-wise (i.e. the nodes furthest from the destination node).
* *
* @return the lowest problematic nodes * @return the lowest problematic nodes
*/ */
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
package graphgen.generator.components.properties.infeasibleMinII.configuration; package graphgen.generator.components.properties.infeasibleMinII.configuration;
import graphgen.graph.LayerStructure; import graphgen.graph.LayerStructure;
import graphgen.graph.Resource;
import graphgen.graph.ResourceNode; import graphgen.graph.ResourceNode;
import java.util.Map; import java.util.Map;
...@@ -26,8 +25,8 @@ import java.util.Objects; ...@@ -26,8 +25,8 @@ import java.util.Objects;
/** /**
* The abstract base class of the {@link StartConfiguration}, {@link InfeasibleConfiguration} and {@link * The abstract base class of the {@link StartConfiguration}, {@link InfeasibleConfiguration} and {@link
* SuffixConfiguration} classes. It stores the graph's layer structure, the node table, the infeasible cycle's * SuffixConfiguration} classes. It stores the graph's layer structure, the node table, the cycle's destination node,
* problematic resource and its maximum inner delay. * the destination node's layer and the cycle's maximum inner delay.
* *
* @author Sebastian Vollbrecht * @author Sebastian Vollbrecht
*/ */
...@@ -35,22 +34,43 @@ public abstract class MinIICycleConfiguration { ...@@ -35,22 +34,43 @@ public abstract class MinIICycleConfiguration {
protected final LayerStructure layers; protected final LayerStructure layers;
protected final Map<Integer, ResourceNode> nodeTable; protected final Map<Integer, ResourceNode> nodeTable;
protected final Resource problematicResource;
/**
* The destination node is the node which the cycle's backedges will connect to later on (hence the name destination
* node).
*/
protected final ResourceNode destinationNode;
/**
* The layer the destination node will reside in.
*/
protected final int destinationNodeLayer;
/**
* The cycle's maximum inner delay which must not be exceeded in order to ensure its corresponding MinII.
*/
protected final int maxInnerDelay; protected final int maxInnerDelay;
/** /**
* Creates a new configuration based on the provided arguments.. * Creates a new configuration based on the provided arguments.
* *
* @param layers the graph's layer structure * @param layers the graph's layer structure
* @param nodeTable the graph's node table * @param nodeTable the graph's node table
* @param problematicResource the infeasible cycle's problematic resource * @param destinationNode the cycle's destination node
* @param maxInnerDelay the infeasible cycle's maximum inner delay * @param destinationNodeLayer the cycle's destination node's layer
* @param maxInnerDelay the cycle's maximum inner delay
*/ */
protected MinIICycleConfiguration(LayerStructure layers, Map<Integer, ResourceNode> nodeTable, protected MinIICycleConfiguration(LayerStructure layers, Map<Integer, ResourceNode> nodeTable,
Resource problematicResource, int maxInnerDelay) { ResourceNode destinationNode, int destinationNodeLayer, int maxInnerDelay) {
this.layers = Objects.requireNonNull(layers); this.layers = Objects.requireNonNull(layers);
this.nodeTable = Objects.requireNonNull(nodeTable); this.nodeTable = Objects.requireNonNull(nodeTable);
this.problematicResource = Objects.requireNonNull(problematicResource); this.destinationNode = Objects.requireNonNull(destinationNode);
if (destinationNodeLayer < 0 || destinationNodeLayer >= layers.getHeight()) {
throw new IllegalArgumentException("The destination node's layer is out of bounds.");
}
this.destinationNodeLayer = destinationNodeLayer;
if (maxInnerDelay < 0) { if (maxInnerDelay < 0) {
throw new IllegalArgumentException("The maximum inner delay cannot be negative."); throw new IllegalArgumentException("The maximum inner delay cannot be negative.");
...@@ -59,7 +79,7 @@ public abstract class MinIICycleConfiguration { ...@@ -59,7 +79,7 @@ public abstract class MinIICycleConfiguration {
} }
protected MinIICycleConfiguration(MinIICycleConfiguration other) { protected MinIICycleConfiguration(MinIICycleConfiguration other) {
this(other.layers, other.nodeTable, other.problematicResource, other.maxInnerDelay); this(other.layers, other.nodeTable, other.destinationNode, other.destinationNodeLayer, other.maxInnerDelay);
} }
public LayerStructure getLayers() { public LayerStructure getLayers() {
...@@ -70,8 +90,22 @@ public abstract class MinIICycleConfiguration { ...@@ -70,8 +90,22 @@ public abstract class MinIICycleConfiguration {
return nodeTable; return nodeTable;
} }