New updates.
This commit is contained in:
parent
5b733e25c7
commit
aab8743d3c
@ -2,6 +2,7 @@ package org.insa.algo;
|
|||||||
|
|
||||||
import org.insa.graph.Arc;
|
import org.insa.graph.Arc;
|
||||||
import org.insa.graph.Graph;
|
import org.insa.graph.Graph;
|
||||||
|
import org.insa.graph.GraphStatistics;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for algorithm input data classes. This class contains the basic
|
* Base class for algorithm input data classes. This class contains the basic
|
||||||
@ -12,77 +13,29 @@ import org.insa.graph.Graph;
|
|||||||
public abstract class AbstractInputData {
|
public abstract class AbstractInputData {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mode for computing costs on the arc (time or length).
|
* Enum specifying the top mode of the algorithms.
|
||||||
*
|
*
|
||||||
|
* @see ArcInspector
|
||||||
*/
|
*/
|
||||||
public enum Mode {
|
public enum Mode {
|
||||||
TIME, LENGTH
|
TIME, LENGTH
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Filtering interface for arcs - This class can be used to indicate to an
|
|
||||||
* algorithm which arc can be used.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface ArcFilter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given arc can be used (is allowed).
|
|
||||||
*
|
|
||||||
* @param arc Arc to check.
|
|
||||||
*
|
|
||||||
* @return true if the given arc is allowed.
|
|
||||||
*/
|
|
||||||
public boolean isAllowed(Arc arc);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Graph
|
// Graph
|
||||||
private final Graph graph;
|
private final Graph graph;
|
||||||
|
|
||||||
// Mode for the computation of the costs.
|
|
||||||
private final Mode mode;
|
|
||||||
|
|
||||||
// Arc filter.
|
// Arc filter.
|
||||||
private final ArcFilter arcFilter;
|
protected final ArcInspector arcInspector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new AbstractInputData instance for the given graph, mode and filter.
|
* Create a new AbstractInputData instance for the given graph, mode and filter.
|
||||||
*
|
*
|
||||||
* @param graph
|
* @param graph Graph for this input data.
|
||||||
* @parma mode
|
* @param arcInspector Arc inspector for this input data.
|
||||||
* @param arcFilter
|
|
||||||
*/
|
*/
|
||||||
protected AbstractInputData(Graph graph, Mode mode, ArcFilter arcFilter) {
|
protected AbstractInputData(Graph graph, ArcInspector arcInspector) {
|
||||||
this.graph = graph;
|
this.graph = graph;
|
||||||
this.mode = mode;
|
this.arcInspector = arcInspector;
|
||||||
this.arcFilter = arcFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new AbstractInputData instance for the given graph and mode, with no
|
|
||||||
* filtering on the arc.
|
|
||||||
*
|
|
||||||
* @param graph
|
|
||||||
* @param mode
|
|
||||||
*/
|
|
||||||
protected AbstractInputData(Graph graph, Mode mode) {
|
|
||||||
this(graph, mode, new AbstractInputData.ArcFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean isAllowed(Arc arc) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new AbstractInputData instance for the given graph, with default
|
|
||||||
* mode (LENGHT), with no filtering on the arc.
|
|
||||||
*
|
|
||||||
* @param graph
|
|
||||||
*/
|
|
||||||
protected AbstractInputData(Graph graph) {
|
|
||||||
this(graph, Mode.LENGTH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,12 +46,39 @@ public abstract class AbstractInputData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Mode of the algorithm (time or length).
|
* Retrieve the cost associated with the given arc according to the underlying
|
||||||
|
* arc inspector.
|
||||||
|
*
|
||||||
|
* @param arc Arc for which cost should be retrieved.
|
||||||
|
*
|
||||||
|
* @return Cost for the given arc.
|
||||||
|
*
|
||||||
|
* @see ArcInspector
|
||||||
|
*/
|
||||||
|
public double getCost(Arc arc) {
|
||||||
|
return this.arcInspector.getCost(arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Mode associated with this input data.
|
||||||
*
|
*
|
||||||
* @see Mode
|
* @see Mode
|
||||||
*/
|
*/
|
||||||
public Mode getMode() {
|
public Mode getMode() {
|
||||||
return mode;
|
return this.arcInspector.getMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the maximum speed associated with this input data, or
|
||||||
|
* {@link GraphStatistics#NO_MAXIMUM_SPEED} if none is associated. The maximum
|
||||||
|
* speed associated with input data is different from the maximum speed
|
||||||
|
* associated with graph (accessible via {@link Graph#getGraphInformation()}).
|
||||||
|
*
|
||||||
|
* @return The maximum speed for this inspector, or
|
||||||
|
* {@link GraphStatistics#NO_MAXIMUM_SPEED} if none is set.
|
||||||
|
*/
|
||||||
|
public int getMaximumSpeed() {
|
||||||
|
return this.arcInspector.getMaximumSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,10 +88,10 @@ public abstract class AbstractInputData {
|
|||||||
*
|
*
|
||||||
* @return true if the given arc is allowed.
|
* @return true if the given arc is allowed.
|
||||||
*
|
*
|
||||||
* @see ArcFilter
|
* @see ArcInspector
|
||||||
*/
|
*/
|
||||||
public boolean isAllowed(Arc arc) {
|
public boolean isAllowed(Arc arc) {
|
||||||
return this.arcFilter.isAllowed(arc);
|
return this.arcInspector.isAllowed(arc);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
package org.insa.algo;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.insa.algo.AbstractInputData.ArcFilter;
|
|
||||||
import org.insa.graph.AccessRestrictions.AccessMode;
|
|
||||||
import org.insa.graph.AccessRestrictions.AccessRestriction;
|
|
||||||
import org.insa.graph.Arc;
|
|
||||||
|
|
||||||
public class ArcFilterFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return List of all arc filters in this factory.
|
|
||||||
*/
|
|
||||||
public static List<ArcFilter> getAllFilters() {
|
|
||||||
List<ArcFilter> filters = new ArrayList<>();
|
|
||||||
|
|
||||||
// Common filters:
|
|
||||||
|
|
||||||
// 1. No filter (all arcs allowed):
|
|
||||||
filters.add(new ArcFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean isAllowed(Arc arc) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "All roads are allowed.";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2. Only road allowed for cars:
|
|
||||||
filters.add(new ArcFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean isAllowed(Arc arc) {
|
|
||||||
return arc.getRoadInformation().getAccessRestrictions()
|
|
||||||
.isAllowedForAny(AccessMode.MOTORCAR, EnumSet.complementOf(EnumSet
|
|
||||||
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Only roads open for cars.";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3. Non-private roads for pedestrian and bicycle:
|
|
||||||
filters.add(new ArcFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean isAllowed(Arc arc) {
|
|
||||||
return arc.getRoadInformation().getAccessRestrictions()
|
|
||||||
.isAllowedForAny(AccessMode.FOOT, EnumSet.complementOf(EnumSet
|
|
||||||
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Non-private roads for pedestrian.";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3. Add your own filters here (do not forget to implement toString() to get an
|
|
||||||
// understandable output!):
|
|
||||||
|
|
||||||
return filters;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
43
src/main/org/insa/algo/ArcInspector.java
Normal file
43
src/main/org/insa/algo/ArcInspector.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package org.insa.algo;
|
||||||
|
|
||||||
|
import org.insa.algo.AbstractInputData.Mode;
|
||||||
|
import org.insa.graph.Arc;
|
||||||
|
import org.insa.graph.GraphStatistics;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class can be used to indicate to an algorithm which arcs can be used and
|
||||||
|
* the costs of the usable arcs..
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface ArcInspector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given arc can be used (is allowed).
|
||||||
|
*
|
||||||
|
* @param arc Arc to check.
|
||||||
|
*
|
||||||
|
* @return true if the given arc is allowed.
|
||||||
|
*/
|
||||||
|
public boolean isAllowed(Arc arc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the cost of the given arc.
|
||||||
|
*
|
||||||
|
* @param arc Arc for which the cost should be returned.
|
||||||
|
*
|
||||||
|
* @return Cost of the arc.
|
||||||
|
*/
|
||||||
|
public double getCost(Arc arc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The maximum speed for this inspector, or
|
||||||
|
* {@link GraphStatistics#NO_MAXIMUM_SPEED} if none is set.
|
||||||
|
*/
|
||||||
|
public int getMaximumSpeed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Mode for this arc inspector.
|
||||||
|
*/
|
||||||
|
public Mode getMode();
|
||||||
|
|
||||||
|
}
|
149
src/main/org/insa/algo/ArcInspectorFactory.java
Normal file
149
src/main/org/insa/algo/ArcInspectorFactory.java
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package org.insa.algo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.insa.algo.AbstractInputData.Mode;
|
||||||
|
import org.insa.graph.AccessRestrictions.AccessMode;
|
||||||
|
import org.insa.graph.AccessRestrictions.AccessRestriction;
|
||||||
|
import org.insa.graph.Arc;
|
||||||
|
import org.insa.graph.GraphStatistics;
|
||||||
|
|
||||||
|
public class ArcInspectorFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return List of all arc filters in this factory.
|
||||||
|
*/
|
||||||
|
public static List<ArcInspector> getAllFilters() {
|
||||||
|
List<ArcInspector> filters = new ArrayList<>();
|
||||||
|
|
||||||
|
// Common filters:
|
||||||
|
|
||||||
|
// No filter (all arcs allowed):
|
||||||
|
filters.add(new ArcInspector() {
|
||||||
|
@Override
|
||||||
|
public boolean isAllowed(Arc arc) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCost(Arc arc) {
|
||||||
|
return arc.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaximumSpeed() {
|
||||||
|
return GraphStatistics.NO_MAXIMUM_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mode getMode() {
|
||||||
|
return Mode.LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Shortest path, all roads allowed";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only road allowed for cars and length:
|
||||||
|
filters.add(new ArcInspector() {
|
||||||
|
@Override
|
||||||
|
public boolean isAllowed(Arc arc) {
|
||||||
|
return arc.getRoadInformation().getAccessRestrictions()
|
||||||
|
.isAllowedForAny(AccessMode.MOTORCAR, EnumSet.complementOf(EnumSet
|
||||||
|
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCost(Arc arc) {
|
||||||
|
return arc.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaximumSpeed() {
|
||||||
|
return GraphStatistics.NO_MAXIMUM_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mode getMode() {
|
||||||
|
return Mode.LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Shortest path, only roads open for cars";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only road allowed for cars and time:
|
||||||
|
filters.add(new ArcInspector() {
|
||||||
|
@Override
|
||||||
|
public boolean isAllowed(Arc arc) {
|
||||||
|
return arc.getRoadInformation().getAccessRestrictions()
|
||||||
|
.isAllowedForAny(AccessMode.MOTORCAR, EnumSet.complementOf(EnumSet
|
||||||
|
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCost(Arc arc) {
|
||||||
|
return arc.getMinimumTravelTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaximumSpeed() {
|
||||||
|
return GraphStatistics.NO_MAXIMUM_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mode getMode() {
|
||||||
|
return Mode.TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Fastest path, only roads open for cars";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Non-private roads for pedestrian and bicycle:
|
||||||
|
filters.add(new ArcInspector() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowed(Arc arc) {
|
||||||
|
return arc.getRoadInformation().getAccessRestrictions()
|
||||||
|
.isAllowedForAny(AccessMode.FOOT, EnumSet.complementOf(EnumSet
|
||||||
|
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCost(Arc arc) {
|
||||||
|
return arc.getTravelTime(
|
||||||
|
Math.min(getMaximumSpeed(), arc.getRoadInformation().getMaximumSpeed()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Fastest path for pedestrian";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaximumSpeed() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mode getMode() {
|
||||||
|
return Mode.TIME;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add your own filters here (do not forget to implement toString()
|
||||||
|
// to get an understandable output!):
|
||||||
|
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
package org.insa.algo.carpooling;
|
package org.insa.algo.carpooling;
|
||||||
|
|
||||||
import org.insa.algo.AbstractInputData;
|
import org.insa.algo.AbstractInputData;
|
||||||
|
import org.insa.algo.ArcInspector;
|
||||||
import org.insa.graph.Graph;
|
import org.insa.graph.Graph;
|
||||||
|
|
||||||
public class CarPoolingData extends AbstractInputData {
|
public class CarPoolingData extends AbstractInputData {
|
||||||
|
|
||||||
protected CarPoolingData(Graph graph, Mode mode, ArcFilter arcFilter) {
|
protected CarPoolingData(Graph graph, ArcInspector arcFilter) {
|
||||||
super(graph, mode, arcFilter);
|
super(graph, arcFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package org.insa.algo.packageswitch;
|
package org.insa.algo.packageswitch;
|
||||||
|
|
||||||
import org.insa.algo.AbstractInputData;
|
import org.insa.algo.AbstractInputData;
|
||||||
|
import org.insa.algo.ArcInspector;
|
||||||
import org.insa.graph.Graph;
|
import org.insa.graph.Graph;
|
||||||
|
|
||||||
public class PackageSwitchData extends AbstractInputData {
|
public class PackageSwitchData extends AbstractInputData {
|
||||||
|
|
||||||
protected PackageSwitchData(Graph graph, Mode mode, ArcFilter arcFilter) {
|
protected PackageSwitchData(Graph graph, ArcInspector arcFilter) {
|
||||||
super(graph, mode, arcFilter);
|
super(graph, arcFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.insa.algo.AbstractInputData;
|
|
||||||
import org.insa.algo.AbstractSolution.Status;
|
import org.insa.algo.AbstractSolution.Status;
|
||||||
import org.insa.graph.Arc;
|
import org.insa.graph.Arc;
|
||||||
import org.insa.graph.Graph;
|
import org.insa.graph.Graph;
|
||||||
@ -37,7 +36,8 @@ public class BellmanFordAlgorithm extends ShortestPathAlgorithm {
|
|||||||
// Initialize array of predecessors.
|
// Initialize array of predecessors.
|
||||||
Arc[] predecessorArcs = new Arc[nbNodes];
|
Arc[] predecessorArcs = new Arc[nbNodes];
|
||||||
|
|
||||||
// Actual algorithm, we will assume the graph does not contain negative cycle...
|
// Actual algorithm, we will assume the graph does not contain negative
|
||||||
|
// cycle...
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (int i = 0; !found && i < nbNodes; ++i) {
|
for (int i = 0; !found && i < nbNodes; ++i) {
|
||||||
found = true;
|
found = true;
|
||||||
@ -50,9 +50,7 @@ public class BellmanFordAlgorithm extends ShortestPathAlgorithm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve weight of the arc.
|
// Retrieve weight of the arc.
|
||||||
double w = data.getMode() == AbstractInputData.Mode.LENGTH ? arc.getLength()
|
double w = data.getCost(arc);
|
||||||
: arc.getMinimumTravelTime();
|
|
||||||
|
|
||||||
double oldDistance = distances[arc.getDestination().getId()];
|
double oldDistance = distances[arc.getDestination().getId()];
|
||||||
double newDistance = distances[node.getId()] + w;
|
double newDistance = distances[node.getId()] + w;
|
||||||
|
|
||||||
@ -75,8 +73,7 @@ public class BellmanFordAlgorithm extends ShortestPathAlgorithm {
|
|||||||
// Destination has no predecessor, the solution is infeasible...
|
// Destination has no predecessor, the solution is infeasible...
|
||||||
if (predecessorArcs[data.getDestination().getId()] == null) {
|
if (predecessorArcs[data.getDestination().getId()] == null) {
|
||||||
solution = new ShortestPathSolution(data, Status.INFEASIBLE);
|
solution = new ShortestPathSolution(data, Status.INFEASIBLE);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
|
|
||||||
// The destination has been found, notify the observers.
|
// The destination has been found, notify the observers.
|
||||||
notifyDestinationReached(data.getDestination());
|
notifyDestinationReached(data.getDestination());
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.insa.algo.shortestpath;
|
package org.insa.algo.shortestpath;
|
||||||
|
|
||||||
import org.insa.algo.AbstractInputData;
|
import org.insa.algo.AbstractInputData;
|
||||||
|
import org.insa.algo.ArcInspector;
|
||||||
import org.insa.graph.Graph;
|
import org.insa.graph.Graph;
|
||||||
import org.insa.graph.Node;
|
import org.insa.graph.Node;
|
||||||
|
|
||||||
@ -9,34 +10,17 @@ public class ShortestPathData extends AbstractInputData {
|
|||||||
// Origin and destination nodes.
|
// Origin and destination nodes.
|
||||||
private final Node origin, destination;
|
private final Node origin, destination;
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new instance of ShortestPathData with the given parameters and
|
|
||||||
* for which all arcs are allowed.
|
|
||||||
*
|
|
||||||
* @param graph Graph in which the path should be looked for.
|
|
||||||
* @param origin Origin node of the path.
|
|
||||||
* @param destination Destination node of the path.
|
|
||||||
* @param mode Cost mode for the path.
|
|
||||||
*/
|
|
||||||
public ShortestPathData(Graph graph, Node origin, Node destination, Mode mode) {
|
|
||||||
super(graph, mode);
|
|
||||||
this.origin = origin;
|
|
||||||
this.destination = destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new instance of ShortestPathInputData with the given parameters.
|
* Construct a new instance of ShortestPathInputData with the given parameters.
|
||||||
*
|
*
|
||||||
* @param graph Graph in which the path should be looked for.
|
* @param graph Graph in which the path should be looked for.
|
||||||
* @param origin Origin node of the path.
|
* @param origin Origin node of the path.
|
||||||
* @param destination Destination node of the path.
|
* @param destination Destination node of the path.
|
||||||
* @param mode Cost mode for the path.
|
* @param arcInspector Filter for arcs (used to allow only a specific set of
|
||||||
* @param arcFilter Filter for arcs (used to allow only a specific set of arcs
|
* arcs in the graph to be used).
|
||||||
* in the graph to be used).
|
|
||||||
*/
|
*/
|
||||||
public ShortestPathData(Graph graph, Node origin, Node destination, Mode mode,
|
public ShortestPathData(Graph graph, Node origin, Node destination, ArcInspector arcInspector) {
|
||||||
AbstractInputData.ArcFilter arcFilter) {
|
super(graph, arcInspector);
|
||||||
super(graph, mode, arcFilter);
|
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
}
|
}
|
||||||
@ -58,6 +42,6 @@ public class ShortestPathData extends AbstractInputData {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Shortest-path from #" + origin.getId() + " to #" + destination.getId() + " ["
|
return "Shortest-path from #" + origin.getId() + " to #" + destination.getId() + " ["
|
||||||
+ getMode().toString().toLowerCase() + "]";
|
+ this.arcInspector.toString().toLowerCase() + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package org.insa.algo.shortestpath;
|
package org.insa.algo.shortestpath;
|
||||||
|
|
||||||
import org.insa.algo.AbstractInputData;
|
import org.insa.algo.AbstractInputData.Mode;
|
||||||
import org.insa.algo.AbstractSolution;
|
import org.insa.algo.AbstractSolution;
|
||||||
|
import org.insa.graph.Arc;
|
||||||
import org.insa.graph.Path;
|
import org.insa.graph.Path;
|
||||||
|
|
||||||
public class ShortestPathSolution extends AbstractSolution {
|
public class ShortestPathSolution extends AbstractSolution {
|
||||||
@ -59,14 +60,17 @@ public class ShortestPathSolution extends AbstractSolution {
|
|||||||
getInputData().getOrigin().getId(), getInputData().getDestination().getId());
|
getInputData().getOrigin().getId(), getInputData().getDestination().getId());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
double cost = 0;
|
||||||
|
for (Arc arc: getPath().getArcs()) {
|
||||||
|
cost += getInputData().getCost(arc);
|
||||||
|
}
|
||||||
info = String.format("Found a path from node #%d to node #%d",
|
info = String.format("Found a path from node #%d to node #%d",
|
||||||
getInputData().getOrigin().getId(), getInputData().getDestination().getId());
|
getInputData().getOrigin().getId(), getInputData().getDestination().getId());
|
||||||
if (getInputData().getMode() == AbstractInputData.Mode.LENGTH) {
|
if (getInputData().getMode() == Mode.LENGTH) {
|
||||||
info = String.format("%s, %.4f kilometers", info, (getPath().getLength() / 1000.0));
|
info = String.format("%s, %.4f kilometers", info, cost / 1000.0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
info = String.format("%s, %.4f minutes", info,
|
info = String.format("%s, %.4f minutes", info, cost / 60.0);
|
||||||
(getPath().getMinimumTravelTime() / 60.0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info += " in " + getSolvingTime().getSeconds() + " seconds.";
|
info += " in " + getSolvingTime().getSeconds() + " seconds.";
|
||||||
|
@ -18,14 +18,13 @@ import java.util.ArrayList;
|
|||||||
* @author Mark Allen Weiss
|
* @author Mark Allen Weiss
|
||||||
* @author DLB
|
* @author DLB
|
||||||
*/
|
*/
|
||||||
public class BinaryHeap<E extends Comparable<E>> {
|
public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
|
||||||
|
|
||||||
// Number of elements in heap.
|
// Number of elements in heap.
|
||||||
private int currentSize;
|
private int currentSize;
|
||||||
|
|
||||||
// The heap array. Java genericity does not work with arrays so we have to use
|
// The heap array.
|
||||||
// an ArrayList.
|
private final ArrayList<E> array;
|
||||||
private ArrayList<E> array;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new empty binary heap.
|
* Construct a new empty binary heap.
|
||||||
@ -126,62 +125,37 @@ public class BinaryHeap<E extends Comparable<E>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @return true if the heap is empty, false otherwise.
|
|
||||||
*/
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return this.currentSize == 0;
|
return this.currentSize == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @return Current size (number of elements) of this heap.
|
|
||||||
*/
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return this.currentSize;
|
return this.currentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Insert the given element into the heap.
|
public void insert(E x) {
|
||||||
*
|
|
||||||
* @param x Item to insert.
|
|
||||||
*/
|
|
||||||
public void add(E x) {
|
|
||||||
int index = this.currentSize++;
|
int index = this.currentSize++;
|
||||||
this.arraySet(index, x);
|
this.arraySet(index, x);
|
||||||
this.percolateUp(index);
|
this.percolateUp(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Tell the binary heap that the given element has been modified and should be
|
public void remove(E x) throws ElementNotFoundException {
|
||||||
* re-positioned inside the heap.
|
|
||||||
*
|
|
||||||
* @param x Item to update.
|
|
||||||
*/
|
|
||||||
public void update(E x) {
|
|
||||||
// TODO:
|
// TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Find the smallest item in the heap.
|
public E findMin() throws EmptyPriorityQueueException {
|
||||||
*
|
|
||||||
* @return The smallest item in the heap.
|
|
||||||
*
|
|
||||||
* @throws RuntimeException if this heap is empty.
|
|
||||||
*/
|
|
||||||
public E findMin() throws RuntimeException {
|
|
||||||
if (isEmpty())
|
if (isEmpty())
|
||||||
throw new RuntimeException("Empty binary heap.");
|
throw new RuntimeException("Empty binary heap.");
|
||||||
return this.array.get(0);
|
return this.array.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Remove the smallest item from the heap.
|
public E deleteMin() throws EmptyPriorityQueueException {
|
||||||
*
|
|
||||||
* @return The smallest item in the heap.
|
|
||||||
*
|
|
||||||
* @throws RuntimeException if this heap is empty.
|
|
||||||
*/
|
|
||||||
public E deleteMin() throws RuntimeException {
|
|
||||||
E minItem = findMin();
|
E minItem = findMin();
|
||||||
E lastItem = this.array.get(--this.currentSize);
|
E lastItem = this.array.get(--this.currentSize);
|
||||||
this.arraySet(0, lastItem);
|
this.arraySet(0, lastItem);
|
||||||
|
64
src/main/org/insa/algo/utils/BinarySearchTree.java
Normal file
64
src/main/org/insa/algo/utils/BinarySearchTree.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package org.insa.algo.utils;
|
||||||
|
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
public class BinarySearchTree<E extends Comparable<E>> implements PriorityQueue<E> {
|
||||||
|
|
||||||
|
// Underlying implementation
|
||||||
|
private final SortedSet<E> sortedSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new empty binary search tree.
|
||||||
|
*/
|
||||||
|
public BinarySearchTree() {
|
||||||
|
this.sortedSet = new TreeSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a copy of the given binary search tree.
|
||||||
|
*
|
||||||
|
* @param bst Binary search tree to copy.
|
||||||
|
*/
|
||||||
|
public BinarySearchTree(BinarySearchTree<E> bst) {
|
||||||
|
this.sortedSet = new TreeSet<>(bst.sortedSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return sortedSet.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return sortedSet.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insert(E x) {
|
||||||
|
sortedSet.add(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(E x) throws ElementNotFoundException {
|
||||||
|
if (!sortedSet.remove(x)) {
|
||||||
|
throw new ElementNotFoundException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E findMin() throws EmptyPriorityQueueException {
|
||||||
|
if (isEmpty()) {
|
||||||
|
throw new EmptyPriorityQueueException();
|
||||||
|
}
|
||||||
|
return sortedSet.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E deleteMin() throws EmptyPriorityQueueException {
|
||||||
|
E min = findMin();
|
||||||
|
remove(min);
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
src/main/org/insa/algo/utils/ElementNotFoundException.java
Normal file
32
src/main/org/insa/algo/utils/ElementNotFoundException.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package org.insa.algo.utils;
|
||||||
|
|
||||||
|
public class ElementNotFoundException extends RuntimeException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
// Element not found
|
||||||
|
private final Object element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param element Element that was not found.
|
||||||
|
*/
|
||||||
|
public ElementNotFoundException(Object element) {
|
||||||
|
this.element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The element that was not found.
|
||||||
|
*/
|
||||||
|
public Object getElement() {
|
||||||
|
return this.element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "element not found: " + element;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.insa.algo.utils;
|
||||||
|
|
||||||
|
public class EmptyPriorityQueueException extends RuntimeException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public EmptyPriorityQueueException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
54
src/main/org/insa/algo/utils/PriorityQueue.java
Normal file
54
src/main/org/insa/algo/utils/PriorityQueue.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package org.insa.algo.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface representing a basic priority queue.
|
||||||
|
*
|
||||||
|
* @see https://en.wikipedia.org/wiki/Priority_queue
|
||||||
|
*/
|
||||||
|
public interface PriorityQueue<E extends Comparable<E>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the priority queue is empty.
|
||||||
|
*
|
||||||
|
* @return true if the queue is empty, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isEmpty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Current size (number of elements) of this queue.
|
||||||
|
*/
|
||||||
|
public int size();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert the given element into the queue.
|
||||||
|
*
|
||||||
|
* @param x Item to insert.
|
||||||
|
*/
|
||||||
|
public void insert(E x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the given element from the priority queue.
|
||||||
|
*
|
||||||
|
* @param x Item to remove.
|
||||||
|
*/
|
||||||
|
public void remove(E x) throws ElementNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve (but not remove) the smallest item in the queue.
|
||||||
|
*
|
||||||
|
* @return The smallest item in the queue.
|
||||||
|
*
|
||||||
|
* @throws EmptyPriorityQueueException if this queue is empty.
|
||||||
|
*/
|
||||||
|
public E findMin() throws EmptyPriorityQueueException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove and return the smallest item from the priority queue.
|
||||||
|
*
|
||||||
|
* @return The smallest item in the queue.
|
||||||
|
*
|
||||||
|
* @throws EmptyPriorityQueueException if this queue is empty.
|
||||||
|
*/
|
||||||
|
public E deleteMin() throws EmptyPriorityQueueException;
|
||||||
|
|
||||||
|
}
|
@ -9,7 +9,7 @@ public class WeaklyConnectedComponentsData extends AbstractInputData {
|
|||||||
* @param graph Graph for which components should be retrieved.
|
* @param graph Graph for which components should be retrieved.
|
||||||
*/
|
*/
|
||||||
public WeaklyConnectedComponentsData(Graph graph) {
|
public WeaklyConnectedComponentsData(Graph graph) {
|
||||||
super(graph);
|
super(graph, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -23,6 +23,8 @@ public class Launch {
|
|||||||
* Create a new Drawing inside a JFrame an return it.
|
* Create a new Drawing inside a JFrame an return it.
|
||||||
*
|
*
|
||||||
* @return The created drawing.
|
* @return The created drawing.
|
||||||
|
*
|
||||||
|
* @throws Exception if something wrong happens when creating the graph.
|
||||||
*/
|
*/
|
||||||
public static Drawing createDrawing() throws Exception {
|
public static Drawing createDrawing() throws Exception {
|
||||||
BasicDrawing basicDrawing = new BasicDrawing();
|
BasicDrawing basicDrawing = new BasicDrawing();
|
||||||
|
@ -94,6 +94,8 @@ public class GraphStatistics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param other Box to intersect.
|
||||||
|
*
|
||||||
* @return true if this box contains the given box.
|
* @return true if this box contains the given box.
|
||||||
*/
|
*/
|
||||||
public boolean contains(BoundingBox other) {
|
public boolean contains(BoundingBox other) {
|
||||||
|
@ -14,22 +14,18 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.swing.Box;
|
import javax.swing.Box;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.ButtonGroup;
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JRadioButton;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
import org.insa.algo.AbstractAlgorithm;
|
import org.insa.algo.AbstractAlgorithm;
|
||||||
import org.insa.algo.AbstractInputData;
|
|
||||||
import org.insa.algo.AbstractInputData.ArcFilter;
|
|
||||||
import org.insa.algo.AbstractInputData.Mode;
|
|
||||||
import org.insa.algo.AlgorithmFactory;
|
import org.insa.algo.AlgorithmFactory;
|
||||||
import org.insa.algo.ArcFilterFactory;
|
import org.insa.algo.ArcInspector;
|
||||||
|
import org.insa.algo.ArcInspectorFactory;
|
||||||
import org.insa.graph.Node;
|
import org.insa.graph.Node;
|
||||||
import org.insa.graphics.NodesInputPanel.InputChangedEvent;
|
import org.insa.graphics.NodesInputPanel.InputChangedEvent;
|
||||||
import org.insa.graphics.drawing.Drawing;
|
import org.insa.graphics.drawing.Drawing;
|
||||||
@ -55,20 +51,18 @@ public class AlgorithmPanel extends JPanel implements DrawingChangeListener {
|
|||||||
protected static final int START_EVENT_ID = 0x1;
|
protected static final int START_EVENT_ID = 0x1;
|
||||||
|
|
||||||
private final List<Node> nodes;
|
private final List<Node> nodes;
|
||||||
private final AbstractInputData.Mode mode;
|
|
||||||
private final Class<? extends AbstractAlgorithm<?>> algoClass;
|
private final Class<? extends AbstractAlgorithm<?>> algoClass;
|
||||||
|
|
||||||
private final AbstractInputData.ArcFilter arcFilter;
|
private final ArcInspector arcFilter;
|
||||||
|
|
||||||
private final boolean graphicVisualization;
|
private final boolean graphicVisualization;
|
||||||
private final boolean textualVisualization;
|
private final boolean textualVisualization;
|
||||||
|
|
||||||
public StartActionEvent(Class<? extends AbstractAlgorithm<?>> algoClass, List<Node> nodes,
|
public StartActionEvent(Class<? extends AbstractAlgorithm<?>> algoClass, List<Node> nodes,
|
||||||
Mode mode, ArcFilter arcFilter, boolean graphicVisualization,
|
ArcInspector arcFilter, boolean graphicVisualization,
|
||||||
boolean textualVisualization) {
|
boolean textualVisualization) {
|
||||||
super(AlgorithmPanel.this, START_EVENT_ID, START_EVENT_COMMAND);
|
super(AlgorithmPanel.this, START_EVENT_ID, START_EVENT_COMMAND);
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
this.mode = mode;
|
|
||||||
this.algoClass = algoClass;
|
this.algoClass = algoClass;
|
||||||
this.graphicVisualization = graphicVisualization;
|
this.graphicVisualization = graphicVisualization;
|
||||||
this.textualVisualization = textualVisualization;
|
this.textualVisualization = textualVisualization;
|
||||||
@ -82,17 +76,10 @@ public class AlgorithmPanel extends JPanel implements DrawingChangeListener {
|
|||||||
return this.nodes;
|
return this.nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Mode associated with this event.
|
|
||||||
*/
|
|
||||||
public Mode getMode() {
|
|
||||||
return this.mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Arc filter associated with this event.
|
* @return Arc filter associated with this event.
|
||||||
*/
|
*/
|
||||||
public ArcFilter getArcFilter() {
|
public ArcInspector getArcFilter() {
|
||||||
return this.arcFilter;
|
return this.arcFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,16 +134,13 @@ public class AlgorithmPanel extends JPanel implements DrawingChangeListener {
|
|||||||
* @param baseAlgorithm Base algorithm for this algorithm panel.
|
* @param baseAlgorithm Base algorithm for this algorithm panel.
|
||||||
* @param title Title of the panel.
|
* @param title Title of the panel.
|
||||||
* @param nodeNames Names of the input nodes.
|
* @param nodeNames Names of the input nodes.
|
||||||
* @param enableModeSelection <code>true</code> to enable {@link Mode}
|
* @param enableArcFilterSelection <code>true</code> to enable
|
||||||
* selection.
|
* {@link ArcInspector} selection.
|
||||||
* @param enableArcFilterSelection <code>true</code> to enable {@link ArcFilter}
|
|
||||||
* selection.
|
|
||||||
*
|
*
|
||||||
* @see ArcFilterFactory
|
* @see ArcInspectorFactory
|
||||||
*/
|
*/
|
||||||
public AlgorithmPanel(Component parent, Class<? extends AbstractAlgorithm<?>> baseAlgorithm,
|
public AlgorithmPanel(Component parent, Class<? extends AbstractAlgorithm<?>> baseAlgorithm,
|
||||||
String title, String[] nodeNames, boolean enableModeSelection,
|
String title, String[] nodeNames, boolean enableArcFilterSelection) {
|
||||||
boolean enableArcFilterSelection) {
|
|
||||||
super();
|
super();
|
||||||
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
|
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
|
||||||
|
|
||||||
@ -178,20 +162,14 @@ public class AlgorithmPanel extends JPanel implements DrawingChangeListener {
|
|||||||
add(this.nodesInputPanel);
|
add(this.nodesInputPanel);
|
||||||
components.add(this.nodesInputPanel);
|
components.add(this.nodesInputPanel);
|
||||||
|
|
||||||
JComboBox<ArcFilter> arcFilterSelect = new JComboBox<>(
|
JComboBox<ArcInspector> arcFilterSelect = new JComboBox<>(
|
||||||
ArcFilterFactory.getAllFilters().toArray(new ArcFilter[0]));
|
ArcInspectorFactory.getAllFilters().toArray(new ArcInspector[0]));
|
||||||
arcFilterSelect.setBackground(Color.WHITE);
|
arcFilterSelect.setBackground(Color.WHITE);
|
||||||
|
|
||||||
// Add mode selection
|
// Add mode selection
|
||||||
JPanel modeAndObserverPanel = new JPanel();
|
JPanel modeAndObserverPanel = new JPanel();
|
||||||
modeAndObserverPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
modeAndObserverPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
modeAndObserverPanel.setLayout(new GridBagLayout());
|
modeAndObserverPanel.setLayout(new GridBagLayout());
|
||||||
JRadioButton lengthModeButton = new JRadioButton("Length");
|
|
||||||
lengthModeButton.setSelected(true);
|
|
||||||
JRadioButton timeModeButton = new JRadioButton("Time");
|
|
||||||
ButtonGroup group = new ButtonGroup();
|
|
||||||
group.add(lengthModeButton);
|
|
||||||
group.add(timeModeButton);
|
|
||||||
|
|
||||||
graphicObserverCheckbox = new JCheckBox("Graphic");
|
graphicObserverCheckbox = new JCheckBox("Graphic");
|
||||||
graphicObserverCheckbox.setSelected(true);
|
graphicObserverCheckbox.setSelected(true);
|
||||||
@ -201,19 +179,6 @@ public class AlgorithmPanel extends JPanel implements DrawingChangeListener {
|
|||||||
|
|
||||||
c.fill = GridBagConstraints.HORIZONTAL;
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
|
||||||
if (enableModeSelection) {
|
|
||||||
c.gridx = 0;
|
|
||||||
c.gridy = 0;
|
|
||||||
c.weightx = 0;
|
|
||||||
modeAndObserverPanel.add(new JLabel("Mode: "), c);
|
|
||||||
c.gridx = 1;
|
|
||||||
c.weightx = 1;
|
|
||||||
modeAndObserverPanel.add(lengthModeButton, c);
|
|
||||||
c.gridx = 2;
|
|
||||||
c.weightx = 1;
|
|
||||||
modeAndObserverPanel.add(timeModeButton, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
c.gridy = 2;
|
c.gridy = 2;
|
||||||
c.gridx = 0;
|
c.gridx = 0;
|
||||||
c.weightx = 0;
|
c.weightx = 0;
|
||||||
@ -236,8 +201,6 @@ public class AlgorithmPanel extends JPanel implements DrawingChangeListener {
|
|||||||
modeAndObserverPanel.add(arcFilterSelect, c);
|
modeAndObserverPanel.add(arcFilterSelect, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
components.add(timeModeButton);
|
|
||||||
components.add(lengthModeButton);
|
|
||||||
components.add(arcFilterSelect);
|
components.add(arcFilterSelect);
|
||||||
components.add(textualObserverCheckbox);
|
components.add(textualObserverCheckbox);
|
||||||
|
|
||||||
@ -258,16 +221,12 @@ public class AlgorithmPanel extends JPanel implements DrawingChangeListener {
|
|||||||
startAlgoButton.addActionListener(new ActionListener() {
|
startAlgoButton.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
AbstractInputData.Mode mode = lengthModeButton.isSelected()
|
|
||||||
? AbstractInputData.Mode.LENGTH
|
|
||||||
: AbstractInputData.Mode.TIME;
|
|
||||||
|
|
||||||
for (ActionListener lis: startActionListeners) {
|
for (ActionListener lis: startActionListeners) {
|
||||||
lis.actionPerformed(new StartActionEvent(
|
lis.actionPerformed(new StartActionEvent(
|
||||||
AlgorithmFactory.getAlgorithmClass(baseAlgorithm,
|
AlgorithmFactory.getAlgorithmClass(baseAlgorithm,
|
||||||
(String) algoSelect.getSelectedItem()),
|
(String) algoSelect.getSelectedItem()),
|
||||||
nodesInputPanel.getNodeForInputs(), mode,
|
nodesInputPanel.getNodeForInputs(),
|
||||||
(AbstractInputData.ArcFilter) arcFilterSelect.getSelectedItem(),
|
(ArcInspector) arcFilterSelect.getSelectedItem(),
|
||||||
graphicObserverCheckbox.isSelected(),
|
graphicObserverCheckbox.isSelected(),
|
||||||
textualObserverCheckbox.isSelected()));
|
textualObserverCheckbox.isSelected()));
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ public class MainWindow extends JFrame {
|
|||||||
this.currentPalette = this.basicPalette;
|
this.currentPalette = this.basicPalette;
|
||||||
|
|
||||||
wccPanel = new AlgorithmPanel(this, WeaklyConnectedComponentsAlgorithm.class,
|
wccPanel = new AlgorithmPanel(this, WeaklyConnectedComponentsAlgorithm.class,
|
||||||
"Weakly-Connected Components", new String[] {}, false, false);
|
"Weakly-Connected Components", new String[] {}, false);
|
||||||
wccPanel.addStartActionListener(new ActionListener() {
|
wccPanel.addStartActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
@ -202,13 +202,13 @@ public class MainWindow extends JFrame {
|
|||||||
});
|
});
|
||||||
|
|
||||||
spPanel = new AlgorithmPanel(this, ShortestPathAlgorithm.class, "Shortest-Path",
|
spPanel = new AlgorithmPanel(this, ShortestPathAlgorithm.class, "Shortest-Path",
|
||||||
new String[] { "Origin", "Destination" }, true, true);
|
new String[] { "Origin", "Destination" }, true);
|
||||||
spPanel.addStartActionListener(new ActionListener() {
|
spPanel.addStartActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
StartActionEvent evt = (StartActionEvent) e;
|
StartActionEvent evt = (StartActionEvent) e;
|
||||||
ShortestPathData data = new ShortestPathData(graph, evt.getNodes().get(0),
|
ShortestPathData data = new ShortestPathData(graph, evt.getNodes().get(0),
|
||||||
evt.getNodes().get(1), evt.getMode(), evt.getArcFilter());
|
evt.getNodes().get(1), evt.getArcFilter());
|
||||||
|
|
||||||
ShortestPathAlgorithm spAlgorithm = null;
|
ShortestPathAlgorithm spAlgorithm = null;
|
||||||
try {
|
try {
|
||||||
@ -257,11 +257,10 @@ public class MainWindow extends JFrame {
|
|||||||
cpPanel = new AlgorithmPanel(
|
cpPanel = new AlgorithmPanel(
|
||||||
this, CarPoolingAlgorithm.class, "Car-Pooling", new String[] { "Origin Car",
|
this, CarPoolingAlgorithm.class, "Car-Pooling", new String[] { "Origin Car",
|
||||||
"Origin Pedestrian", "Destination Car", "Destination Pedestrian" },
|
"Origin Pedestrian", "Destination Car", "Destination Pedestrian" },
|
||||||
true, true);
|
true);
|
||||||
|
|
||||||
psPanel = new AlgorithmPanel(this, PackageSwitchAlgorithm.class, "Car-Pooling",
|
psPanel = new AlgorithmPanel(this, PackageSwitchAlgorithm.class, "Car-Pooling",
|
||||||
new String[] { "Oribin A", "Origin B", "Destination A", "Destination B" }, true,
|
new String[] { "Oribin A", "Origin B", "Destination A", "Destination B" }, true);
|
||||||
true);
|
|
||||||
|
|
||||||
// add algorithm panels
|
// add algorithm panels
|
||||||
algoPanels.add(wccPanel);
|
algoPanels.add(wccPanel);
|
||||||
|
@ -15,7 +15,6 @@ import java.awt.geom.Point2D;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -65,6 +64,11 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
this.color = color;
|
this.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The Z level of this overlay (>= 1).
|
||||||
|
*/
|
||||||
|
public abstract int getZLevel();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setColor(Color color) {
|
public void setColor(Color color) {
|
||||||
this.color = color;
|
this.color = color;
|
||||||
@ -88,11 +92,8 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete() {
|
public void delete() {
|
||||||
synchronized (overlays) {
|
|
||||||
BasicDrawing.this.overlays.remove(this);
|
BasicDrawing.this.overlays.remove(this);
|
||||||
}
|
}
|
||||||
BasicDrawing.this.repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw the given overlay.
|
* Draw the given overlay.
|
||||||
@ -134,6 +135,10 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
this.alphaMode = alphaMode;
|
this.alphaMode = alphaMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getZLevel() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Point getPoint() {
|
public Point getPoint() {
|
||||||
return point;
|
return point;
|
||||||
@ -181,6 +186,10 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
this.color = color;
|
this.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getZLevel() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setColor(Color color) {
|
public void setColor(Color color) {
|
||||||
super.setColor(color);
|
super.setColor(color);
|
||||||
@ -243,6 +252,10 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
this.graphics.setBackground(new Color(0, 0, 0, 0));
|
this.graphics.setBackground(new Color(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getZLevel() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setColor(Color color) {
|
public void setColor(Color color) {
|
||||||
super.setColor(color);
|
super.setColor(color);
|
||||||
@ -294,6 +307,68 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class encapsulating a set of overlays.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private class BasicOverlays {
|
||||||
|
|
||||||
|
// List of overlays.
|
||||||
|
private ArrayList<ArrayList<BasicOverlay>> overlays = new ArrayList<>();
|
||||||
|
|
||||||
|
public synchronized void draw(Graphics2D g) {
|
||||||
|
// Clear overlays.
|
||||||
|
for (ArrayList<BasicOverlay> arr: this.overlays) {
|
||||||
|
for (BasicOverlay overlay: arr) {
|
||||||
|
overlay.draw(g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void remove(BasicOverlay overlay) {
|
||||||
|
overlays.get(overlay.getZLevel() - 1).remove(overlay);
|
||||||
|
BasicDrawing.this.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
clear(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear(boolean repaint) {
|
||||||
|
// Clear overlays.
|
||||||
|
for (ArrayList<BasicOverlay> arr: this.overlays) {
|
||||||
|
arr.clear();
|
||||||
|
}
|
||||||
|
// Repaint if requested.
|
||||||
|
if (repaint) {
|
||||||
|
BasicDrawing.this.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BasicOverlay add(BasicOverlay marker) {
|
||||||
|
return add(marker, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized BasicOverlay add(BasicOverlay overlay, boolean repaint) {
|
||||||
|
|
||||||
|
// Check if we have a level for this...
|
||||||
|
for (int i = overlays.size(); i < overlay.getZLevel(); ++i) {
|
||||||
|
overlays.add(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add overlay to the given list.
|
||||||
|
overlays.get(overlay.getZLevel() - 1).add(overlay);
|
||||||
|
|
||||||
|
// Repaint if requested.
|
||||||
|
if (repaint) {
|
||||||
|
BasicDrawing.this.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
return overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// Default path color.
|
// Default path color.
|
||||||
public static final Color DEFAULT_PATH_COLOR = new Color(66, 134, 244);
|
public static final Color DEFAULT_PATH_COLOR = new Color(66, 134, 244);
|
||||||
|
|
||||||
@ -317,8 +392,7 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
private Graphics2D graphGraphics = null;
|
private Graphics2D graphGraphics = null;
|
||||||
|
|
||||||
// List of image for markers
|
// List of image for markers
|
||||||
private List<BasicOverlay> overlays = Collections
|
private BasicOverlays overlays = new BasicOverlays();
|
||||||
.synchronizedList(new ArrayList<BasicOverlay>());
|
|
||||||
|
|
||||||
// Mapping DrawingClickListener -> MouseEventListener
|
// Mapping DrawingClickListener -> MouseEventListener
|
||||||
private List<DrawingClickListener> drawingClickListeners = new ArrayList<>();
|
private List<DrawingClickListener> drawingClickListeners = new ArrayList<>();
|
||||||
@ -391,11 +465,7 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw markers
|
// Draw markers
|
||||||
synchronized (overlays) {
|
this.overlays.draw(g);
|
||||||
for (BasicOverlay overlay: overlays) {
|
|
||||||
overlay.draw(g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g.setTransform(sTransform);
|
g.setTransform(sTransform);
|
||||||
if (this.zoomControls != null) {
|
if (this.zoomControls != null) {
|
||||||
@ -416,9 +486,7 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
if (this.graphGraphics != null) {
|
if (this.graphGraphics != null) {
|
||||||
this.graphGraphics.clearRect(0, 0, this.width, this.height);
|
this.graphGraphics.clearRect(0, 0, this.width, this.height);
|
||||||
}
|
}
|
||||||
synchronized (overlays) {
|
this.overlays.clear(false);
|
||||||
this.overlays.clear();
|
|
||||||
}
|
|
||||||
this.repaint();
|
this.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,11 +497,8 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void clearOverlays() {
|
public void clearOverlays() {
|
||||||
synchronized (overlays) {
|
|
||||||
this.overlays.clear();
|
this.overlays.clear();
|
||||||
}
|
}
|
||||||
this.repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The current ZoomAndPanListener associated with this drawing.
|
* @return The current ZoomAndPanListener associated with this drawing.
|
||||||
@ -495,21 +560,12 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MarkerOverlay drawMarker(Point point, Color outer, Color inner, AlphaMode mode) {
|
public MarkerOverlay drawMarker(Point point, Color outer, Color inner, AlphaMode mode) {
|
||||||
BasicMarkerOverlay marker = createMarker(point, outer, inner, mode);
|
return (MarkerOverlay) this.overlays.add(createMarker(point, outer, inner, mode));
|
||||||
synchronized (overlays) {
|
|
||||||
this.overlays.add(marker);
|
|
||||||
}
|
|
||||||
this.repaint();
|
|
||||||
return marker;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PointSetOverlay createPointSetOverlay() {
|
public PointSetOverlay createPointSetOverlay() {
|
||||||
BasicPointSetOverlay ps = new BasicPointSetOverlay();
|
return (PointSetOverlay) this.overlays.add(new BasicPointSetOverlay(), false);
|
||||||
synchronized (overlays) {
|
|
||||||
this.overlays.add(ps);
|
|
||||||
}
|
|
||||||
return ps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -671,12 +727,8 @@ public class BasicDrawing extends JPanel implements Drawing {
|
|||||||
destination = createMarker(path.getDestination().getPoint(), color, color,
|
destination = createMarker(path.getDestination().getPoint(), color, color,
|
||||||
AlphaMode.TRANSPARENT);
|
AlphaMode.TRANSPARENT);
|
||||||
}
|
}
|
||||||
BasicPathOverlay overlay = new BasicPathOverlay(points, color, origin, destination);
|
return (PathOverlay) this.overlays
|
||||||
synchronized (overlays) {
|
.add(new BasicPathOverlay(points, color, origin, destination));
|
||||||
this.overlays.add(overlay);
|
|
||||||
}
|
|
||||||
this.repaint();
|
|
||||||
return overlay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -18,7 +18,8 @@ import org.mapsforge.map.layer.overlay.Marker;
|
|||||||
* correcting this. Internally, this image stores an {@link Image} instance and
|
* correcting this. Internally, this image stores an {@link Image} instance and
|
||||||
* scale it when a redraw is requested.
|
* scale it when a redraw is requested.
|
||||||
*
|
*
|
||||||
* @see MarkerUtils#getMarkerForColor(java.awt.Color)
|
* @see MarkerUtils#getMarkerForColor(java.awt.Color, java.awt.Color,
|
||||||
|
* org.insa.graphics.drawing.Drawing.AlphaMode)
|
||||||
* @see PaintUtils#getStrokeWidth(int, byte)
|
* @see PaintUtils#getStrokeWidth(int, byte)
|
||||||
*/
|
*/
|
||||||
public class MarkerAutoScaling extends Marker {
|
public class MarkerAutoScaling extends Marker {
|
||||||
|
@ -18,8 +18,6 @@ public class MarkerUtils {
|
|||||||
* @param mode Mode to use to fill the inner part of the marker.
|
* @param mode Mode to use to fill the inner part of the marker.
|
||||||
*
|
*
|
||||||
* @return An image representing a marker.
|
* @return An image representing a marker.
|
||||||
*
|
|
||||||
* @see MarkerUtils#getMarkerForColor(Color, AlphaMode)
|
|
||||||
*/
|
*/
|
||||||
public static Image getMarkerForColor(Color outer, Color inner, AlphaMode mode) {
|
public static Image getMarkerForColor(Color outer, Color inner, AlphaMode mode) {
|
||||||
// create image
|
// create image
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.insa.algo.utils;
|
package org.insa.algo.utils;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -59,46 +60,78 @@ public class BinaryHeapTest {
|
|||||||
this.heap2 = new BinaryHeap<>();
|
this.heap2 = new BinaryHeap<>();
|
||||||
|
|
||||||
for (MutableInteger v: data1) {
|
for (MutableInteger v: data1) {
|
||||||
this.heap1.add(v);
|
this.heap1.insert(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MutableInteger v: data2) {
|
for (MutableInteger v: data2) {
|
||||||
this.heap2.add(v);
|
this.heap2.insert(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsEmpty() {
|
||||||
|
BinaryHeap<MutableInteger> tree = new BinaryHeap<>();
|
||||||
|
assertTrue(tree.isEmpty());
|
||||||
|
assertFalse(this.heap1.isEmpty());
|
||||||
|
assertFalse(this.heap2.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSize() {
|
||||||
|
BinaryHeap<MutableInteger> tree = new BinaryHeap<>();
|
||||||
|
assertEquals(0, tree.size());
|
||||||
|
assertEquals(20, this.heap1.size());
|
||||||
|
assertEquals(7, this.heap2.size());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInsert() {
|
public void testInsert() {
|
||||||
BinaryHeap<MutableInteger> heap = new BinaryHeap<>();
|
BinaryHeap<MutableInteger> heap = new BinaryHeap<>();
|
||||||
int size = 0;
|
int size = 0;
|
||||||
for (MutableInteger x: data1) {
|
for (MutableInteger x: data1) {
|
||||||
heap.add(x);
|
heap.insert(x);
|
||||||
size += 1;
|
assertEquals(++size, heap.size());
|
||||||
assertEquals(heap.size(), size);
|
|
||||||
}
|
}
|
||||||
assertEquals(data1.length, heap.size());
|
assertEquals(data1.length, heap.size());
|
||||||
|
|
||||||
heap = new BinaryHeap<>();
|
heap = new BinaryHeap<>();
|
||||||
size = 0;
|
size = 0;
|
||||||
for (MutableInteger x: data2) {
|
for (MutableInteger x: data2) {
|
||||||
heap.add(x);
|
heap.insert(x);
|
||||||
size += 1;
|
assertEquals(++size, heap.size());
|
||||||
assertEquals(heap.size(), size);
|
|
||||||
}
|
}
|
||||||
assertEquals(data2.length, heap.size());
|
assertEquals(data2.length, heap.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = EmptyPriorityQueueException.class)
|
||||||
|
public void testEmptyFindMin() {
|
||||||
|
BinaryHeap<MutableInteger> heap = new BinaryHeap<>();
|
||||||
|
heap.findMin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindMin() {
|
||||||
|
assertEquals(0, heap1.findMin().get());
|
||||||
|
assertEquals(1, heap2.findMin().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = EmptyPriorityQueueException.class)
|
||||||
|
public void testEmptyDeleteMin() {
|
||||||
|
BinaryHeap<MutableInteger> heap = new BinaryHeap<>();
|
||||||
|
heap.deleteMin();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteMin() {
|
public void testDeleteMin() {
|
||||||
// range 1 (sorted)
|
// range 1 (sorted)
|
||||||
int size = data1.length;
|
int size = data1.length;
|
||||||
assertEquals(heap1.size(), size);
|
assertEquals(heap1.size(), size);
|
||||||
for (MutableInteger x: data1) {
|
for (MutableInteger x: data1) {
|
||||||
assertEquals(heap1.deleteMin(), x);
|
assertEquals(x, heap1.deleteMin());
|
||||||
size -= 1;
|
size -= 1;
|
||||||
assertEquals(heap1.size(), size);
|
assertEquals(size, heap1.size());
|
||||||
}
|
}
|
||||||
assertEquals(heap1.size(), 0);
|
assertEquals(0, heap1.size());
|
||||||
assertTrue(heap1.isEmpty());
|
assertTrue(heap1.isEmpty());
|
||||||
|
|
||||||
// range 2 (was not sorted)
|
// range 2 (was not sorted)
|
||||||
@ -107,20 +140,56 @@ public class BinaryHeapTest {
|
|||||||
size = range2.length;
|
size = range2.length;
|
||||||
assertEquals(heap2.size(), size);
|
assertEquals(heap2.size(), size);
|
||||||
for (MutableInteger x: range2) {
|
for (MutableInteger x: range2) {
|
||||||
assertEquals(heap2.deleteMin().get(), x.get());
|
assertEquals(x.get(), heap2.deleteMin().get());
|
||||||
size -= 1;
|
size -= 1;
|
||||||
assertEquals(heap2.size(), size);
|
assertEquals(size, heap2.size());
|
||||||
|
}
|
||||||
|
assertEquals(0, heap2.size());
|
||||||
|
assertTrue(heap2.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ElementNotFoundException.class)
|
||||||
|
public void testRemoveEmpty() {
|
||||||
|
BinaryHeap<MutableInteger> heap = new BinaryHeap<>();
|
||||||
|
heap.remove(new MutableInteger(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ElementNotFoundException.class)
|
||||||
|
public void testRemoveNotFound() {
|
||||||
|
heap1.remove(new MutableInteger(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemove() {
|
||||||
|
// heap 1
|
||||||
|
int size1 = heap1.size();
|
||||||
|
int[] deleteOrder1 = new int[] { 12, 17, 18, 19, 4, 5, 3, 2, 0, 9, 10, 16, 8, 14, 13, 15, 7,
|
||||||
|
6, 1, 11 };
|
||||||
|
for (int x: deleteOrder1) {
|
||||||
|
heap1.remove(this.data1[x]);
|
||||||
|
assertEquals(--size1, heap1.size());
|
||||||
|
}
|
||||||
|
assertTrue(heap1.isEmpty());
|
||||||
|
|
||||||
|
// heap 2
|
||||||
|
int size2 = heap2.size();
|
||||||
|
int[] deleteOrder2 = new int[] { 6, 5, 0, 1, 4, 2, 3 };
|
||||||
|
for (int x: deleteOrder2) {
|
||||||
|
heap2.remove(this.data2[x]);
|
||||||
|
assertEquals(--size2, heap2.size());
|
||||||
}
|
}
|
||||||
assertEquals(heap2.size(), 0);
|
|
||||||
assertTrue(heap2.isEmpty());
|
assertTrue(heap2.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdate() {
|
public void testRemoveThenAdd() {
|
||||||
MutableInteger newMin = data2[data2.length - 1];
|
MutableInteger mi5 = this.data1[6];
|
||||||
newMin.set(0);
|
heap1.remove(mi5);
|
||||||
heap2.update(newMin);
|
assertEquals(19, heap1.size());
|
||||||
assertEquals(heap2.findMin(), newMin);
|
mi5.set(-20);
|
||||||
|
heap1.insert(mi5);
|
||||||
|
assertEquals(20, heap1.size());
|
||||||
|
assertEquals(-20, heap1.findMin().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
195
src/test/org/insa/algo/utils/BinarySearchTreeTest.java
Normal file
195
src/test/org/insa/algo/utils/BinarySearchTreeTest.java
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
package org.insa.algo.utils;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class BinarySearchTreeTest {
|
||||||
|
|
||||||
|
class MutableInteger implements Comparable<MutableInteger> {
|
||||||
|
|
||||||
|
// Actual value
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
public MutableInteger(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The integer value stored inside this MutableInteger.
|
||||||
|
*/
|
||||||
|
public int get() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the integer value stored inside this MutableInteger.
|
||||||
|
*
|
||||||
|
* @param value New value to set.
|
||||||
|
*/
|
||||||
|
public void set(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(MutableInteger other) {
|
||||||
|
return Integer.compare(this.value, other.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Raw data arrays.
|
||||||
|
private MutableInteger[] data1 = IntStream.range(0, 20).mapToObj(MutableInteger::new)
|
||||||
|
.toArray(MutableInteger[]::new);
|
||||||
|
private MutableInteger[] data2 = Arrays.stream(new int[] { 8, 1, 6, 3, 4, 5, 9 })
|
||||||
|
.mapToObj(MutableInteger::new).toArray(MutableInteger[]::new);
|
||||||
|
|
||||||
|
// Actual searchTree.
|
||||||
|
private BinarySearchTree<MutableInteger> searchTree1, searchTree2;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
// Create the range searchTree
|
||||||
|
this.searchTree1 = new BinarySearchTree<>();
|
||||||
|
this.searchTree2 = new BinarySearchTree<>();
|
||||||
|
|
||||||
|
for (MutableInteger v: data1) {
|
||||||
|
this.searchTree1.insert(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MutableInteger v: data2) {
|
||||||
|
this.searchTree2.insert(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsEmpty() {
|
||||||
|
BinarySearchTree<MutableInteger> tree = new BinarySearchTree<>();
|
||||||
|
assertTrue(tree.isEmpty());
|
||||||
|
assertFalse(this.searchTree1.isEmpty());
|
||||||
|
assertFalse(this.searchTree2.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSize() {
|
||||||
|
BinarySearchTree<MutableInteger> tree = new BinarySearchTree<>();
|
||||||
|
assertEquals(0, tree.size());
|
||||||
|
assertEquals(20, this.searchTree1.size());
|
||||||
|
assertEquals(7, this.searchTree2.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsert() {
|
||||||
|
BinarySearchTree<MutableInteger> searchTree = new BinarySearchTree<>();
|
||||||
|
int size = 0;
|
||||||
|
for (MutableInteger x: data1) {
|
||||||
|
searchTree.insert(x);
|
||||||
|
assertEquals(++size, searchTree.size());
|
||||||
|
}
|
||||||
|
assertEquals(data1.length, searchTree.size());
|
||||||
|
|
||||||
|
searchTree = new BinarySearchTree<>();
|
||||||
|
size = 0;
|
||||||
|
for (MutableInteger x: data2) {
|
||||||
|
searchTree.insert(x);
|
||||||
|
assertEquals(++size, searchTree.size());
|
||||||
|
}
|
||||||
|
assertEquals(data2.length, searchTree.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = EmptyPriorityQueueException.class)
|
||||||
|
public void testEmptyFindMin() {
|
||||||
|
BinarySearchTree<MutableInteger> searchTree = new BinarySearchTree<>();
|
||||||
|
searchTree.findMin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindMin() {
|
||||||
|
assertEquals(0, searchTree1.findMin().get());
|
||||||
|
assertEquals(1, searchTree2.findMin().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = EmptyPriorityQueueException.class)
|
||||||
|
public void testEmptyDeleteMin() {
|
||||||
|
BinarySearchTree<MutableInteger> searchTree = new BinarySearchTree<>();
|
||||||
|
searchTree.deleteMin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteMin() {
|
||||||
|
// range 1 (sorted)
|
||||||
|
int size = data1.length;
|
||||||
|
assertEquals(searchTree1.size(), size);
|
||||||
|
for (MutableInteger x: data1) {
|
||||||
|
assertEquals(x, searchTree1.deleteMin());
|
||||||
|
size -= 1;
|
||||||
|
assertEquals(size, searchTree1.size());
|
||||||
|
}
|
||||||
|
assertEquals(0, searchTree1.size());
|
||||||
|
assertTrue(searchTree1.isEmpty());
|
||||||
|
|
||||||
|
// range 2 (was not sorted)
|
||||||
|
MutableInteger[] range2 = Arrays.copyOf(data2, data2.length);
|
||||||
|
Arrays.sort(range2);
|
||||||
|
size = range2.length;
|
||||||
|
assertEquals(searchTree2.size(), size);
|
||||||
|
for (MutableInteger x: range2) {
|
||||||
|
assertEquals(x.get(), searchTree2.deleteMin().get());
|
||||||
|
size -= 1;
|
||||||
|
assertEquals(size, searchTree2.size());
|
||||||
|
}
|
||||||
|
assertEquals(0, searchTree2.size());
|
||||||
|
assertTrue(searchTree2.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ElementNotFoundException.class)
|
||||||
|
public void testRemoveEmpty() {
|
||||||
|
BinarySearchTree<MutableInteger> searchTree = new BinarySearchTree<>();
|
||||||
|
searchTree.remove(new MutableInteger(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ElementNotFoundException.class)
|
||||||
|
public void testRemoveNotFound() {
|
||||||
|
searchTree1.remove(new MutableInteger(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemove() {
|
||||||
|
// searchTree 1
|
||||||
|
int size1 = searchTree1.size();
|
||||||
|
int[] deleteOrder1 = new int[] { 12, 17, 18, 19, 4, 5, 3, 2, 0, 9, 10, 16, 8, 14, 13, 15, 7,
|
||||||
|
6, 1, 11 };
|
||||||
|
for (int x: deleteOrder1) {
|
||||||
|
searchTree1.remove(this.data1[x]);
|
||||||
|
assertEquals(--size1, searchTree1.size());
|
||||||
|
}
|
||||||
|
assertTrue(searchTree1.isEmpty());
|
||||||
|
|
||||||
|
// searchTree 2
|
||||||
|
int size2 = searchTree2.size();
|
||||||
|
int[] deleteOrder2 = new int[] { 6, 5, 0, 1, 4, 2, 3 };
|
||||||
|
for (int x: deleteOrder2) {
|
||||||
|
searchTree2.remove(this.data2[x]);
|
||||||
|
assertEquals(--size2, searchTree2.size());
|
||||||
|
}
|
||||||
|
assertTrue(searchTree2.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveThenAdd() {
|
||||||
|
MutableInteger mi5 = this.data1[6];
|
||||||
|
searchTree1.remove(mi5);
|
||||||
|
assertEquals(19, searchTree1.size());
|
||||||
|
mi5.set(-20);
|
||||||
|
searchTree1.insert(mi5);
|
||||||
|
assertEquals(20, searchTree1.size());
|
||||||
|
assertEquals(-20, searchTree1.findMin().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user