Commit 9354d739 authored by Sebastian Vollbrecht's avatar Sebastian Vollbrecht
Browse files

Added new classes & tests related to the creation of feasible MinII cycles.

Also redesigned the corresponding type hierarchy (including the classes of the infeasible MinII cycles).
parent 26f9eb00
Loading
Loading
Loading
Loading
+107 −0
Original line number Diff line number Diff line
@@ -15,43 +15,78 @@
 * limitations under the License.
 */

package graphgen.generator.components.properties.minII.infeasible.configuration;
package graphgen.generator.components.properties.minII;

import graphgen.graph.LayerStructure;
import graphgen.graph.Resource;
import graphgen.graph.ResourceNode;

import java.util.Map;
import java.util.Objects;

/**
 * The start configuration represents the very start of an infeasible cycle. It contains the cycle's problematic
 * resource.
 * The abstract base class of the configuration classes related to creating feasible or infeasible MinII-specific
 * cycles. It stores the graph's layer structure, the node table and the cycle's maximum inner delay. The maximum inner
 * delay must not be exceeded in order to ensure corresponding MinIIs or other cycle properties.
 *
 * @author Sebastian Vollbrecht
 */
public class StartConfiguration extends MinIICycleConfiguration {
public abstract class MinIICycleConfiguration {

	private final Resource problematicResource;
	protected final LayerStructure layers;
	protected final Map<Integer, ResourceNode> nodeTable;

	/**
	 * Creates a new start configuration based on the provided arguments.
	 * The cycle's maximum inner delay which must not be exceeded in order to ensure its corresponding MinII (or other
	 * cycle properties).
	 */
	protected final int maxInnerDelay;

	/**
	 * Creates a new 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
	 * @param maxInnerDelay the cycle's maximum inner delay
	 * @param problematicResource  the cycle's problematic resource
	 */
	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);
	protected MinIICycleConfiguration(LayerStructure layers, Map<Integer, ResourceNode> nodeTable, int maxInnerDelay) {
		this.layers = Objects.requireNonNull(layers);
		this.nodeTable = Objects.requireNonNull(nodeTable);

		if (maxInnerDelay < 0) {
			throw new IllegalArgumentException("The maximum inner delay cannot be negative.");
		}
		this.maxInnerDelay = maxInnerDelay;
	}

	public Resource getProblematicResource() {
		return problematicResource;
	protected MinIICycleConfiguration(MinIICycleConfiguration other) {
		this(other.layers, other.nodeTable, other.maxInnerDelay);
	}

	/**
	 * Returns the graph's layer structure.
	 *
	 * @return the layer structure
	 */
	public LayerStructure getLayers() {
		return layers;
	}

	/**
	 * Returns the graph's mapping of node IDs to nodes.
	 *
	 * @return the node table
	 */
	public Map<Integer, ResourceNode> getNodeTable() {
		return nodeTable;
	}

	/**
	 * Returns the cycle's inner delay.
	 *
	 * @return the cycle's inner delay
	 */
	public int getMaxInnerDelay() {
		return maxInnerDelay;
	}

	@Override
@@ -60,14 +95,13 @@ public class StartConfiguration extends MinIICycleConfiguration {
			return true;
		if (o == null || getClass() != o.getClass())
			return false;
		if (!super.equals(o))
			return false;
		StartConfiguration that = (StartConfiguration) o;
		return Objects.equals(problematicResource, that.problematicResource);
		MinIICycleConfiguration that = (MinIICycleConfiguration) o;
		return maxInnerDelay == that.maxInnerDelay && Objects.equals(layers, that.layers) && Objects
				.equals(nodeTable, that.nodeTable);
	}

	@Override
	public int hashCode() {
		return Objects.hash(super.hashCode(), problematicResource);
		return Objects.hash(layers, nodeTable, maxInnerDelay);
	}
}
+140 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 Sebastian Vollbrecht, Julian Oppermann
 * Embedded Systems and Applications Group, TU Darmstadt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package graphgen.generator.components.properties.minII;

import graphgen.datastructures.Pair;
import graphgen.datastructures.SeededRandom;
import graphgen.generator.components.properties.minII.util.PlannedEdge;
import graphgen.graph.ResourceNode;
import graphgen.util.JavaUtils;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * This is the abstract base class of classes which deal with interconnecting nodes in MinII-specific cycles. Besides
 * some small utility methods, it provides methods for determining needed edges (in terms of source-destination pairs)
 * and for distributing individual amounts of delay over sets of planned edges. For these purposes it also stores the
 * generator's {@link SeededRandom} instance.
 *
 * @author Sebastian Vollbrecht
 */
public abstract class MinIICycleEdgePlanner {

