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));
}
......
......@@ -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;
}
possibleLayers.add(currentLayer);
......@@ -237,6 +231,28 @@ public class InfeasibleNodePlacer {
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<>();
for (int id : infeasibleCfg.getLayers().getLayer(layer)) {
......@@ -244,7 +260,9 @@ public class InfeasibleNodePlacer {
ResourceNode node = infeasibleCfg.getNodeTable().get(id);
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;
import graphgen.graph.ResourceNode;
import graphgen.util.JavaUtils;
import graphgen.util.MathUtils;
import java.util.Collections;
import java.util.HashMap;
......@@ -115,17 +114,21 @@ public class InfeasibleConfiguration extends MinIICycleConfiguration {
*
* @param problematicNode the new problematic node
* @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
* or if the node is the destination node with a delay greater than zero
* <i>problematic resource's limit + 1</i>), if the node's resource doesn't match
* 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) {
if (problematicNodes.size() == problematicResource.limit + 1) {
throw new IllegalArgumentException("The set of problematic nodes contains enough nodes already.");
} else if (problematicNodes.contains(Objects.requireNonNull(problematicNode))) {
if (Objects.requireNonNull(problematicNode).resource != startCfg.getProblematicResource()) {
throw new IllegalArgumentException("Node " + problematicNode + " doesn't use the problematic resource.");
} else if (problematicNodes.contains(problematicNode)) {
throw new IllegalArgumentException(
"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(
"The destination node cannot be considered problematic with a delay > 0.");
}
......@@ -180,7 +183,23 @@ public class InfeasibleConfiguration extends MinIICycleConfiguration {
* @return the amount of problematic nodes which still need to be placed
*/
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 {
}
/**
* 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
*/
......
......@@ -18,7 +18,6 @@
package graphgen.generator.components.properties.infeasibleMinII.configuration;
import graphgen.graph.LayerStructure;
import graphgen.graph.Resource;
import graphgen.graph.ResourceNode;
import java.util.Map;
......@@ -26,8 +25,8 @@ import java.util.Objects;
/**
* 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
* problematic resource and its maximum inner delay.
* SuffixConfiguration} classes. It stores the graph's layer structure, the node table, the cycle's destination node,
* the destination node's layer and the cycle's maximum inner delay.
*
* @author Sebastian Vollbrecht
*/
......@@ -35,22 +34,43 @@ public abstract class MinIICycleConfiguration {
protected final LayerStructure layers;
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;
/**
* 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 nodeTable the graph's node table
* @param problematicResource the infeasible cycle's problematic resource
* @param maxInnerDelay the infeasible cycle's maximum inner delay
* @param layers the graph's layer structure
* @param nodeTable the graph's node table
* @param destinationNode the cycle's destination node
* @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,
Resource problematicResource, int maxInnerDelay) {
ResourceNode destinationNode, int destinationNodeLayer, int maxInnerDelay) {
this.layers = Objects.requireNonNull(layers);
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) {
throw new IllegalArgumentException("The maximum inner delay cannot be negative.");
......@@ -59,7 +79,7 @@ public abstract class MinIICycleConfiguration {
}
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() {
......@@ -70,8 +90,22 @@ public abstract class MinIICycleConfiguration {
return nodeTable;
}
public Resource getProblematicResource() {
return problematicResource;
/**
* Returns the destination node of the cycle.
*
* @return the destination node
*/
public ResourceNode getDestinationNode() {
return destinationNode;
}
/**
* Returns the layer of the destination node.
*
* @return the destination node's layer
*/
public int getDestinationNodeLayer() {
return destinationNodeLayer;
}
public int getMaxInnerDelay() {
......@@ -85,12 +119,13 @@ public abstract class MinIICycleConfiguration {
if (o == null || getClass() != o.getClass())
return false;
MinIICycleConfiguration that = (MinIICycleConfiguration) o;
return maxInnerDelay == that.maxInnerDelay && Objects.equals(layers, that.layers) && Objects
.equals(nodeTable, that.nodeTable) && Objects.equals(problematicResource, that.problematicResource);
return destinationNodeLayer == that.destinationNodeLayer && maxInnerDelay == that.maxInnerDelay && Objects
.equals(layers, that.layers) && Objects.equals(nodeTable, that.nodeTable) && Objects
.equals(destinationNode, that.destinationNode);
}
@Override
public int hashCode() {
return Objects.hash(layers, nodeTable, problematicResource, maxInnerDelay);
return Objects.hash(layers, nodeTable, destinationNode, destinationNodeLayer, maxInnerDelay);
}
}
......@@ -25,87 +25,33 @@ import java.util.Map;
import java.util.Objects;
/**
* The start configuration represents the very start of an infeasible cycle. It contains the <i>destination node</i> and
* the layer it is located in. The destination node is the single node which all backedges of the infeasible cycle must
* later connect to (hence the name <i>destination</i> node).
* The start configuration represents the very start of an infeasible cycle. It contains the cycle's problematic
* resource.
*
* @author Sebastian Vollbrecht
*/
public class StartConfiguration extends MinIICycleConfiguration {
/**
* The destination node is the node which the infeasible cycle's backedges will connect to later on (hence the name
* destination node).
*/
protected ResourceNode destinationNode;
/**
* The layer the destination node will reside in.
*/
private Integer destinationNodeLayer;
/**
* Creates a new start configuration based on the provided arguments. The destination node and the layer it is
* located in must be separately using {@link #setDestinationNode(ResourceNode)} and {@link
* #setDestinationNodeLayer(int)}.
*
* @param layers the graph's layer structure
* @param nodeTable the graph's node table
* @param problematicResource the infeasible cycle's problematic resource
* @param maxInnerDelay the infeasible cycle's maximum inner delay
*/
public StartConfiguration(LayerStructure layers, Map<Integer, ResourceNode> nodeTable, Resource problematicResource,
int maxInnerDelay) {
super(layers, nodeTable, problematicResource, maxInnerDelay);
}
private final Resource problematicResource;
/**
* Sets the destination node of the infeasible cycle.
*
* @param destinationNode the infeasible cycle's destination node
* @throws NullPointerException if the destination node is null
*/
public void setDestinationNode(ResourceNode destinationNode) {
this.destinationNode = Objects.requireNonNull(destinationNode);
}
/**
* Sets the layer of the infeasible cycle's destination node.
* Creates a new start configuration based on the provided arguments.
*
* @param layers the graph's layer structure
* @param nodeTable the graph's node table
* @param destinationNode the cycle's destination node
* @param destinationNodeLayer the destination node's layer
* @throws IllegalArgumentException if the destination node layer is less than zero
* @param maxInnerDelay the cycle's maximum inner delay
* @param problematicResource the cycle's problematic resource
*/
public void setDestinationNodeLayer(int destinationNodeLayer) {
if (destinationNodeLayer < 0) {
throw new IllegalArgumentException("Destination node layer cannot be negative.");
}
this.destinationNodeLayer = destinationNodeLayer;
public StartConfiguration(LayerStructure layers, Map<Integer, ResourceNode> nodeTable, ResourceNode destinationNode,
int destinationNodeLayer, int maxInnerDelay, Resource problematicResource) {
super(layers, nodeTable, destinationNode, destinationNodeLayer, maxInnerDelay);
this.problematicResource = Objects.requireNonNull(problematicResource);
}
/**
* Returns the destination node of the infeasible cycle.
*
* @return the destination node
* @throws UnsupportedOperationException if the destination node is null
*/
public ResourceNode getDestinationNode() {
if (destinationNode == null) {
throw new UnsupportedOperationException("Destination node must be set first.");
}
return destinationNode;
}
/**
* Returns the layer of the destination node.
*
* @return the destination node's layer
* @throws UnsupportedOperationException if the layer is null
*/
public int getDestinationNodeLayer() {
if (destinationNodeLayer == null) {
throw new UnsupportedOperationException("Destination node layer must be set first.");
}
return destinationNodeLayer;
public Resource getProblematicResource() {
return problematicResource;
}
@Override
......@@ -117,12 +63,11 @@ public class StartConfiguration extends MinIICycleConfiguration {
if (!super.equals(o))
return false;
StartConfiguration that = (StartConfiguration) o;
return Objects.equals(destinationNode, that.destinationNode) && Objects
.equals(destinationNodeLayer, that.destinationNodeLayer);
return Objects.equals(problematicResource, that.problematicResource);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), destinationNode, destinationNodeLayer);
return Objects.hash(super.hashCode(), problematicResource);
}
}
......@@ -25,9 +25,12 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;