Commit 14582279 authored by Sebastian Vollbrecht's avatar Sebastian Vollbrecht

Fixed some minor bugs.

- fixed faulty generator log output: certain graphs caused the 'creating edge x of y'-messages to contain wrong x/y values
- fixed a test case
parent fc62c362
...@@ -213,9 +213,6 @@ public final class GraphGenerator { ...@@ -213,9 +213,6 @@ public final class GraphGenerator {
nodes.forEach(n -> nodeTable.put(n.getId(), n)); nodes.forEach(n -> nodeTable.put(n.getId(), n));
Map<ResourceNode, Integer> asapTimes = new HashMap<>(); Map<ResourceNode, Integer> asapTimes = new HashMap<>();
nodes.forEach(n -> asapTimes.put(n, -1));
asapTimes.put(SOURCE, -1);
asapTimes.put(SINK, -1);
edgeCreator.setASAPTimesMap(asapTimes); edgeCreator.setASAPTimesMap(asapTimes);
edgeIncluder.setASAPTimesMap(asapTimes); edgeIncluder.setASAPTimesMap(asapTimes);
...@@ -223,15 +220,17 @@ public final class GraphGenerator { ...@@ -223,15 +220,17 @@ public final class GraphGenerator {
property.generateProperty(layers, Collections.unmodifiableSet(nodes), nodeTable, edgeCreator); property.generateProperty(layers, Collections.unmodifiableSet(nodes), nodeTable, edgeCreator);
nodes.add(SOURCE);
nodes.add(SINK);
if (verbose) { if (verbose) {
out.println("\tLayer structure post property generation: " + layers.toString()); out.println("\tLayer structure post property generation: " + layers.toString());
out.println("\tGenerated edges post property generation: " + edgeCreator.edgeView()); out.println("\tGenerated edges post property generation: " + edgeCreator.edgeView());
out.println("\tGenerating incoming edges."); out.println("\tGenerating incoming edges.");
} }
nodes.add(SOURCE);
nodes.add(SINK);
nodes.forEach(n -> asapTimes.put(n, -1));
generateIncomingEdges(layers, nodes, nodeTable, asapTimes, seed); generateIncomingEdges(layers, nodes, nodeTable, asapTimes, seed);
if (verbose) { if (verbose) {
...@@ -568,13 +567,21 @@ public final class GraphGenerator { ...@@ -568,13 +567,21 @@ public final class GraphGenerator {
private void generateOptionalEdges(LayerStructure layers, Set<ResourceNode> nodes, private void generateOptionalEdges(LayerStructure layers, Set<ResourceNode> nodes,
Map<Integer, ResourceNode> nodeTable, Map<ResourceNode, Integer> asapTimes) { Map<Integer, ResourceNode> nodeTable, Map<ResourceNode, Integer> asapTimes) {
long maxEdgeCount = verbose ? GraphUtils.getMaxPossibleEdgeNumber(layers) : 0; long maxEdgeCount = getMaxPossibleEdgeNumber(layers);
long currentEdgeCount = verbose ? edgeCreator.edgeView().stream().filter(e -> !e.isBackedge()).count() : 0; long currentEdgeCount = 0;
for (Edge<ResourceNode> edge : edgeCreator.edgeView()) {
if (edge.isBackedge() || edge.getSrc() == SOURCE || edge.getDst() == SINK) {
continue;
}
currentEdgeCount++;
}
for (ResourceNode src : JavaUtils.asShuffledList(nodes, rng)) { for (ResourceNode src : JavaUtils.asShuffledList(nodes, rng)) {
if (src == SOURCE || src == SINK) if (src == SOURCE || src == SINK) {
continue; continue;
}
int srcLayer = layers.getDepth(src); int srcLayer = layers.getDepth(src);
...@@ -586,12 +593,14 @@ public final class GraphGenerator { ...@@ -586,12 +593,14 @@ public final class GraphGenerator {
for (ResourceNode dst : JavaUtils.asShuffledList(dstNodes, rng)) { for (ResourceNode dst : JavaUtils.asShuffledList(dstNodes, rng)) {
/* /*
* Check if the edge is a valid edge. An edge is not valid if an edge exists * Check if the edge is a valid edge. An edge is not valid if an edge exists
* already between the two nodes. * already between the two nodes.
*/ */
if (!edgeCreator.isEdgeValid(src, dst)) if (!edgeCreator.isEdgeValid(src, dst)) {
continue; continue;
}
int delay = edgeCreator.computeEdgeDelay(src, dst); int delay = edgeCreator.computeEdgeDelay(src, dst);
...@@ -633,36 +642,37 @@ public final class GraphGenerator { ...@@ -633,36 +642,37 @@ public final class GraphGenerator {
Map<Integer, Set<ResourceNode>> asapSlots = JavaUtils.invertMap(asapTimes); Map<Integer, Set<ResourceNode>> asapSlots = JavaUtils.invertMap(asapTimes);
long maxBackedgeCount = GraphUtils.getMaxPossibleBackedgeNumber(asapSlots); long maxBackedgeCount = getMaxPossibleBackedgeNumber(asapSlots);
long currentBackedgeCount = edgeCreator.edgeView().stream().filter(Edge::isBackedge).count(); long currentBackedgeCount = edgeCreator.edgeView().stream().filter(Edge::isBackedge).count();
int asapMax = Collections.max(asapSlots.keySet()); List<Integer> asapSlotsSorted = JavaUtils.asSortedList(asapSlots.keySet());
for (int i = asapMax; i >= 0; i--) { for (int i = 0; i < asapSlotsSorted.size(); i++) {
if (!asapSlots.containsKey(i)) int srcSlot = asapSlotsSorted.get(i);
continue;
// For every node in the current ASAP slot... // For every node in the current ASAP slot...
for (ResourceNode src : JavaUtils.asShuffledList(asapSlots.get(i), rng)) { for (ResourceNode src : JavaUtils.asShuffledList(asapSlots.get(srcSlot), rng)) {
if (src == SOURCE || src == SINK) if (src == SOURCE || src == SINK) {
continue; continue;
}
// .. iterate through all possible ASAP slots... // .. iterate through all possible ASAP slots...
for (int j = i; j >= 0; j--) { for (int j = 0; j <= i; j++) {
if (!asapSlots.containsKey(j)) int dstSlot = asapSlotsSorted.get(j);
continue;
// ... and their nodes. // ... and their nodes.
for (ResourceNode dst : JavaUtils.asShuffledList(asapSlots.get(j), rng)) { for (ResourceNode dst : JavaUtils.asShuffledList(asapSlots.get(dstSlot), rng)) {
if (dst == SOURCE || dst == SINK || src == dst) if (dst == SOURCE || dst == SINK) {
continue; continue;
}
if (!edgeCreator.isBackedgeValid(src, dst)) if (!edgeCreator.isBackedgeValid(src, dst)) {
continue; continue;
}
int delay = edgeCreator.computeBackedgeDelay(src, dst); int delay = edgeCreator.computeBackedgeDelay(src, dst);
int distance = edgeCreator.computeBackedgeDistance(src, dst); int distance = edgeCreator.computeBackedgeDistance(src, dst);
...@@ -696,7 +706,6 @@ public final class GraphGenerator { ...@@ -696,7 +706,6 @@ public final class GraphGenerator {
} }
} }
} }
} }
/** /**
...@@ -763,6 +772,79 @@ public final class GraphGenerator { ...@@ -763,6 +772,79 @@ public final class GraphGenerator {
return JavaUtils.asSet(ids.stream().map(nodeTable::get)); return JavaUtils.asSet(ids.stream().map(nodeTable::get));
} }
/**
* Computes the maximum possible number of edges using the provided layer structure.
*
* @param layers the layer structure
* @return the maximum possible number of edges
*/
private static int getMaxPossibleEdgeNumber(LayerStructure layers) {
int maxAmount = 0;
for (int srcLayer = 0; srcLayer < layers.getHeight() - 1; srcLayer++) {
int srcLayerSize = layers.getLayer(srcLayer).size();
int possibleConnections = 0;
for (int dstLayer = srcLayer + 1; dstLayer < layers.getHeight(); dstLayer++) {
possibleConnections += layers.getLayer(dstLayer).size();
}
maxAmount += srcLayerSize * possibleConnections;
}
return maxAmount;
}
/**
* Computes the maximum possible number of backedges using the provided map of ASAP slots.
*
* @param asapSlots the ASAP slots
* @return the maximum possible number of backedges
*/
private static int getMaxPossibleBackedgeNumber(Map<Integer, Set<ResourceNode>> asapSlots) {
int maxAmount = 0;
for (int srcSlot : asapSlots.keySet()) {
int srcSlotSize = asapSlots.get(srcSlot).size();
if (asapSlots.get(srcSlot).contains(SOURCE)) {
srcSlotSize--;
}
if (asapSlots.get(srcSlot).contains(SINK)) {
srcSlotSize--;
}
int possibleConnections = 0;
for (int dstSlot : asapSlots.keySet()) {
if (dstSlot <= srcSlot) {
int dstSlotSize = asapSlots.get(dstSlot).size();
if (asapSlots.get(dstSlot).contains(SOURCE)) {
dstSlotSize--;
}
if (asapSlots.get(dstSlot).contains(SINK)) {
dstSlotSize--;
}
// Take src == dst into account.
if (srcSlot == dstSlot) {
dstSlotSize--;
}
possibleConnections += dstSlotSize;
}
}
maxAmount += srcSlotSize * possibleConnections;
}
return maxAmount;
}
/** /**
* This class is the default property class, used by the {@link GraphGenerator} if no specific property is supplied. * This class is the default property class, used by the {@link GraphGenerator} if no specific property is supplied.
* It never changes a graph and never returns false on an edge validity check. * It never changes a graph and never returns false on an edge validity check.
......
...@@ -61,6 +61,7 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -61,6 +61,7 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
private final Map<ResourceNode, Set<Edge<ResourceNode>>> incomingBackedges; private final Map<ResourceNode, Set<Edge<ResourceNode>>> incomingBackedges;
private LayerStructure layers; private LayerStructure layers;
private Map<ResourceNode, Integer> asapTimes;
private boolean strict; private boolean strict;
/** /**
...@@ -95,8 +96,8 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -95,8 +96,8 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
* @param dst the edge's destination node * @param dst the edge's destination node
* @param delay the edge's delay * @param delay the edge's delay
* @return the created edge * @return the created edge
* @throws IllegalEdgeException if the delay is less than 0 or if the source and destination nodes are connected * @throws IllegalEdgeException if the delay is less than 0 or if the edge is {@link #isEdgeValid(ResourceNode,
* through a forward edge already * ResourceNode) invalid}
* @throws StrictModeException if the edge creator is in strict mode and any of the preventive measures specified * @throws StrictModeException if the edge creator is in strict mode and any of the preventive measures specified
* in the {@link #setStrict(boolean)}-method isn't met * in the {@link #setStrict(boolean)}-method isn't met
*/ */
...@@ -140,8 +141,8 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -140,8 +141,8 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
* @param delay the backedge's delay * @param delay the backedge's delay
* @param distance the backedge's distance * @param distance the backedge's distance
* @return the created backedge * @return the created backedge
* @throws IllegalEdgeException if the delay is less than 0, if the distance is not greater than 0 or if the source * @throws IllegalEdgeException if the delay is less than 0, if the distance is not greater than 0 or if it is
* and destination nodes are connected through a backedge already * {@link #isBackedgeValid(ResourceNode, ResourceNode) invalid}
* @throws StrictModeException if the edge creator is in strict mode and any of the preventive measures specified * @throws StrictModeException if the edge creator is in strict mode and any of the preventive measures specified
* in the {@link #setStrict(boolean)}-method isn't met * in the {@link #setStrict(boolean)}-method isn't met
*/ */
...@@ -153,7 +154,7 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -153,7 +154,7 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
if (distance <= 0) if (distance <= 0)
throw new IllegalEdgeException(distance, true); throw new IllegalEdgeException(distance, true);
if (src != GraphGenerator.SOURCE && dst != GraphGenerator.SINK && !isBackedgeValid(src, dst)) if (!isBackedgeValid(src, dst))
throw new IllegalEdgeException(src, dst, true); throw new IllegalEdgeException(src, dst, true);
if (strict) { if (strict) {
...@@ -194,8 +195,8 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -194,8 +195,8 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
* An edge is valid iff any of these two conditions is met: * An edge is valid iff any of these two conditions is met:
* <ul> * <ul>
* <li>the source node's depth is less than the destination node's depth</li> * <li>the source node's depth is less than the destination node's depth</li>
* <li>the source or destination node (or both) are virtual source and sink * <li>the source node is the virtual sink node or if the destination node is the virtual source
* nodes</li> * node</li>
* </ul> * </ul>
* and if there doesn't exist a forward edge connecting the two nodes already. * and if there doesn't exist a forward edge connecting the two nodes already.
* *
...@@ -205,6 +206,14 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -205,6 +206,14 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
*/ */
public boolean isEdgeValid(ResourceNode src, ResourceNode dst) { public boolean isEdgeValid(ResourceNode src, ResourceNode dst) {
if (src == GraphGenerator.SINK) {
return false;
}
if (dst == GraphGenerator.SOURCE) {
return false;
}
if (src != GraphGenerator.SOURCE && dst != GraphGenerator.SINK) { if (src != GraphGenerator.SOURCE && dst != GraphGenerator.SINK) {
if (layers.getDepth(src) >= layers.getDepth(dst)) { if (layers.getDepth(src) >= layers.getDepth(dst)) {
return false; return false;
...@@ -224,13 +233,12 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -224,13 +233,12 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
* Returns whether a backedge connecting the source and destination nodes would be valid. Note that this method does * Returns whether a backedge connecting the source and destination nodes would be valid. Note that this method does
* not use the internal {@link EdgeIncluder} to decide validity. * not use the internal {@link EdgeIncluder} to decide validity.
* <p> * <p>
* A backedge is valid iff any of these two conditions is met: * A backedge is invalid iff any of these conditions is met:
* <ul> * <ul>
* <li>the source and destination nodes are distinct</li> * <li>the source and destination nodes are not distinct</li>
* <li>the source or destination node (or both) are virtual source and sink * <li>the source node's ASAP time is less than the destination node's ASAP time</li>
* nodes</li> * <li>there exists a backedge connecting these two nodes already</li>
* </ul> * </ul>
* and if there doesn't exist a backedge connecting the two nodes already.
* *
* @param src the edge's source node * @param src the edge's source node
* @param dst the edge's destination node * @param dst the edge's destination node
...@@ -238,8 +246,15 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -238,8 +246,15 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
*/ */
public boolean isBackedgeValid(ResourceNode src, ResourceNode dst) { public boolean isBackedgeValid(ResourceNode src, ResourceNode dst) {
if (src != GraphGenerator.SOURCE && dst != GraphGenerator.SINK && src == dst) if (src == dst) {
return false; return false;
}
if (asapTimes.containsKey(src) && asapTimes.containsKey(dst)) {
if (asapTimes.get(src) < asapTimes.get(dst)) {
return false;
}
}
outgoingBackedges.putIfAbsent(src, new HashSet<>()); outgoingBackedges.putIfAbsent(src, new HashSet<>());
outgoingBackedges.putIfAbsent(dst, new HashSet<>()); outgoingBackedges.putIfAbsent(dst, new HashSet<>());
...@@ -296,6 +311,9 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -296,6 +311,9 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
@Override @Override
public void setASAPTimesMap(Map<ResourceNode, Integer> asapTimes) { public void setASAPTimesMap(Map<ResourceNode, Integer> asapTimes) {
this.asapTimes = asapTimes;
edgeDelayComputer.setASAPTimesMap(asapTimes); edgeDelayComputer.setASAPTimesMap(asapTimes);
backedgeDelayComputer.setASAPTimesMap(asapTimes); backedgeDelayComputer.setASAPTimesMap(asapTimes);
backedgeDistanceComputer.setASAPTimesMap(asapTimes); backedgeDistanceComputer.setASAPTimesMap(asapTimes);
...@@ -311,6 +329,9 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC ...@@ -311,6 +329,9 @@ public class EdgeCreator extends Observable<Edge<ResourceNode>> implements EdgeC
@Override @Override
public void reset() { public void reset() {
layers = null;
asapTimes = null;
edges.clear(); edges.clear();
outgoingEdges.clear(); outgoingEdges.clear();
......
...@@ -1772,57 +1772,6 @@ public class GraphUtils { ...@@ -1772,57 +1772,6 @@ public class GraphUtils {
} }
} }
/**
* Computes the maximum possible number of edges using the provided layer structure.
*
* @param layers the layer structure
* @return the maximum possible number of edges
*/
public static int getMaxPossibleEdgeNumber(LayerStructure layers) {
int maxAmount = 0;
for (int srcLayer = 0; srcLayer < layers.getHeight() - 1; srcLayer++) {
int srcLayerSize = layers.getLayer(srcLayer).size();
int possibleConnections = 0;
for (int dstLayer = srcLayer + 1; dstLayer < layers.getHeight(); dstLayer++) {
possibleConnections += layers.getLayer(dstLayer).size();
}
maxAmount += srcLayerSize * possibleConnections;
}
return maxAmount;
}
/**
* Computes the maximum possible number of backedges using the provided map of ASAP slots.
*
* @param <N> the node type
* @param asapSlots the ASAP slots
* @return the maximum possible number of backedges
*/
public static <N extends Node> int getMaxPossibleBackedgeNumber(Map<Integer, Set<N>> asapSlots) {
int maxAmount = 0;
for (int srcSlot : JavaUtils.asSortedList(asapSlots.keySet())) {
int srcSlotSize = asapSlots.get(srcSlot).size();
int possibleConnections = 0;
for (int dstSlot : JavaUtils.asSortedList(asapSlots.keySet())) {
if (dstSlot == srcSlot)
possibleConnections += asapSlots.get(dstSlot).size() - 1;
else
possibleConnections += asapSlots.get(dstSlot).size();
}
maxAmount += srcSlotSize * possibleConnections;
}
return maxAmount;
}
/** /**
* Constructs a graph from the given graph without the edges matching the specified edge type. * Constructs a graph from the given graph without the edges matching the specified edge type.
* *
......
...@@ -39,7 +39,7 @@ public class LayerStructureTest { ...@@ -39,7 +39,7 @@ public class LayerStructureTest {
int id = GraphGenerator.SINK.getId() + 1; int id = GraphGenerator.SINK.getId() + 1;
List<Integer> layer0 = Arrays.asList(id); List<Integer> layer0 = Arrays.asList(id++);
List<Integer> layer1 = Arrays.asList(id++, id++, id++, id++, id++); List<Integer> layer1 = Arrays.asList(id++, id++, id++, id++, id++);
List<Integer> layer2 = Arrays.asList(id++, id++, id++, id++); List<Integer> layer2 = Arrays.asList(id++, id++, id++, id++);
List<Integer> layer3 = Arrays.asList(id++, id++, id++); List<Integer> layer3 = Arrays.asList(id++, id++, id++);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment