Commit 89e2b3ee authored by Sebastian Vollbrecht's avatar Sebastian Vollbrecht

JavaDoc fixes and changes regarding the way the generation process is logged.

Also some other minimal changes.
parent 152176dd
......@@ -64,32 +64,17 @@ public class Pair<T1, T2> {
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((first == null) ? 0 : first.hashCode());
result = prime * result + ((second == null) ? 0 : second.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
public boolean equals(Object o) {
if (this == o)
return true;
if (obj == null)
return false;
if (!(obj instanceof Pair))
if (o == null || getClass() != o.getClass())
return false;
Pair<?, ?> other = (Pair<?, ?>) obj;
if (first == null) {
if (other.first != null)
return false;
} else if (!first.equals(other.first))
return false;
if (second == null) {
return other.second == null;
} else
return second.equals(other.second);
Pair<?, ?> pair = (Pair<?, ?>) o;
return Objects.equals(first, pair.first) && Objects.equals(second, pair.second);
}
@Override
public int hashCode() {
return Objects.hash(first, second);
}
}
......@@ -84,6 +84,17 @@ public class SeededRandom {
return rng.nextDouble();
}
/**
* Returns a random long value.
*
* @return the random long value
* @throws UnsupportedOperationException if this instance has not yet been seeded
*/
public long nextLong() {
checkSeededStatus();
return rng.nextLong();
}
/**
* Returns the wrapped random instance.
*
......
......@@ -19,6 +19,7 @@ package graphgen.generator;
import graphgen.datastructures.Pair;
import graphgen.datastructures.SeededRandom;
import graphgen.enums.ResourceType;
import graphgen.generator.components.StrictComponent;
import graphgen.generator.components.edges.EdgeCreator;
import graphgen.generator.components.edges.includers.EdgeIncluder;
......@@ -36,6 +37,7 @@ import graphgen.util.GraphUtils;
import graphgen.util.JavaUtils;
import modsched.Edge;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
......@@ -84,7 +86,6 @@ public final class GraphGenerator implements StrictComponent {
private final SeededRandom rng;
private final EdgeInclusionDuplicateChecker edgeChecker;
private boolean verbose = false;
private PrintStream out = System.out;
/**
......@@ -165,9 +166,7 @@ public final class GraphGenerator implements StrictComponent {
*/
public Graph<ResourceNode> createGraph(long seed) {
if (verbose) {
out.println("Creating graph with seed " + seed);
}
out.println("Creating graph with seed " + seed);
// Reset and clear generation objects.
layerCreator.reset();
......@@ -186,9 +185,7 @@ public final class GraphGenerator implements StrictComponent {
GeneratedLayerStructure layers = layerCreator.createLayerStructure();
if (verbose) {
out.println("\tGenerated layer structure: " + layers.toString());
}
out.println("\tGenerated layer structure: " + layers.toString());
edgeCreator.addObserver(layers);
edgeCreator.addObserver(property);
......@@ -201,9 +198,17 @@ public final class GraphGenerator implements StrictComponent {
Set<ResourceNode> nodes = nodeCreator.createNodes(layers);
if (verbose) {
out.println("\tGenerated nodes: " + nodes.toString());
out.print("\tResources in use: [");
List<Resource> resourcesUsed = new ArrayList<>(GraphUtils.getResources(nodes, ResourceType.ALL));
for (int i = 0; i < resourcesUsed.size(); i++) {
if (i > 0) {
out.print(", ");
}
Resource r = resourcesUsed.get(i);
out.print(String.format("(%s, %d, %d)", r.name, r.delay, r.limit));
}
out.println("]");
out.println("\tGenerated nodes: " + nodes.toString());
Map<Integer, ResourceNode> nodeTable = new HashMap<>();
nodes.forEach(n -> nodeTable.put(n.getId(), n));
......@@ -218,11 +223,9 @@ public final class GraphGenerator implements StrictComponent {
edgeCreator
);
if (verbose) {
out.println("\tLayer structure post property generation: " + layers.toString());
out.println("\tGenerated edges post property generation: " + edgeCreator.edgeView());
out.println("\tGenerating incoming edges.");
}
out.println("\tLayer structure post property generation: " + layers.toString());
out.println("\tGenerated edges post property generation: " + edgeCreator.edgeView());
out.println("\tGenerating incoming edges.");
nodes.add(SOURCE);
nodes.add(SINK);
......@@ -231,22 +234,16 @@ public final class GraphGenerator implements StrictComponent {
generateIncomingEdges(layers, nodes, nodeTable, asapTimes);
if (verbose) {
out.println("\tGenerating outgoing edges.");
}
out.println("\tGenerating outgoing edges.");
generateOutgoingEdges(layers, nodes, nodeTable, asapTimes);
if (verbose) {
out.println("\tGenerating optional edges.");
}
out.println("\tGenerating optional edges.");
generateOptionalEdges(layers, nodes, nodeTable, asapTimes);
verifyASAPTimesMap(edgeCreator.edgeView(), asapTimes);
if (verbose) {
out.println("\tGenerating remaining backedges.");
}
out.println("\tGenerating remaining backedges.");
generateBackedges(asapTimes);
......@@ -280,11 +277,11 @@ public final class GraphGenerator implements StrictComponent {
for (int i = 0; i < amount; i++) {
if (!graphs.add(createGraph(seed)) && verbose) {
out.println("Duplicate detected.");
if (!graphs.add(createGraph(seed))) {
out.println("Duplicate detected (seed: " + seed + ").");
}
seed = rng.getRandom().nextLong();
seed = rng.nextLong();
}
} else {
......@@ -298,11 +295,11 @@ public final class GraphGenerator implements StrictComponent {
if (!GraphUtils.isGraphIsomorphicToAny(graph, asapTimes, asapTimesMap))
graphs.add(graph);
else if (verbose) {
out.println("Isomorphism detected.");
else {
out.println("Isomorphism detected (seed: " + seed + ").");
}
seed = rng.getRandom().nextLong();
seed = rng.nextLong();
}
}
......@@ -321,25 +318,26 @@ public final class GraphGenerator implements StrictComponent {
}
/**
* Sets the generator to verbose mode, i.e. that the generation process will be written to the provided print
* stream.
* Toggles the generator's verbosity. If a print print stream is supplied, the generation process will be written to
* it. If <i>out</i> is null, the generation process won't be documented.
* <p>
* Use <code>new PrintStream(new FileOutputStream(new File(filename))</code> to immediately write to a file.<br>
* Use<p>{@code new PrintStream(new FileOutputStream(new File(filename))}<p>to immediately write to a file.<br>
* <b>Warning</b>: The resulting file might be excessively large due to the
* amount of edges possible in large graphs (O(2*V<sup>2</sup>)).
*
* @param out the print stream
*/
public void setVerbose(PrintStream out) {
verbose = true;
this.out = out;
}
/**
* Sets the generator to non-verbose mode, i.e. that the generation process won't be documented.
* @param out the print stream used to document the generation process or null to disable any generation output
*/
public void setNonVerbose() {
verbose = false;
public void setOut(PrintStream out) {
if (out == null) {
this.out = new PrintStream(new OutputStream() {
@Override
public void write(int b) {
// Do nothing.
}
});
} else {
this.out = out;
}
}
/**
......@@ -375,9 +373,7 @@ public final class GraphGenerator implements StrictComponent {
if (hasMandatoryIncomingEdge)
continue;
if (verbose) {
out.println("\t\tTrying to generate an incoming edge for node " + dst);
}
out.println("\t\tTrying to generate an incoming edge for node " + dst);
/*
* Store source candidates with edge delays whose corresponding edges are
......@@ -400,9 +396,7 @@ public final class GraphGenerator implements StrictComponent {
int delay = edgeCreator.computeEdgeDelay(src, dst);
if (verbose) {
out.print("\t\t\t" + src + "--" + delay + "-->" + dst + ": ");
}
out.print("\t\t\t" + src + "--" + delay + "-->" + dst + ": ");
if (isEdgePossible(src, dst, delay)) {
if (edgeIncluder.includeEdge(new Edge<>(src, dst, delay, 0))) {
......@@ -414,14 +408,11 @@ public final class GraphGenerator implements StrictComponent {
possibleCandidates.add(Pair.of(src, delay));
if (verbose) {
out.println("optimal.");
}
out.println("optimal.");
} else {
if (verbose) {
out.println("the edge includer denied the inclusion.");
}
out.println("the edge includer denied the inclusion.");
if (!optimalCandidatesFound) {
possibleCandidates.add(Pair.of(src, delay));
......@@ -435,9 +426,7 @@ public final class GraphGenerator implements StrictComponent {
int delay;
if (possibleCandidates.isEmpty()) {
if (verbose) {
out.println("\t\t\tChosen incoming edge: " + SOURCE + "--" + 0 + "-->" + dst + ": ");
}
out.println("\t\t\tChosen incoming edge: " + SOURCE + "--" + 0 + "-->" + dst + ": ");
src = SOURCE;
delay = 0;
} else {
......@@ -445,12 +434,10 @@ public final class GraphGenerator implements StrictComponent {
src = srcAndDelay.first;
delay = srcAndDelay.second;
if (verbose) {
if (optimalCandidatesFound)
out.println("\t\t\tChosen incoming edge (optimal): " + src + "--" + delay + "-->" + dst + ": ");
else
out.println(
"\t\t\tChosen incoming edge (not optimal): " + src + "--" + delay + "-->" + dst + ": ");
if (optimalCandidatesFound) {
out.println("\t\t\tChosen incoming edge (optimal): " + src + "--" + delay + "-->" + dst + ": ");
} else {
out.println("\t\t\tChosen incoming edge (not optimal): " + src + "--" + delay + "-->" + dst + ": ");
}
}
......@@ -470,9 +457,7 @@ public final class GraphGenerator implements StrictComponent {
if (!edgeCreator.outgoingEdgesOf(src).isEmpty() || src == SINK)
continue;
if (verbose) {
out.println("\t\tTrying to generate an outgoing edge for node " + src);
}
out.println("\t\tTrying to generate an outgoing edge for node " + src);
int srcDepth = layers.getDepth(src);
......@@ -495,9 +480,7 @@ public final class GraphGenerator implements StrictComponent {
int delay = edgeCreator.computeEdgeDelay(src, dst);
if (verbose) {
out.print("\t\t\t" + src + "--" + delay + "-->" + dst + ": ");
}
out.print("\t\t\t" + src + "--" + delay + "-->" + dst + ": ");
if (isEdgePossible(src, dst, delay)) {
if (edgeIncluder.includeEdge(new Edge<>(src, dst, delay, 0))) {
......@@ -509,13 +492,11 @@ public final class GraphGenerator implements StrictComponent {
possibleCandidates.add(Pair.of(dst, delay));
if (verbose) {
out.println("optimal.");
}
out.println("optimal.");
} else {
if (verbose) {
out.println("the edge includer denied the inclusion.");
}
out.println("the edge includer denied the inclusion.");
if (!optimalCandidatesFound) {
possibleCandidates.add(Pair.of(dst, delay));
......@@ -528,9 +509,7 @@ public final class GraphGenerator implements StrictComponent {
int delay;
if (possibleCandidates.isEmpty()) {
if (verbose) {
out.println("\t\t\tChosen incoming edge: " + src + "--" + 0 + "-->" + SINK + ": ");
}
out.println("\t\t\tChosen incoming edge: " + src + "--" + 0 + "-->" + SINK + ": ");
dst = SINK;
delay = 0;
} else {
......@@ -538,12 +517,10 @@ public final class GraphGenerator implements StrictComponent {
dst = dstAndDelay.first;
delay = dstAndDelay.second;
if (verbose) {
if (optimalCandidatesFound)
out.println("\t\t\tChosen outgoing edge (optimal): " + src + "--" + delay + "-->" + dst + ": ");
else
out.println(
"\t\t\tChosen outgoing edge (not optimal): " + src + "--" + delay + "-->" + dst + ": ");
if (optimalCandidatesFound) {
out.println("\t\t\tChosen outgoing edge (optimal): " + src + "--" + delay + "-->" + dst + ": ");
} else {
out.println("\t\t\tChosen outgoing edge (not optimal): " + src + "--" + delay + "-->" + dst + ": ");
}
}
......@@ -597,30 +574,22 @@ public final class GraphGenerator implements StrictComponent {
int delay = edgeCreator.computeEdgeDelay(src, dst);
if (verbose) {
out.print(
"\t\tChecking inclusion of edge " + ++currentEdgeCount + " of " + maxEdgeCount + ": " + src + "--" + delay + "-->" + dst + ": ");
}
out.print(
"\t\tChecking inclusion of edge " + ++currentEdgeCount + " of " + maxEdgeCount + ": " + src + "--" + delay + "-->" + dst + ": ");
if (!edgeIncluder.includeEdge(new Edge<>(src, dst, delay, 0))) {
if (verbose) {
out.println("the edge includer denied the inclusion.");
}
out.println("the edge includer denied the inclusion.");
continue;
}
if (edgeChecker.hasEdgeBeenDeniedAlready(src, dst, delay) || !property.isEdgeValid(src, dst, delay)) {
if (verbose) {
out.println("the property denied the inclusion.");
}
out.println("the property denied the inclusion.");
continue;
}
edgeCreator.createEdge(src, dst, delay);
if (verbose) {
out.println("OK.");
}
out.println("OK.");
int newDstTime = asapTimes.get(src) + src.getDelay() + delay;
......@@ -670,30 +639,22 @@ public final class GraphGenerator implements StrictComponent {
int delay = edgeCreator.computeBackedgeDelay(src, dst);
int distance = edgeCreator.computeBackedgeDistance(src, dst);
if (verbose) {
out.print(
"\t\tChecking inclusion of backedge " + ++currentBackedgeCount + " of " + maxBackedgeCount + ": " + src + "--(" + delay + ", " + distance + ")-->" + dst + ": ");
}
out.print(
"\t\tChecking inclusion of backedge " + ++currentBackedgeCount + " of " + maxBackedgeCount + ": " + src + "--(" + delay + ", " + distance + ")-->" + dst + ": ");
if (!backedgeIncluder.includeEdge(new Edge<>(src, dst, delay, distance))) {
if (verbose) {
out.println("the backedge includer denied the inclusion.");
}
out.println("the backedge includer denied the inclusion.");
continue;
}
if (!property.isBackedgeValid(src, dst, delay, distance)) {
if (verbose) {
out.println("the property denied the inclusion.");
}
out.println("the property denied the inclusion.");
continue;
}
edgeCreator.createBackedge(src, dst, delay, distance);
if (verbose) {
out.println("OK.");
}
out.println("OK.");
}
}
......@@ -736,23 +697,17 @@ public final class GraphGenerator implements StrictComponent {
private boolean isEdgePossible(ResourceNode src, ResourceNode dst, int delay) {
if (!edgeCreator.isEdgeValid(src, dst)) {
if (verbose) {
out.println("the nodes are connected already.");
}
out.println("the nodes are connected already.");
return false;
}
if (edgeChecker.hasEdgeBeenDeniedAlready(src, dst, delay)) {
if (verbose) {
out.println("the property denied the inclusion.");
}
out.println("the property denied the inclusion.");
return false;
}
if (!property.isEdgeValid(src, dst, delay)) {
if (verbose) {
out.println("the property denied the inclusion.");
}
out.println("the property denied the inclusion.");
edgeChecker.addEdgeDenial(src, dst, delay);
return false;
}
......
......@@ -105,6 +105,8 @@ public abstract class ValueComputer implements EdgeCreationComponent, StrictComp
/**
* Tells the value computer which value it is actually computing. This edge value is then used used to determine (in
* strict mode) whether or not a created edge is illegal.
*
* @param edgeValue the edge value whose computation this value computer is used for
*/
public final void setEdgeValue(EdgeValue edgeValue) {
this.edgeValue = edgeValue;
......
......@@ -57,7 +57,7 @@ public class GeneratedLayerStructure extends LayerStructure implements StrictCom
}
/**
* Swaps the two IDs with each other (see {@link LayerStructure#swapIDs(int, int)}).
* Swaps the two IDs with each other.
*
* @throws IllegalSwapException if an illegal swap is detected, i.e. if the IDs are connected with an edge during a
* graph creation phase and if the swap would violate the layer structure implied by
......
......@@ -176,12 +176,17 @@ public abstract class MinIIProperty<C extends MinIICycleConfiguration> extends P
* It is the lower bound of the RecMinII formula's ceiling function and can be retrieved like so:
* <pre>RecMinII = ceil((minInnerDelay + backedgeDelay) / backedgeDistance)</pre>
* It follows that
* <pre>(minInnerDelay + backedgeDelay) / backedgeDistance > RecMinII - 1</pre>
* <pre>(minInnerDelay + backedgeDelay) / backedgeDistance &gt; RecMinII - 1</pre>
* and
* <pre>minInnerDelay > backedgeDistance * (RecMinII - 1) - backedgeDelay</pre><p>
* <pre>minInnerDelay &gt; backedgeDistance * (RecMinII - 1) - backedgeDelay</pre><p>
* Because the inner delay is an integer value, the smallest possible value which still fulfills the inequality is
* the result of adding 1 to the right-hand side.
*
* @param minII the MinII which needs to be ensured
* @param backedgeDelay the delay of possible RecMinII-ensuring backedges
* @param backedgeDistance the distance of possible RecMinII-ensuring backedges
* @return the minimum inner delay a cycle containing such RecMinII-ensuring backedges can have while still ensuring
* the specified MinII
* @throws IllegalArgumentException if the MinII is not greater than zero, if the delay is negative, if the distance
* is not greater than zero or if the backedge parameters already exceed the
* specified MinII
......@@ -202,6 +207,11 @@ public abstract class MinIIProperty<C extends MinIICycleConfiguration> extends P
* and
* <pre>RecMinII * backedgeDistance - backedgeDelay = maxInnerDelay</pre>
*
* @param minII the MinII which needs to be ensured
* @param backedgeDelay the delay of possible RecMinII-ensuring backedges
* @param backedgeDistance the distance of possible RecMinII-ensuring backedges
* @return the maximum inner delay a cycle containing such RecMinII-ensuring backedges can have while still ensuring
* the specified MinII
* @throws IllegalArgumentException if the MinII is not greater than zero, if the delay is negative, if the distance
* is not greater than zero or if the backedge parameters already exceed the
* specified MinII
......
......@@ -154,7 +154,6 @@ public class InfeasibleMinIIProperty extends MinIIProperty<InfeasibleConfigurati
ResourceNode dstNode;
/* Immediately choose a destination node to avoid listing all possibilities (see method doc). */
if (!nodesInCurrentLayer.isEmpty()) {
dstNode = JavaUtils.pickRandomElement(nodesInCurrentLayer, rng);
} else {
......
......@@ -52,6 +52,8 @@ public class LookupTables {
case BACKEDGE_DISTANCE:
probabilityMapping.put(1, 1.0);
break;
default:
throw new UnsupportedOperationException(edgeValue.toString());
}
return new DeterministicDistribution<>(probabilityMapping);
......
......@@ -54,15 +54,11 @@ public class GraphFileUtils {
/**
* Sanitizes a name so that it can be used as a filename without causing problems. For example:<br>
* <p>
* <code>
* sanitizeFilename("#thisIsATestGraph????!!")
* </code>
* {@code sanitizeFilename("#thisIsATestGraph????!!") }
* <p>
* would be sanitized to
* <p>
* <code>
* "_thisIsATestGraph_"
* </code>
* {@code "_thisIsATestGraph_" }
* <p>
* <b>Warning</b>: collisions can occur.
*
......@@ -76,15 +72,11 @@ public class GraphFileUtils {
/**
* Julianizes a path. For example:<br>
* <p>
* <code>
* julianizePath("./foo/bar/jpeg_export/graph46.graphml")
* </code>
* {@code julianizePath("./foo/bar/jpeg_export/graph46.graphml") }
* <p>
* would be julianized to
* <p>
* <code>
* "jpeg::graph46"
* </code>
* {@code "jpeg::graph46" }
* <p>
* <b>Warning</b>: collisions can occur.
*
......@@ -301,8 +293,7 @@ public class GraphFileUtils {
* Generates java code to create a {@link MoovacFormulation} from scratch for the given graph. The generated code is
* written to the provided print stream.
* <p>
* Use <code>new PrintStream(new FileOutputStream(new File(filename))</code> to immediately write the code to a
* file.
* Use {@code new PrintStream(new FileOutputStream(new File(filename))} to immediately write the code to a file.
*
* @param graph the graph to create the formulation code for
* @param problemName the formulation's problem name
......
......@@ -228,11 +228,7 @@ public class JavaUtils {
* @param key the key to insert or increment
*/
public static <K> void insertOrIncValue(Map<? super K, Integer> map, K key) {
if (!Objects.requireNonNull(map).containsKey(key)) {
map.put(key, 1);
} else {
map.put(key, map.get(key) + 1);
}
map.put(Objects.requireNonNull(key), map.getOrDefault(key, 0) + 1);
}
/**
......@@ -245,12 +241,7 @@ public class JavaUtils {
* @throws IllegalArgumentException if min is greater than max
*/
public static int pickBounded(int min, int max, SeededRandom rng) {
if (min > max) {
throw new IllegalArgumentException(
"Min value must be less than or equal to the max value.\nMin: " + min + "\nMax: " + max);
}
requireLessOrEqual(min, max);
return rng.nextInt(max - min + 1) + min;
}
......
......@@ -34,6 +34,7 @@ import modsched.MoovacFormulation;
import modsched.Node;
import modsched.Schedule;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
......@@ -57,6 +58,12 @@ public class SchedulingUtils {
*/
public static final long TIMELIMIT_CANDIDATE = 3600L;
/**
* The output stream which CPLEX writes its output to. If set to null, CPLEX won't print any output (see {@link
* ilog.cplex.IloCplex#setOut(OutputStream)}).
*/
public static OutputStream out = System.out;
/**
* Schedules the provided graph using the specified formulation. The solution limit specifies how many solutions
* should be computed by CPLEX before the best one will be returned.
......
......@@ -17,6 +17,7 @@
package modsched;
import graphgen.util.SchedulingUtils;
import ilog.concert.IloException;
import ilog.concert.IloIntExpr;
import ilog.concert.IloIntVar;
......@@ -57,6 +58,7 @@ public final class EichenbergerFormulation<O, R> extends IterativeFormulation<O,
List<Edge<EichenbergerNode>> E = edges;
IloCplex cp = new IloCplex();
cp.setOut(SchedulingUtils.out);
// construct some constants
IloIntExpr _0 = cp.constant(0);
......
......@@ -40,7 +40,6 @@ public abstract class IterativeFormulation<O, R, N extends Node> extends Formula
try {
for (int candII = minII, nAttempts = 0; candII <= maxII && nAttempts < attemptLimit;
++candII, ++nAttempts) {
System.out.println("Trying II: " + candII);
if (constructionTimeout) {
// if formulation signals a construction timout, all
......
......@@ -17,6 +17,7 @@
package modsched;
import graphgen.util.SchedulingUtils;
import ilog.concert.IloException;
import ilog.concert.IloIntExpr;
import ilog.concert.IloIntVar;
......@@ -41,6 +42,7 @@ public class MinII {
int recMII = -1;
try {
IloCplex cp = new IloCplex();
cp.setOut(SchedulingUtils.out);
Map<N, IloIntVar> startTimes = new LinkedHashMap<>();
for (N i : nodes) {
......
......@@ -17,6 +17,7 @@
package modsched;
import graphgen.util.SchedulingUtils;
import ilog.concert.IloException;
import ilog.concert.IloIntExpr;
import ilog.concert.IloIntVar;
......@@ -60,6 +61,7 @@ public final class MoovacFormulation<O, R> extends IterativeFormulation<O, R, Mo
long constructionBegin = System.nanoTime();
IloCplex cp = new IloCplex();
cp.setOut(SchedulingUtils.out);
// construct some constants
IloIntExpr _0 = cp.constant(0);
......
......@@ -52,8 +52,10 @@ import graphgen.util.SchedulingUtils;
import graphgen.util.TestUtils;
import modsched.Edge;
import modsched.Schedule;
import org.junit.Before;
import org.junit.Test;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
......@@ -62,6 +64,16 @@ import static org.junit.Assert.fail;
public class FeasibleMinIIPropertyTest {
@Before
public void init() {
SchedulingUtils.out = new OutputStream() {
@Override
public void write(int b) {
// Do nothing, thus getting rid of CPLEX output.
}
};
}
@Test