	protected final SeededRandom rng;

	protected MinIICycleEdgePlanner(SeededRandom rng) {
		this.rng = Objects.requireNonNull(rng);
	}

	/**
	 * Computes source-destination node pairs for every destination node which needs an incoming edge.
	 *
	 * @return the source-destination node pairs
	 */
	protected abstract Set<Pair<ResourceNode, ResourceNode>> getIncomingEdgePairs();

	/**
	 * Distributes some internally computed delay over the provided set of edges.
	 *
	 * @param edges the set of edges to distribute the delay over
	 */
	protected abstract void distributeDelay(Set<PlannedEdge> edges);

	/**
	 * Distributes an amount of delay uniformly (for delays approaching infinity) over a collection of planned edges.
	 *
	 * @param plannedEdges the collection of planned edges
	 * @param delay        the delay to distribute
	 * @param rng          the {@link SeededRandom} instance to use
	 * @throws NullPointerException     if the set of edges is null
	 * @throws IllegalArgumentException if the set of edges is empty and the delay to distribute is non-zero, or if the
	 *                                  delay is negative
	 */
	protected static void uniformlyDistributeDelay(Collection<PlannedEdge> plannedEdges, int delay, SeededRandom rng) {

		if (plannedEdges.isEmpty() && delay > 0) {
			throw new IllegalArgumentException("Cannot distribute delay of " + delay + " over non-existent edges.");
		} else if (delay < 0) {
			throw new IllegalArgumentException("The delay cannot be negative.");
		}

		while (delay > 0) {
			JavaUtils.pickRandomElement(plannedEdges, rng).delay++;
			delay--;
		}
	}

	/**
	 * Maps nodes to their incoming edge, based on the provided set of edges. The set containing the relevant nodes is
	 * used to determine which nodes to include in the returned map.
	 *
	 * @param edges         the set of edges
	 * @param relevantNodes the nodes to consider
	 * @return a mapping of relevant nodes to their incoming edge
	 * @throws IllegalArgumentException if any of the relevant nodes has more than one incoming edge or none at all
	 */
	protected static Map<ResourceNode, PlannedEdge> getIncomingEdgesMap(Set<PlannedEdge> edges,
																		Collection<ResourceNode> relevantNodes) {
		Map<ResourceNode, PlannedEdge> incomingEdgesByNode = new HashMap<>();

		for (PlannedEdge edge : Objects.requireNonNull(edges)) {

			if (Objects.requireNonNull(relevantNodes).contains(edge.src) && relevantNodes.contains(edge.dst)) {

				if (incomingEdgesByNode.containsKey(edge.dst)) {
					throw new IllegalArgumentException("Node " + edge.dst + " must have exactly one incoming edge.");
				}

				incomingEdgesByNode.put(edge.dst, edge);
			}
		}

		return incomingEdgesByNode;
	}

