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 {
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
......@@ -737,7 +737,7 @@ public class FeasibleMinIIProperty extends Property {
remainingPathDelay -= edgeDelay;
path.appendEdge(new PlannedEdge(src, candidate, edgeDelay, 0));
path.appendEdge(new PlannedEdge(src, candidate, edgeDelay));
} else {
......@@ -758,7 +758,7 @@ public class FeasibleMinIIProperty extends Property {
remainingPathDelay -= edgeDelay;
path.prependEdge(new PlannedEdge(candidate, dst, edgeDelay, 0));
path.prependEdge(new PlannedEdge(candidate, dst, edgeDelay));
}
......
......@@ -17,10 +17,11 @@
package graphgen.generator.components.properties.infeasibleMinII;
import graphgen.generator.components.properties.infeasibleMinII.configuration.StartConfiguration;
import graphgen.graph.LayerStructure;
import graphgen.graph.Resource;
import graphgen.graph.ResourceNode;
import graphgen.util.JavaUtils;
import modsched.Node;
import java.util.HashMap;
import java.util.HashSet;
......@@ -28,25 +29,34 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* This class contains some utility methods related to inspecting nodes and layer structure regarding possible
* infeasible node arrangements.
* infeasible cycles.
*
* @author Sebastian Vollbrecht
*/
public class InfeasibilityInspector {
public class InfeasibleCycleInspector {
private final LayerStructure layers;
private final Set<ResourceNode> nodes;
public InfeasibleCycleInspector(LayerStructure layers, Set<ResourceNode> nodes) {
this.layers = Objects.requireNonNull(layers);
this.nodes = Objects.requireNonNull(nodes);
}
/**
* Computes possible problematic resources whose limit could be exceeded in a cycle, using the provided set of
* nodes. The maximum inner delay is taken into account to discard resources whose delay exceeds the maximum inner
* delay already. A cycle consisting of these resources would automatically exceed corresponding MinIIs.
* Computes possible problematic resources whose limit could be exceeded in a cycle. The maximum inner delay is
* taken into account to discard resources whose delay exceeds the maximum inner delay already. A cycle consisting
* of these resources would automatically exceed corresponding MinIIs.
*
* @param nodes the set of nodes
* @param maxInnerDelay the cycle's maximum inner delay
* @return a set containing problematic resource candidates
*/
public static Set<Resource> getProblematicResources(Set<ResourceNode> nodes, int maxInnerDelay) {
public Set<Resource> getProblematicResources(int maxInnerDelay) {
if (maxInnerDelay < 0) {
throw new IllegalArgumentException("The cycle's maximum inner delay cannot be negative.");
......@@ -59,7 +69,7 @@ public class InfeasibilityInspector {
*/
Map<Resource, Integer> limitedResourceUsages = new HashMap<>();
for (ResourceNode node : Objects.requireNonNull(nodes)) {
for (ResourceNode node : nodes) {
if (node.isUnlimited()) {
continue;
......@@ -89,21 +99,17 @@ public class InfeasibilityInspector {
/**
* Computes all destination nodes that could potentially be placed in the specified layer and serve as the
* destination node for the backedges of an infeasible cycle. The infeasible cycle's parameters (i.e. problematic
* resource, layer structure, node table and the maximum inner delay) are extracted from the provided start
* configuration.
* destination node for the backedges of an infeasible cycle. This method assumes that the infeasibility is created
* by nodes using the given problematic resource.
*
* @param dstNodeLayer the layer for which possible possible destination nodes are needed
* @param startCfg the start configuration containing the cycle's parameters
* @param dstNodeLayer the layer for which possible possible destination nodes are needed
* @param problematicResource the chosen problematic resource
* @return a set containing all potential destination node candidates
*/
public static Set<ResourceNode> getPossibleDstNodes(int dstNodeLayer, StartConfiguration startCfg) {
public Set<ResourceNode> getPossibleDstNodes(int dstNodeLayer, Resource problematicResource, int maxInnerDelay) {
Set<ResourceNode> possibleDstNodes = new HashSet<>();
Set<ResourceNode> nodes = new HashSet<>(Objects.requireNonNull(startCfg).getNodeTable().values());
Resource problematicResource = startCfg.getProblematicResource();
Map<Integer, Set<ResourceNode>> nodesByDelay = new HashMap<>();
for (ResourceNode node : nodes) {
......@@ -111,69 +117,79 @@ public class InfeasibilityInspector {
nodesByDelay.get(node.getDelay()).add(node);
}
/*
* Stores the delays of the remaining nodes if enough of the respective
* resource's nodes were to be chosen for the problematic resource. The
* delays are useful as we then don't have to regard every destination
* node candidate individually. This means that if a delay is a possible
* delay for the destination node, every node having this delay is
* (almost always) a destination node candidate too.
*/
Map<Integer, Integer> remainingDelays = getRemainingDelays(nodes, problematicResource);
long problematicResourceCount = nodes.stream().filter(n -> n.resource == problematicResource).count();
boolean noSpareNodesAvailable = problematicResourceCount == problematicResource.limit + 1;
boolean isProblematicDelayZero = problematicResource.delay == 0;
for (Entry<Integer, Set<ResourceNode>> nodesByDelayEntry : nodesByDelay.entrySet()) {
int dstNodeDelay = nodesByDelayEntry.getKey();
boolean isSameDelay = dstNodeDelay == problematicResource.delay;
boolean arrangementPossible = areDstNodeParametersValid(dstNodeDelay, dstNodeLayer, startCfg,
remainingDelays
DestinationNodeStatus dstNodeStatus = getDstNodeStatus(dstNodeDelay, dstNodeLayer, problematicResource,
maxInnerDelay
);
if (arrangementPossible) {
/*
* If the problematic resource's delay is not zero, if the current destination
* node's delay equals the problematic resource's delay and if there are no
* spare nodes, only non-problematic nodes may become destination nodes.
*
* Otherwise, if a problematic node were picked to be the destination node in
* this case, no infeasible time slot containing all problematic nodes would
* be manageable anymore due to the problematic destination node having a
* delay > 0 and due to there being no spare nodes.
*/
if (!isProblematicDelayZero && isSameDelay && noSpareNodesAvailable) {
for (ResourceNode node : nodesByDelayEntry.getValue()) {
if (node.resource != problematicResource) {
possibleDstNodes.add(node);
}
}
} else {
possibleDstNodes.addAll(nodesByDelayEntry.getValue());
}
Predicate<ResourceNode> dstNodeFilter;
switch (dstNodeStatus) {
case PROBLEMATIC_ONLY:
dstNodeFilter = n -> n.resource == problematicResource;
break;
case NON_PROBLEMATIC_ONLY:
dstNodeFilter = n -> n.resource != problematicResource;
break;
case ANY:
dstNodeFilter = n -> true;
break;
case NONE:
dstNodeFilter = n -> false;
break;
default:
throw new UnsupportedOperationException(dstNodeStatus.toString());
}
nodesByDelayEntry.getValue().stream().filter(dstNodeFilter).forEach(possibleDstNodes::add);
}
return possibleDstNodes;
}
private static boolean areDstNodeParametersValid(int dstNodeDelay, int dstNodeLayer, StartConfiguration startCfg,
Map<Integer, Integer> remainingDelays) {
/**
* An enum which stores what kinds of nodes can be used as destination nodes.
*/
private enum DestinationNodeStatus {
Map<Integer, Integer> delayCounts = new HashMap<>();
/**
* Only problematic nodes can become destination nodes.
*/
PROBLEMATIC_ONLY,
for (ResourceNode node : Objects.requireNonNull(startCfg).getNodeTable().values()) {
JavaUtils.insertOrIncValue(delayCounts, node.getDelay());
}
/**
* Only non-problematic nodes can become destination nodes.
*/
NON_PROBLEMATIC_ONLY,
/**
* All nodes can become destination nodes.
*/
ANY,
/**
* No node can become destination node.
*/
NONE
}
private DestinationNodeStatus getDstNodeStatus(int dstNodeDelay, int dstNodeLayer, Resource problematicResource,
int maxInnerDelay) {
Resource problematicResource = startCfg.getProblematicResource();
/*
* The map of remaining delays is useful as we then don't have to regard every destination node candidate
* individually. This means that if a delay is a possible delay for the destination node, every node
* having this delay is (almost always) a destination node candidate too.
*/
Map<Integer, Integer> remainingDelays = getRemainingDelays(problematicResource);
Map<Integer, Long> delayCounts = nodes.stream()
.collect(Collectors.groupingBy(Node::getDelay, Collectors.counting()));
boolean isSameDelay = dstNodeDelay == problematicResource.delay;
boolean isProblematicDelayZero = problematicResource.delay == 0;
......@@ -182,8 +198,8 @@ public class InfeasibilityInspector {
* If the current destination node's delay makes it impossible to ensure the
* RecMinII, the delay is not valid.
*/
if (dstNodeDelay + problematicResource.delay > startCfg.getMaxInnerDelay()) {
return false;
if (dstNodeDelay + problematicResource.delay > maxInnerDelay) {
return DestinationNodeStatus.NONE;
}
/*
......@@ -195,7 +211,7 @@ public class InfeasibilityInspector {
*/
if (isSameDelay && dstNodeDelay > 0) {
if (delayCounts.get(dstNodeDelay) == problematicResource.limit + 1) {
return false;
return DestinationNodeStatus.NONE;
}
}
......@@ -204,7 +220,7 @@ public class InfeasibilityInspector {
* can be a valid destination node delay. This is done later on by verifying
* that all problematic nodes can be placed in a single time slot.
*/
int zeroNodesRemaining = delayCounts.getOrDefault(0, 0);
long zeroNodesRemaining = delayCounts.getOrDefault(0, 0L);
int leftToPlace = problematicResource.limit + 1;
/*
......@@ -225,7 +241,10 @@ public class InfeasibilityInspector {
* Try to see if the problematic nodes can still all be placed in the same slot,
* beginning with the destination node's succeeding layer.
*/
int lastPossibleLayer = startCfg.getLayers().getHeight() - 1;
int lastPossibleLayer = layers.getHeight() - 1;
boolean noSparesAvailable = nodes.stream().filter(n -> n.resource == problematicResource)
.count() == problematicResource.limit + 1;
for (int lastProblematicLayer = dstNodeLayer + 1; lastProblematicLayer <= lastPossibleLayer;
lastProblematicLayer++) {
......@@ -233,50 +252,67 @@ public class InfeasibilityInspector {
* The current configuration can only be valid if all of the remaining problematic
* nodes could potentially be placed in the current layer.
*/
if (leftToPlace <= startCfg.getLayers().getLayer(lastProblematicLayer).size()) {
/*
* If the problematic resource's delay is zero and if the destination node's
* delay is zero as well, an additional subsequent end node is needed which the
* RecMinII-ensuring backedge can then extend from, since the path does not have
* any delay so far as the destination node and the problematic nodes all share
* the same time slot (the destination node is automatically treated as a
* problematic node if the resource's delay is zero).
*
* If no additional end node can be used, the maximum inner delay will be
* impossible to ensure (as there wouldn't be any edges available to distribute
* the remaining delay over) and the destination node's delay/layer are invalid.
*/
if (isProblematicDelayZero && isSameDelay && 0 < startCfg.getMaxInnerDelay()) {
if (lastProblematicLayer < lastPossibleLayer) {
int layerSize = layers.getLayer(lastProblematicLayer).size();
if (leftToPlace <= layerSize) {
if (isProblematicDelayZero && isSameDelay) {
/*
* If the problematic resource's delay is zero and if the destination node's
* delay is zero as well, an additional subsequent end node is needed which the
* RecMinII-ensuring backedge can then extend from in order to ensure inner
* delays > 0 (the path does not have any delay so far as the destination node
* and the problematic nodes all share the same time slot - as the destination
* node is automatically treated as a problematic node if the resource's delay
* is zero).
*/
if (maxInnerDelay > 0) {
if (lastProblematicLayer < lastPossibleLayer) {
/*
* We must check whether we have any end node candidates whose delays are small
* enough to not exceed the maximum inner delay.
*/
if (remainingDelays.keySet().stream().anyMatch(delay -> delay <= maxInnerDelay)) {
return DestinationNodeStatus.ANY;
}
}
/*
* We must check whether we have any end node candidates whose delays are small
* enough to not exceed the maximum inner delay.
* If no additional end node can be used, the maximum inner delay will be
* impossible to ensure (as there wouldn't be any edges available to distribute
* the remaining delay over) - the destination node's delay/layer is thus invalid.
*/
boolean candidateFound = false;
return DestinationNodeStatus.NONE;
for (int remainingDelay : remainingDelays.keySet()) {
if (zeroNodesRemaining == 0 && remainingDelay == 0) {
continue;
}
if (remainingDelay <= startCfg.getMaxInnerDelay()) {
candidateFound = true;
break;
}
}
}
/*
* If the entire last layer would be needed to ensure the cycle's infeasibility, only
* problematic nodes may become start nodes themselves - otherwise they would not fit
* in one timeslot anymore.
*/
else if (lastProblematicLayer == lastPossibleLayer && leftToPlace == layerSize) {
return DestinationNodeStatus.PROBLEMATIC_ONLY;
}
return candidateFound;
}
} else {
return false;
}
/*
* If the problematic resource's delay is not zero, if the current destination
* node's delay equals the problematic resource's delay and if there are no
* spare nodes, only non-problematic nodes may become destination nodes.
*
* Otherwise, if a problematic node were picked to be the destination node in
* this case, no infeasible time slot containing all problematic nodes would
* be manageable anymore due to the problematic destination node having a
* delay > 0 and due to there being no spare nodes.
*/
else if (!isProblematicDelayZero && isSameDelay && noSparesAvailable) {
return DestinationNodeStatus.NON_PROBLEMATIC_ONLY;
}
return true;
return DestinationNodeStatus.ANY;
}
......@@ -286,7 +322,7 @@ public class InfeasibilityInspector {
* layer without automatically pushing its nodes in different timeslots.
*/
if (zeroNodesRemaining == 0) {
return false;
return DestinationNodeStatus.NONE;
}
/*
......@@ -294,7 +330,7 @@ public class InfeasibilityInspector {
* If the problematic nodes' delay is zero, an additional problematic node can
* be placed without increasing the next layer's minimal ASAP time.
*/
int placedNodes = startCfg.getLayers().getLayer(lastProblematicLayer).size() - 1;
int placedNodes = layers.getLayer(lastProblematicLayer).size() - 1;
if (isProblematicDelayZero) {
zeroNodesRemaining -= ++placedNodes;
......@@ -305,10 +341,14 @@ public class InfeasibilityInspector {
leftToPlace -= placedNodes;
}
return false;
return DestinationNodeStatus.NONE;
}
private static Map<Integer, Integer> getRemainingDelays(Set<ResourceNode> nodes, Resource problematicResource) {
/**
* Computes the delays of the remaining nodes if enough of the problematic resource's nodes were to be chosen for
* the problematic resource.
*/
private Map<Integer, Integer> getRemainingDelays(Resource problematicResource) {
Map<Integer, Integer> remainingDelays = new HashMap<>();
......@@ -316,7 +356,7 @@ public class InfeasibilityInspector {
* Skip an amount of nodes equal to [the resource's limit + 1] in order to compute the
* remaining delays if the resource were to be deemed the problematic resource.
*/
int skipsRequired = Objects.requireNonNull(problematicResource).limit + 1;
int skipsRequired = problematicResource.limit + 1;
for (ResourceNode node : nodes) {
......
......@@ -34,7 +34,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Predicate;
......@@ -197,15 +196,12 @@ public class InfeasibleEdgePlanner {
*
* @param problematicTimeslot the problematic nodes' timeslot, needed to compute slacks and offsets
* @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) {
throw new IllegalArgumentException("The problematic nodes' timeslot cannot be negative.");
} else if (problematicTimeslot + infeasibleCfg.getProblematicResource().delay > infeasibleCfg
.getMaxInnerDelay()) {
} else if (problematicTimeslot + startCfg.getProblematicResource().delay > infeasibleCfg.getMaxInnerDelay()) {
throw new IllegalArgumentException(
"Placing the nodes in the specified timeslot would exceed the maximum inner delay.");
}
......@@ -275,12 +271,8 @@ public class InfeasibleEdgePlanner {
outgoingEdgesByNode.get(lowestNode).delay = representative.delay;
}
return Optional.of(representative.delay);
}
return Optional.empty();
}
/**
......@@ -377,7 +369,7 @@ public class InfeasibleEdgePlanner {
int suffixNodeSlot = suffixCfg.getSuffixOffsets().get(firstSuffixNode);
int edgeDelay = suffixNodeSlot - fixedNode.getDelay() - problematicTimeslot;
problematicEdges.add(new PlannedEdge(fixedNode, firstSuffixNode, edgeDelay, 0));
problematicEdges.add(new PlannedEdge(fixedNode, firstSuffixNode, edgeDelay));
} else {
/*
......@@ -399,7 +391,7 @@ public class InfeasibleEdgePlanner {
*/
else {
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;
......
......@@ -37,8 +37,6 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
......@@ -130,11 +128,7 @@ public class InfeasibleMinIIProperty extends Property {
throw new MinIIImpossibleException(resMinII, minII);
}
int maxInnerDelay = SchedulingUtils.getMaxInnerDelay(minII, backedgeDelay, backedgeDistance);
Set<Resource> problematicResources = getProblematicResources(maxInnerDelay);
StartConfiguration startCfg = chooseStartConfiguration(problematicResources, maxInnerDelay);
StartConfiguration startCfg = chooseStartConfiguration();
InfeasibleConfiguration infeasibleCfg = chooseInfeasibleConfiguration(startCfg);
......@@ -154,44 +148,39 @@ public class InfeasibleMinIIProperty extends Property {
// 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. */
Set<Resource> problematicResources = InfeasibilityInspector.getProblematicResources(nodes, maxInnerDelay);
int maxInnerDelay = SchedulingUtils.getMaxInnerDelay(minII, backedgeDelay, backedgeDistance);
/* Determine possible problematic resources from the given set of nodes. */
Set<Resource> problematicResources = inspector.getProblematicResources(maxInnerDelay);
if (problematicResources.isEmpty()) {
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.
*/
Map<Resource, Set<StartConfiguration>> startConfigurationsByResource = new HashMap<>();
for (Resource problematicResource : Objects.requireNonNull(problematicResources)) {
for (Resource problematicResource : problematicResources) {
Set<StartConfiguration> startConfigurations = new HashSet<>();
for (int dstNodeLayer = 0; dstNodeLayer < layers.getHeight() - 1; dstNodeLayer++) {
StartConfiguration startCfg = new StartConfiguration(layers, nodeTable, problematicResource,
maxInnerDelay
);
Set<ResourceNode> possibleDstNodes = InfeasibilityInspector.getPossibleDstNodes(dstNodeLayer, startCfg);
Set<ResourceNode> possibleDstNodes = inspector
.getPossibleDstNodes(dstNodeLayer, problematicResource, maxInnerDelay);
/*
* Continue with the next destination node layer if there are no valid
......@@ -219,8 +208,9 @@ public class InfeasibleMinIIProperty extends Property {
dstNode = JavaUtils.pickRandomElement(possibleDstNodes, rng);
}
startCfg.setDestinationNode(dstNode);
startCfg.setDestinationNodeLayer(dstNodeLayer);
StartConfiguration startCfg = new StartConfiguration(layers, nodeTable, dstNode, dstNodeLayer,
maxInnerDelay, problematicResource
);
startConfigurations.add(startCfg);
......@@ -336,8 +326,9 @@ public class InfeasibleMinIIProperty extends Property {
Set<ResourceNode> candidates = new HashSet<>();
if (remainingInnerDelay == 0 && rng.nextDouble() <= pToAppendMoreZeroNodes)
if (remainingInnerDelay == 0 && rng.nextDouble() > pToAppendMoreZeroNodes) {
break;
}
for (int nodeID : layers.getLayer(layer)) {
......@@ -378,7 +369,7 @@ public class InfeasibleMinIIProperty extends Property {
/* Stores pairs of source and destination nodes which need to be connected with an edge. */
Set<Pair<ResourceNode, ResourceNode>> edgePairs = edgePlanner.getIncomingEdgePairs();
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). */
Set<Integer> possibleTimeslots = edgePlanner.getProblematicTimeslots();
......@@ -389,28 +380,14 @@ 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<Integer> lowestEdgesDelay = edgePlanner.distributeDelay(problematicTimeslot, plannedEdges);
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 (lowestEdgesDelay.isPresent()) {
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));
}
}
suffixCfg.updateSuffixOffsets(plannedEdges);
/*
* Create the required outgoing edges.
......
......@@ -82,8 +82,6 @@ public class InfeasibleNodePlacer {
remainingZeroNodes--;
}
boolean isDelayZero = problematicNode.getDelay() == 0;
int firstLayer = startCfg.getDestinationNodeLayer() + 1;
/*
......@@ -129,23 +127,19 @@ public class InfeasibleNodePlacer {
/*
* 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
* any delay so far (the destination node and the other problematic nodes all
* share the same time slot).
*
* If no additional end 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
* will be impossible to ensure and the current layer and all its subsequent
* layers are thus invalid.
* If no additional suffix node can be appended (this is the case if the last
* needed layer is the very last layer), the current layer and all its
* subsequent layers are invalid.
*/
boolean isDstNodeProblematic = infeasibleCfg.getProblematicNodes()
.contains(startCfg.getDestinationNode());
boolean isSuffixNecessary = infeasibleCfg.isSuffixNecessary();
if (isDelayZero && isDstNodeProblematic && lastLayerNeeded.get() == layers.getHeight() - 1) {
if (infeasibleCfg.getMaxInnerDelay() > 0) {
break;
}
if (isSuffixNecessary && lastLayerNeeded.get() == layers.getHeight() - 1) {
break;