	/**
	 * Maps nodes to their outgoing edge, based on the provided set of edges. The set containing the relevant nodes is
	 * used to determine which nodes to include in the returned map.
	 *
	 * @param edges         the set of edges
	 * @param relevantNodes the nodes to consider
	 * @return a mapping of relevant nodes to their outgoing edge
	 * @throws IllegalArgumentException if any of the relevant nodes has more than one outgoing edge or none at all
	 */
	protected static Map<ResourceNode, PlannedEdge> getOutgoingEdgesMap(Set<PlannedEdge> edges,
																		Collection<ResourceNode> relevantNodes) {
		Map<ResourceNode, PlannedEdge> outgoingEdgesByNode = new HashMap<>();

		for (PlannedEdge edge : Objects.requireNonNull(edges)) {
			if (Objects.requireNonNull(relevantNodes).contains(edge.src) && relevantNodes.contains(edge.dst)) {

				if (outgoingEdgesByNode.containsKey(edge.src)) {
					throw new IllegalArgumentException("Node " + edge.src + " must have exactly one outgoing edge.");
				}

				outgoingEdgesByNode.put(edge.src, edge);
			}
		}
		return outgoingEdgesByNode;
	}

}
+4 −4
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ public abstract class MinIICycleInspector {
	 * @param backedgeDistance the distance of the backedge(s) which will <i>close</i> the cycle
	 * @return the cycle's minimum inner delay adhering to the above-mentioned requirements
	 */
	public abstract int getMinInnerDelay(int minII, int backedgeDelay, int backedgeDistance);
	protected abstract int getMinInnerDelay(int minII, int backedgeDelay, int backedgeDistance);

	/**
	 * Returns the maximum inner delay which a cycle induced by the given arguments can have. The implementing classes
@@ -62,7 +62,7 @@ public abstract class MinIICycleInspector {
	 * @param backedgeDistance the distance of the backedge(s) which will <i>close</i> the cycle
	 * @return the cycle's maximum inner delay adhering to the above-mentioned requirements
	 */
	public abstract int getMaxInnerDelay(int minII, int backedgeDelay, int backedgeDistance);
	protected abstract int getMaxInnerDelay(int minII, int backedgeDelay, int backedgeDistance);

	/**
	 * Returns the minimum inner delay which a cycle containing backedges with the specified parameters can have without
@@ -80,7 +80,7 @@ public abstract class MinIICycleInspector {
	 * @throws IllegalArgumentException if the MinII is not positive, if the delay is negative or if the distance is not
	 *                                  positive
	 */
	public static int minInnerDelay(int minII, int backedgeDelay, int backedgeDistance) {
	protected static int minInnerDelay(int minII, int backedgeDelay, int backedgeDistance) {
		if (minII <= 0) {
			throw new IllegalArgumentException("MinII must be positive.");
		} else if (backedgeDelay < 0) {
@@ -105,7 +105,7 @@ public abstract class MinIICycleInspector {
	 * @throws IllegalArgumentException if the MinII is not positive, if the delay is negative or if the distance is not
	 *                                  positive
	 */
	public static int maxInnerDelay(int minII, int backedgeDelay, int backedgeDistance) {
	protected static int maxInnerDelay(int minII, int backedgeDelay, int backedgeDistance) {
		if (minII <= 0) {
			throw new IllegalArgumentException("MinII must be positive.");
		} else if (backedgeDelay < 0) {
+51 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 Sebastian Vollbrecht, Julian Oppermann
 * Embedded Systems and Applications Group, TU Darmstadt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package graphgen.generator.components.properties.minII;

import graphgen.datastructures.SeededRandom;
import graphgen.graph.ResourceNode;

import java.util.Objects;
import java.util.Set;

/**
 * This is the abstract base class of classes which deal with arranging nodes in MinII-specific cycles. It provides a
 * single abstract method for placing nodes in certain target layers. It also stores the generator's {@link
 * SeededRandom} instance. This way, the implementing classes can choose the target layer randomly (or other things
 * which might be needed).
 *
 * @author Sebastian Vollbrecht
 */
public abstract class MinIICycleNodePlacer {

	protected final SeededRandom rng;

	protected MinIICycleNodePlacer(SeededRandom rng) {
		this.rng = Objects.requireNonNull(rng);
	}

	/**
	 * Places the specified node in one of the possible provided target layers. Depending on the property, this method
	 * might introduce further changes to the graph (e.g. moving other nodes around).
	 *
	 * @param node         the node to place in any of the layers
	 * @param targetLayers the layers the node can be placed in
	 */
	protected abstract void placeNode(ResourceNode node, Set<Integer> targetLayers);

}
+23 −23
Original line number Diff line number Diff line
@@ -33,36 +33,36 @@ import java.util.Set;
 *
 * @author Sebastian Vollbrecht
 */
public class FeasibleCycleInspector extends MinIICycleInspector {
class FeasibleCycleInspector extends MinIICycleInspector {

	public FeasibleCycleInspector(LayerStructure layers, Set<ResourceNode> nodes) {
	FeasibleCycleInspector(LayerStructure layers, Set<ResourceNode> nodes) {
		super(layers, nodes);
	}

	@Override
	public int getMinInnerDelay(int minII, int backedgeDelay, int backedgeDistance) {
	protected int getMinInnerDelay(int minII, int backedgeDelay, int backedgeDistance) {
		return minInnerDelay(minII, backedgeDelay, backedgeDistance);
	}

	@Override
	public int getMaxInnerDelay(int minII, int backedgeDelay, int backedgeDistance) {
	protected int getMaxInnerDelay(int minII, int backedgeDelay, int backedgeDistance) {
		return maxInnerDelay(minII, backedgeDelay, backedgeDistance);
	}

	/**
	 * Computes all destination nodes that could potentially be the destination node for the backedges of a feasible
	 * cycle.<p>A node can only be considered destination node if at least one other node exists which can be appended
	 * to the destination node without exceeding the specified inner delay.<p>In case of a two-element cycle consisting
	 * of these two nodes only, it is furthermore important to filter out nodes which might result in an
	 * <i>infeasible</i> cycle if connected to the destination node. For example, if both nodes shared the same
	 * Computes all initial nodes of a feasible cycle.<p>A node can only be considered initial node if at least one
	 * other node exists which can be appended to the initial node without exceeding the specified inner delay.<p>In
	 * case of a two-element cycle consisting of these two nodes only, it is furthermore important to filter out nodes
	 * which might result in an
	 * <i>infeasible</i> cycle if connected to the initial node. For example, if both nodes shared the same
	 * resource with delay 0 and a limit of 1, an edge with delay 0 would render their induced cycle infeasible.
	 *
	 * @param innerDelay the feasible cycle's inner delay
	 * @return a set containing all potential destination node candidates
	 * @return a set containing all potential initial node candidates
	 */
	public Set<ResourceNode> getPossibleDstNodes(int innerDelay) {
	Set<ResourceNode> getPossibleInitialNodes(int innerDelay) {

		Set<ResourceNode> possibleDstNodes = new HashSet<>();
		Set<ResourceNode> possibleInitialNodes = new HashSet<>();

		Map<Integer, Set<ResourceNode>> nodesByDelay = new HashMap<>();
		for (ResourceNode node : nodes) {
@@ -78,9 +78,9 @@ public class FeasibleCycleInspector extends MinIICycleInspector {
				continue;
			}

			for (ResourceNode dstNode : firstEntry.getValue()) {
			for (ResourceNode initialNode : firstEntry.getValue()) {

				if (possibleDstNodes.contains(dstNode)) {
				if (possibleInitialNodes.contains(initialNode)) {
					continue;
				}

@@ -97,22 +97,22 @@ public class FeasibleCycleInspector extends MinIICycleInspector {

					for (ResourceNode otherNode : secondEntry.getValue()) {

						if (dstNode == otherNode) {
						if (initialNode == otherNode) {
							continue;
						}

						/*
						 * Infeasibility check.
						 */
						if (dstNode.resource == otherNode.resource) {
							if (dstNode.resource.delay == 0 && dstNode.resource.limit == 1) {
						if (initialNode.resource == otherNode.resource) {
							if (initialNode.resource.delay == 0 && initialNode.resource.limit == 1) {

								/*
								 * If there is no inner delay remaining if these two nodes were used,
								 * they would need to be connected with an edge with delay 0, thus
								 * rendering the cycle infeasible.
								 */
								if (innerDelay - (2 * dstNode.resource.delay) == 0) {
								if (innerDelay - (2 * initialNode.resource.delay) == 0) {
									continue;
								}
							}
@@ -120,11 +120,11 @@ public class FeasibleCycleInspector extends MinIICycleInspector {

						/*
						 * If the first node can be the destination node, the second one can automatically
						 * be the destination node as well (skipping them in the next iteration speeds up
						 * the calculation).
						 * be the destination node as well (by skipping them in the next iteration we can
						 * slightly speed up the calculation).
						 */
						possibleDstNodes.add(dstNode);
						possibleDstNodes.add(otherNode);
						possibleInitialNodes.add(initialNode);
						possibleInitialNodes.add(otherNode);
						break;

					}
@@ -132,7 +132,7 @@ public class FeasibleCycleInspector extends MinIICycleInspector {
			}
		}

		return possibleDstNodes;
		return possibleInitialNodes;

	}

Loading