commit 789cccd73d6d70432afe90a1ee294904b320002d
Author: abdelkaderakoum1 <164890243+abdelkaderakoum1@users.noreply.github.com>
Date: Tue May 13 10:19:38 2025 +0200
My initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..969d625
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+# OS specific files and folders
+.DS_Store
+
+# Java specific files and folders
+bin
+target
+doc
+*.jar
+.settings
+.classpath
+.vscode
+
+# Editor specific files and folders
+*~
+.project
+
+# Project specific files and folders
+*.mapfg
+*.mapgr
+*.path
+*.tgz
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fec4f74
--- /dev/null
+++ b/README.md
@@ -0,0 +1,35 @@
+# Graph & Algorithm project — INSA Toulouse
+
+This is an INSA local copy of [Mikael CAPELLE's repository](https://gitea.typename.fr/INSA/be-graphes).
+
+## How to start?
+
+1. On your favorite platform, create a new empty repository of yours.
+ - [INSA GitEtud](https://git.etud.insa-toulouse.fr/)
+ - [Gitlab](https://gitlab.com/)
+ - [Bitbucket](https://bitbucket.org/)
+ - [Github](https://github.com/)
+
+2. On your computer or on an INSA computer, clone your own repository (in the following, we call it MINE)
+ ```bash
+ git clone (here-the-https-URL-to-your-own-repository)
+ ```
+
+3. Somewhere else on the same computer, clone this repository (we call it THEIRS)
+ ```bash
+ git clone https://git.etud.insa-toulouse.fr/lebotlan/BE-Graphes.git
+ ```
+
+4. In this cloned directory (THEIRS), remove the `.git` folder.
+
+5. Your repository (MINE) is initially empty. Move all the content of the BE-Graphes project (THEIRS) into it. Keep also the .gitignore file.
+
+6. Commit your changes (MINE):
+ ```bash
+ git status
+ git add .
+ git status ## Check the added files
+ git commit -m "My initial commit"
+ git push
+ ```
+
diff --git a/be-graphes-algos/pom.xml b/be-graphes-algos/pom.xml
new file mode 100644
index 0000000..bfa028e
--- /dev/null
+++ b/be-graphes-algos/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+
+ org.insa.graphs
+ be-graphes-all
+ 0.0.1-SNAPSHOT
+
+
+ be-graphes-algos
+ be-graphes-algos
+
+
+
+ org.insa.graphs
+ be-graphes-model
+ ${project.version}
+
+
+
+
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractAlgorithm.java
new file mode 100644
index 0000000..6f6f4f7
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractAlgorithm.java
@@ -0,0 +1,85 @@
+package org.insa.graphs.algorithm;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+
+/**
+ * Base class for algorithm classes.
+ *
+ * @param Observer type for the algorithm.
+ */
+public abstract class AbstractAlgorithm {
+
+ // Input data for the algorithm
+ protected final AbstractInputData data;
+
+ // List of observers for the algorithm
+ protected final ArrayList observers;
+
+ /**
+ * Create a new algorithm with an empty list of observers.
+ *
+ * @param data Input data for the algorithm.
+ */
+ protected AbstractAlgorithm(AbstractInputData data) {
+ this.data = data;
+ this.observers = new ArrayList();
+ }
+
+ /**
+ * Create a new algorithm with the given list of observers.
+ *
+ * @param data Input data for the algorithm.
+ * @param observers Initial list of observers for the algorithm.
+ */
+ protected AbstractAlgorithm(AbstractInputData data, ArrayList observers) {
+ this.data = data;
+ this.observers = observers;
+ }
+
+ /**
+ * Add an observer to this algorithm.
+ *
+ * @param observer Observer to add to this algorithm.
+ */
+ public void addObserver(Observer observer) {
+ observers.add(observer);
+ }
+
+ /**
+ * @return The list of observers for this algorithm.
+ */
+ public ArrayList getObservers() {
+ return observers;
+ }
+
+ /**
+ * @return Input for this algorithm.
+ */
+ public AbstractInputData getInputData() {
+ return data;
+ }
+
+ /**
+ * Run the algorithm and return the solution. This methods internally time the call
+ * to doRun() and update the result of the call with the computed solving time.
+ *
+ * @return The solution found by the algorithm (may not be a feasible solution).
+ */
+ public AbstractSolution run() {
+ Instant start = Instant.now();
+ AbstractSolution solution = this.doRun();
+ solution.setSolvingTime(Duration.between(start, Instant.now()));
+ return solution;
+ }
+
+ /**
+ * Abstract method that should be implemented by child class.
+ *
+ * @return The solution found, must not be null (use an infeasible or unknown status
+ * if necessary).
+ */
+ protected abstract AbstractSolution doRun();
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractInputData.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractInputData.java
new file mode 100644
index 0000000..3366bf9
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractInputData.java
@@ -0,0 +1,94 @@
+package org.insa.graphs.algorithm;
+
+import org.insa.graphs.model.Arc;
+import org.insa.graphs.model.Graph;
+import org.insa.graphs.model.GraphStatistics;
+
+/**
+ * Base class for algorithm input data classes. This class contains the basic data that
+ * are required by most graph algorithms, i.e. a graph, a mode (time / length) and a
+ * filter for the arc.
+ */
+public abstract class AbstractInputData {
+
+ /**
+ * Enum specifying the top mode of the algorithms.
+ *
+ * @see ArcInspector
+ */
+ public enum Mode {
+ TIME, LENGTH
+ }
+
+ // Graph
+ private final Graph graph;
+
+ // Arc filter.
+ protected final ArcInspector arcInspector;
+
+ /**
+ * Create a new AbstractInputData instance for the given graph, mode and filter.
+ *
+ * @param graph Graph for this input data.
+ * @param arcInspector Arc inspector for this input data.
+ */
+ protected AbstractInputData(Graph graph, ArcInspector arcInspector) {
+ this.graph = graph;
+ this.arcInspector = arcInspector;
+ }
+
+ /**
+ * @return Graph associated with this input.
+ */
+ public Graph getGraph() {
+ return graph;
+ }
+
+ /**
+ * 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
+ */
+ public Mode getMode() {
+ 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() {
+ final int inspectorMaxSpeed = this.arcInspector.getMaximumSpeed();
+ return inspectorMaxSpeed == GraphStatistics.NO_MAXIMUM_SPEED
+ ? getGraph().getGraphInformation().getMaximumSpeed()
+ : inspectorMaxSpeed;
+ }
+
+ /**
+ * Check if the given arc is allowed for the filter corresponding to this input.
+ *
+ * @param arc Arc to check.
+ * @return true if the given arc is allowed.
+ * @see ArcInspector
+ */
+ public boolean isAllowed(Arc arc) {
+ return this.arcInspector.isAllowed(arc);
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractSolution.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractSolution.java
new file mode 100644
index 0000000..cb312ab
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractSolution.java
@@ -0,0 +1,85 @@
+package org.insa.graphs.algorithm;
+
+import java.time.Duration;
+
+/**
+ * Base class for solution classes returned by the algorithm. This class contains the
+ * basic information that any solution should have: status of the solution (unknown,
+ * infeasible, etc.), solving time and the original input data.
+ */
+public abstract class AbstractSolution {
+
+ /**
+ * Possible status for a solution.
+ */
+ public enum Status {
+ UNKNOWN, INFEASIBLE, FEASIBLE, OPTIMAL,
+ };
+
+ // Status of the solution.
+ private final Status status;
+
+ // Solving time for the solution.
+ private Duration solvingTime;
+
+ // Original input of the solution.
+ private final AbstractInputData data;
+
+ /**
+ * Create a new abstract solution with unknown status.
+ *
+ * @param data
+ */
+ protected AbstractSolution(AbstractInputData data) {
+ this.data = data;
+ this.solvingTime = Duration.ZERO;
+ this.status = Status.UNKNOWN;
+ }
+
+ /**
+ * @param data
+ * @param status
+ */
+ protected AbstractSolution(AbstractInputData data, Status status) {
+ this.data = data;
+ this.status = status;
+ }
+
+ /**
+ * @return Original input for this solution.
+ */
+ public AbstractInputData getInputData() {
+ return data;
+ }
+
+ /**
+ * @return Status of this solution.
+ */
+ public Status getStatus() {
+ return status;
+ }
+
+ /**
+ * @return Solving time of this solution.
+ */
+ public Duration getSolvingTime() {
+ return solvingTime;
+ }
+
+ /**
+ * Set the solving time of this solution.
+ *
+ * @param solvingTime Solving time for the solution.
+ */
+ protected void setSolvingTime(Duration solvingTime) {
+ this.solvingTime = solvingTime;
+ }
+
+ /**
+ * @return true if the solution is feasible or optimal.
+ */
+ public boolean isFeasible() {
+ return status == Status.FEASIBLE || status == Status.OPTIMAL;
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AlgorithmFactory.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AlgorithmFactory.java
new file mode 100644
index 0000000..9bb811f
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AlgorithmFactory.java
@@ -0,0 +1,125 @@
+package org.insa.graphs.algorithm;
+
+import java.lang.reflect.Constructor;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.insa.graphs.algorithm.shortestpath.AStarAlgorithm;
+import org.insa.graphs.algorithm.shortestpath.BellmanFordAlgorithm;
+import org.insa.graphs.algorithm.shortestpath.DijkstraAlgorithm;
+import org.insa.graphs.algorithm.shortestpath.ShortestPathAlgorithm;
+import org.insa.graphs.algorithm.weakconnectivity.WeaklyConnectedComponentsAlgorithm;
+
+/**
+ * Factory class used to register and retrieve algorithms based on their common ancestor
+ * and name.
+ */
+public class AlgorithmFactory {
+
+ // Map between algorithm names and class.
+ private final static Map>, Map>>> ALGORITHMS =
+ new IdentityHashMap<>();
+
+ static {
+ // Register weakly-connected components algorithm:
+ registerAlgorithm(WeaklyConnectedComponentsAlgorithm.class, "WCC basic",
+ WeaklyConnectedComponentsAlgorithm.class);
+
+ // Register shortest path algorithm:
+ registerAlgorithm(ShortestPathAlgorithm.class, "Bellman-Ford",
+ BellmanFordAlgorithm.class);
+ registerAlgorithm(ShortestPathAlgorithm.class, "Dijkstra",
+ DijkstraAlgorithm.class);
+ registerAlgorithm(ShortestPathAlgorithm.class, "A*", AStarAlgorithm.class);
+
+ // Register your algorithms here:
+ // registerAlgorithm(CarPoolingAlgorithm.class, "My Awesome Algorithm",
+ // MyCarPoolingAlgorithm.class);
+ }
+
+ /**
+ * Register the given algorithm class with the given name as a child class of the
+ * given base algorithm.
+ *
+ * @param baseAlgorithm Base algorithm class that corresponds to the newly
+ * registered algorithm class (e.g., generic algorithm class for the
+ * problem).
+ * @param name Name for the registered algorithm class.
+ * @param algoClass Algorithm class to register.
+ */
+ public static void registerAlgorithm(
+ Class extends AbstractAlgorithm>> baseAlgorithm, String name,
+ Class extends AbstractAlgorithm>> algoClass) {
+ if (!ALGORITHMS.containsKey(baseAlgorithm)) {
+ ALGORITHMS.put(baseAlgorithm, new LinkedHashMap<>());
+ }
+ ALGORITHMS.get(baseAlgorithm).put(name, algoClass);
+ }
+
+ /**
+ * Create an instance of the given algorithm class using the given input data.
+ * Assuming algorithm correspond to a class "Algorithm", this function returns an
+ * object equivalent to `new Algorithm(data)`.
+ *
+ * @param algorithm Class of the algorithm to create.
+ * @param data Input data for the algorithm.
+ * @return A new instance of the given algorithm class using the given data.
+ * @throws Exception if something wrong happens when constructing the object, i.e.
+ * the given input data does not correspond to the given algorithm and/or no
+ * constructor that takes a single parameter of type (data.getClass())
+ * exists.
+ */
+ public static AbstractAlgorithm> createAlgorithm(
+ Class extends AbstractAlgorithm>> algorithm, AbstractInputData data)
+ throws Exception {
+ // Retrieve the set of constructors for the given algorithm class.
+ Constructor>[] constructors = algorithm.getDeclaredConstructors();
+
+ // Within this set, find the constructor that can be called with "data" (only).
+ AbstractAlgorithm> constructed = null;
+ for (Constructor> c : constructors) {
+ Class>[] params = c.getParameterTypes();
+ if (params.length == 1 && params[0].isAssignableFrom(data.getClass())) {
+ c.setAccessible(true);
+ constructed =
+ (AbstractAlgorithm>) c.newInstance(new Object[] { data });
+ break;
+ }
+ }
+ return constructed;
+ }
+
+ /**
+ * Return the algorithm class corresponding to the given base algorithm class and
+ * name. The algorithm must have been previously registered using registerAlgorithm.
+ *
+ * @param baseAlgorithm Base algorithm class for the algorithm to retrieve.
+ * @param name Name of the algorithm to retrieve.
+ * @return Class corresponding to the given name.
+ * @see #registerAlgorithm
+ */
+ public static Class extends AbstractAlgorithm>> getAlgorithmClass(
+ Class extends AbstractAlgorithm>> baseAlgorithm, String name) {
+ return ALGORITHMS.get(baseAlgorithm).get(name);
+ }
+
+ /**
+ * Return the list of names corresponding to the registered algorithm classes for
+ * the given base algorithm class.
+ *
+ * @param baseAlgorithm Base algorithm class for the algorithm class names to
+ * retrieve.
+ * @return Names of the currently registered algorithms.
+ * @see #registerAlgorithm
+ */
+ public static Set getAlgorithmNames(
+ Class extends AbstractAlgorithm>> baseAlgorithm) {
+ if (!ALGORITHMS.containsKey(baseAlgorithm)) {
+ return new TreeSet<>();
+ }
+ return ALGORITHMS.get(baseAlgorithm).keySet();
+ }
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/ArcInspector.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/ArcInspector.java
new file mode 100644
index 0000000..b37571c
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/ArcInspector.java
@@ -0,0 +1,40 @@
+package org.insa.graphs.algorithm;
+
+import org.insa.graphs.algorithm.AbstractInputData.Mode;
+import org.insa.graphs.model.Arc;
+import org.insa.graphs.model.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();
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/ArcInspectorFactory.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/ArcInspectorFactory.java
new file mode 100644
index 0000000..45c1a75
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/ArcInspectorFactory.java
@@ -0,0 +1,124 @@
+package org.insa.graphs.algorithm;
+
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import org.insa.graphs.algorithm.AbstractInputData.Mode;
+import org.insa.graphs.model.Arc;
+import org.insa.graphs.model.GraphStatistics;
+import org.insa.graphs.model.AccessRestrictions.AccessMode;
+import org.insa.graphs.model.AccessRestrictions.AccessRestriction;
+
+public class ArcInspectorFactory {
+
+ private static class NoFilterByLengthArcInspector implements 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";
+ }
+ };
+
+ private static class OnlyCarsByLengthArcInspector
+ extends NoFilterByLengthArcInspector {
+
+ @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 "Shortest path, only roads open for cars";
+ }
+ };
+
+ private static class OnlyCarsByTimeArcInspector
+ extends NoFilterByLengthArcInspector {
+
+ @Override
+ public double getCost(Arc arc) {
+ return arc.getMinimumTravelTime();
+ }
+
+ @Override
+ public Mode getMode() {
+ return Mode.TIME;
+ }
+
+ @Override
+ public String toString() {
+ return "Fastest path, all roads allowed";
+ }
+ };
+
+ private static class OnlyPedestrianByTime implements ArcInspector {
+
+ static final int maxPedestrianSpeed = 5;
+
+ @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(maxPedestrianSpeed,
+ 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;
+ }
+ };
+
+ /**
+ * @return List of all arc filters in this factory.
+ */
+ public static List getAllFilters() {
+ // Add your own filters here (do not forget to implement toString()
+ // to get an understandable output!):
+ return Arrays.asList(new NoFilterByLengthArcInspector(),
+ new OnlyCarsByLengthArcInspector(), new OnlyCarsByTimeArcInspector(),
+ new OnlyPedestrianByTime());
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingAlgorithm.java
new file mode 100644
index 0000000..55a76c7
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingAlgorithm.java
@@ -0,0 +1,25 @@
+package org.insa.graphs.algorithm.carpooling;
+
+import org.insa.graphs.algorithm.AbstractAlgorithm;
+
+public abstract class CarPoolingAlgorithm
+ extends AbstractAlgorithm {
+
+ protected CarPoolingAlgorithm(CarPoolingData data) {
+ super(data);
+ }
+
+ @Override
+ public CarPoolingSolution run() {
+ return (CarPoolingSolution) super.run();
+ }
+
+ @Override
+ protected abstract CarPoolingSolution doRun();
+
+ @Override
+ public CarPoolingData getInputData() {
+ return (CarPoolingData) super.getInputData();
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingData.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingData.java
new file mode 100644
index 0000000..d281f72
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingData.java
@@ -0,0 +1,13 @@
+package org.insa.graphs.algorithm.carpooling;
+
+import org.insa.graphs.algorithm.AbstractInputData;
+import org.insa.graphs.algorithm.ArcInspector;
+import org.insa.graphs.model.Graph;
+
+public class CarPoolingData extends AbstractInputData {
+
+ protected CarPoolingData(Graph graph, ArcInspector arcFilter) {
+ super(graph, arcFilter);
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingGraphicObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingGraphicObserver.java
new file mode 100644
index 0000000..eaffac6
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingGraphicObserver.java
@@ -0,0 +1,5 @@
+package org.insa.graphs.algorithm.carpooling;
+
+public class CarPoolingGraphicObserver implements CarPoolingObserver {
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingObserver.java
new file mode 100644
index 0000000..7726e92
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingObserver.java
@@ -0,0 +1,5 @@
+package org.insa.graphs.algorithm.carpooling;
+
+public interface CarPoolingObserver {
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingSolution.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingSolution.java
new file mode 100644
index 0000000..701c47b
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingSolution.java
@@ -0,0 +1,11 @@
+package org.insa.graphs.algorithm.carpooling;
+
+import org.insa.graphs.algorithm.AbstractSolution;
+
+public class CarPoolingSolution extends AbstractSolution {
+
+ protected CarPoolingSolution(CarPoolingData data, Status status) {
+ super(data, status);
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingTextObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingTextObserver.java
new file mode 100644
index 0000000..0327a95
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingTextObserver.java
@@ -0,0 +1,5 @@
+package org.insa.graphs.algorithm.carpooling;
+
+public class CarPoolingTextObserver implements CarPoolingObserver {
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchAlgorithm.java
new file mode 100644
index 0000000..6856aba
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchAlgorithm.java
@@ -0,0 +1,30 @@
+package org.insa.graphs.algorithm.packageswitch;
+
+import org.insa.graphs.algorithm.AbstractAlgorithm;
+
+public abstract class PackageSwitchAlgorithm
+ extends AbstractAlgorithm {
+
+ /**
+ * Create a new PackageSwitchAlgorithm with the given data.
+ *
+ * @param data
+ */
+ protected PackageSwitchAlgorithm(PackageSwitchData data) {
+ super(data);
+ }
+
+ @Override
+ public PackageSwitchSolution run() {
+ return (PackageSwitchSolution) super.run();
+ }
+
+ @Override
+ protected abstract PackageSwitchSolution doRun();
+
+ @Override
+ public PackageSwitchData getInputData() {
+ return (PackageSwitchData) super.getInputData();
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchData.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchData.java
new file mode 100644
index 0000000..cc9e6d5
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchData.java
@@ -0,0 +1,13 @@
+package org.insa.graphs.algorithm.packageswitch;
+
+import org.insa.graphs.algorithm.AbstractInputData;
+import org.insa.graphs.algorithm.ArcInspector;
+import org.insa.graphs.model.Graph;
+
+public class PackageSwitchData extends AbstractInputData {
+
+ protected PackageSwitchData(Graph graph, ArcInspector arcFilter) {
+ super(graph, arcFilter);
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchGraphicObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchGraphicObserver.java
new file mode 100644
index 0000000..6b4af91
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchGraphicObserver.java
@@ -0,0 +1,5 @@
+package org.insa.graphs.algorithm.packageswitch;
+
+public class PackageSwitchGraphicObserver implements PackageSwitchObserver {
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchObserver.java
new file mode 100644
index 0000000..c7313b7
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchObserver.java
@@ -0,0 +1,5 @@
+package org.insa.graphs.algorithm.packageswitch;
+
+public interface PackageSwitchObserver {
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchSolution.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchSolution.java
new file mode 100644
index 0000000..93562bb
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchSolution.java
@@ -0,0 +1,11 @@
+package org.insa.graphs.algorithm.packageswitch;
+
+import org.insa.graphs.algorithm.AbstractSolution;
+
+public class PackageSwitchSolution extends AbstractSolution {
+
+ protected PackageSwitchSolution(PackageSwitchData data, Status status) {
+ super(data, status);
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchTextObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchTextObserver.java
new file mode 100644
index 0000000..d0225d5
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchTextObserver.java
@@ -0,0 +1,5 @@
+package org.insa.graphs.algorithm.packageswitch;
+
+public class PackageSwitchTextObserver implements PackageSwitchObserver {
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/AStarAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/AStarAlgorithm.java
new file mode 100644
index 0000000..fd172f0
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/AStarAlgorithm.java
@@ -0,0 +1,9 @@
+package org.insa.graphs.algorithm.shortestpath;
+
+public class AStarAlgorithm extends DijkstraAlgorithm {
+
+ public AStarAlgorithm(ShortestPathData data) {
+ super(data);
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/BellmanFordAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/BellmanFordAlgorithm.java
new file mode 100644
index 0000000..709438e
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/BellmanFordAlgorithm.java
@@ -0,0 +1,103 @@
+package org.insa.graphs.algorithm.shortestpath;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.insa.graphs.algorithm.AbstractSolution.Status;
+import org.insa.graphs.model.Arc;
+import org.insa.graphs.model.Graph;
+import org.insa.graphs.model.Node;
+import org.insa.graphs.model.Path;
+
+public class BellmanFordAlgorithm extends ShortestPathAlgorithm {
+
+ public BellmanFordAlgorithm(ShortestPathData data) {
+ super(data);
+ }
+
+ @Override
+ protected ShortestPathSolution doRun() {
+
+ // Retrieve the graph.
+ ShortestPathData data = getInputData();
+ Graph graph = data.getGraph();
+
+ final int nbNodes = graph.size();
+
+ // Initialize array of distances.
+ double[] distances = new double[nbNodes];
+ Arrays.fill(distances, Double.POSITIVE_INFINITY);
+ distances[data.getOrigin().getId()] = 0;
+
+ // Notify observers about the first event (origin processed).
+ notifyOriginProcessed(data.getOrigin());
+
+ // Initialize array of predecessors.
+ Arc[] predecessorArcs = new Arc[nbNodes];
+
+ // Actual algorithm, we will assume the graph does not contain negative
+ // cycle...
+ boolean found = false;
+ for (int i = 0; !found && i < nbNodes; ++i) {
+ found = true;
+ for (Node node : graph.getNodes()) {
+ for (Arc arc : node.getSuccessors()) {
+
+ // Small test to check allowed roads...
+ if (!data.isAllowed(arc)) {
+ continue;
+ }
+
+ // Retrieve weight of the arc.
+ double w = data.getCost(arc);
+ double oldDistance = distances[arc.getDestination().getId()];
+ double newDistance = distances[node.getId()] + w;
+
+ if (Double.isInfinite(oldDistance)
+ && Double.isFinite(newDistance)) {
+ notifyNodeReached(arc.getDestination());
+ }
+
+ // Check if new distances would be better, if so update...
+ if (newDistance < oldDistance) {
+ found = false;
+ distances[arc.getDestination().getId()] =
+ distances[node.getId()] + w;
+ predecessorArcs[arc.getDestination().getId()] = arc;
+ }
+ }
+ }
+ }
+
+ ShortestPathSolution solution = null;
+
+ // Destination has no predecessor, the solution is infeasible...
+ if (predecessorArcs[data.getDestination().getId()] == null) {
+ solution = new ShortestPathSolution(data, Status.INFEASIBLE);
+ }
+ else {
+
+ // The destination has been found, notify the observers.
+ notifyDestinationReached(data.getDestination());
+
+ // Create the path from the array of predecessors...
+ ArrayList arcs = new ArrayList<>();
+ Arc arc = predecessorArcs[data.getDestination().getId()];
+ while (arc != null) {
+ arcs.add(arc);
+ arc = predecessorArcs[arc.getOrigin().getId()];
+ }
+
+ // Reverse the path...
+ Collections.reverse(arcs);
+
+ // Create the final solution.
+ solution = new ShortestPathSolution(data, Status.OPTIMAL,
+ new Path(graph, arcs));
+ }
+
+ return solution;
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java
new file mode 100644
index 0000000..18a540f
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java
@@ -0,0 +1,25 @@
+package org.insa.graphs.algorithm.shortestpath;
+
+public class DijkstraAlgorithm extends ShortestPathAlgorithm {
+
+ public DijkstraAlgorithm(ShortestPathData data) {
+ super(data);
+ }
+
+ @Override
+ protected ShortestPathSolution doRun() {
+
+ // retrieve data from the input problem (getInputData() is inherited from the
+ // parent class ShortestPathAlgorithm)
+ final ShortestPathData data = getInputData();
+
+ // variable that will contain the solution of the shortest path problem
+ ShortestPathSolution solution = null;
+
+ // TODO: implement the Dijkstra algorithm
+
+ // when the algorithm terminates, return the solution that has been found
+ return solution;
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathAlgorithm.java
new file mode 100644
index 0000000..fdebcd6
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathAlgorithm.java
@@ -0,0 +1,70 @@
+package org.insa.graphs.algorithm.shortestpath;
+
+import org.insa.graphs.algorithm.AbstractAlgorithm;
+import org.insa.graphs.model.Node;
+
+public abstract class ShortestPathAlgorithm
+ extends AbstractAlgorithm {
+
+ protected ShortestPathAlgorithm(ShortestPathData data) {
+ super(data);
+ }
+
+ @Override
+ public ShortestPathSolution run() {
+ return (ShortestPathSolution) super.run();
+ }
+
+ @Override
+ protected abstract ShortestPathSolution doRun();
+
+ @Override
+ public ShortestPathData getInputData() {
+ return (ShortestPathData) super.getInputData();
+ }
+
+ /**
+ * Notify all observers that the origin has been processed.
+ *
+ * @param node Origin.
+ */
+ public void notifyOriginProcessed(Node node) {
+ for (ShortestPathObserver obs : getObservers()) {
+ obs.notifyOriginProcessed(node);
+ }
+ }
+
+ /**
+ * Notify all observers that a node has been reached for the first time.
+ *
+ * @param node Node that has been reached.
+ */
+ public void notifyNodeReached(Node node) {
+ for (ShortestPathObserver obs : getObservers()) {
+ obs.notifyNodeReached(node);
+ }
+ }
+
+ /**
+ * Notify all observers that a node has been marked, i.e. its final value has been
+ * set.
+ *
+ * @param node Node that has been marked.
+ */
+ public void notifyNodeMarked(Node node) {
+ for (ShortestPathObserver obs : getObservers()) {
+ obs.notifyNodeMarked(node);
+ }
+ }
+
+ /**
+ * Notify all observers that the destination has been reached.
+ *
+ * @param node Destination.
+ */
+ public void notifyDestinationReached(Node node) {
+ for (ShortestPathObserver obs : getObservers()) {
+ obs.notifyDestinationReached(node);
+ }
+ }
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathData.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathData.java
new file mode 100644
index 0000000..4041eb3
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathData.java
@@ -0,0 +1,48 @@
+package org.insa.graphs.algorithm.shortestpath;
+
+import org.insa.graphs.algorithm.AbstractInputData;
+import org.insa.graphs.algorithm.ArcInspector;
+import org.insa.graphs.model.Graph;
+import org.insa.graphs.model.Node;
+
+public class ShortestPathData extends AbstractInputData {
+
+ // Origin and destination nodes.
+ private final Node origin, destination;
+
+ /**
+ * Construct a new instance of ShortestPathInputData with the given parameters.
+ *
+ * @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 arcInspector Filter for arcs (used to allow only a specific set of arcs in
+ * the graph to be used).
+ */
+ public ShortestPathData(Graph graph, Node origin, Node destination,
+ ArcInspector arcInspector) {
+ super(graph, arcInspector);
+ this.origin = origin;
+ this.destination = destination;
+ }
+
+ /**
+ * @return Origin node for the path.
+ */
+ public Node getOrigin() {
+ return origin;
+ }
+
+ /**
+ * @return Destination node for the path.
+ */
+ public Node getDestination() {
+ return destination;
+ }
+
+ @Override
+ public String toString() {
+ return "Shortest-path from #" + origin.getId() + " to #" + destination.getId()
+ + " [" + this.arcInspector.toString().toLowerCase() + "]";
+ }
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathObserver.java
new file mode 100644
index 0000000..371eca8
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathObserver.java
@@ -0,0 +1,36 @@
+package org.insa.graphs.algorithm.shortestpath;
+
+import org.insa.graphs.model.Node;
+
+public interface ShortestPathObserver {
+
+ /**
+ * Notify the observer that the origin has been processed.
+ *
+ * @param node Origin.
+ */
+ public void notifyOriginProcessed(Node node);
+
+ /**
+ * Notify the observer that a node has been reached for the first time.
+ *
+ * @param node Node that has been reached.
+ */
+ public void notifyNodeReached(Node node);
+
+ /**
+ * Notify the observer that a node has been marked, i.e. its final value has been
+ * set.
+ *
+ * @param node Node that has been marked.
+ */
+ public void notifyNodeMarked(Node node);
+
+ /**
+ * Notify the observer that the destination has been reached.
+ *
+ * @param node Destination.
+ */
+ public void notifyDestinationReached(Node node);
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathSolution.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathSolution.java
new file mode 100644
index 0000000..4cbb327
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathSolution.java
@@ -0,0 +1,75 @@
+package org.insa.graphs.algorithm.shortestpath;
+
+import org.insa.graphs.algorithm.AbstractInputData.Mode;
+import org.insa.graphs.model.Arc;
+import org.insa.graphs.model.Path;
+import org.insa.graphs.algorithm.AbstractSolution;
+
+public class ShortestPathSolution extends AbstractSolution {
+
+ // Optimal solution.
+ private final Path path;
+
+ /**
+ * Create a new infeasible shortest-path solution for the given input and status.
+ *
+ * @param data Original input data for this solution.
+ * @param status Status of the solution (UNKNOWN / INFEASIBLE).
+ */
+ public ShortestPathSolution(ShortestPathData data, Status status) {
+ super(data, status);
+ this.path = null;
+ }
+
+ /**
+ * Create a new shortest-path solution.
+ *
+ * @param data Original input data for this solution.
+ * @param status Status of the solution (FEASIBLE / OPTIMAL).
+ * @param path Path corresponding to the solution.
+ */
+ public ShortestPathSolution(ShortestPathData data, Status status, Path path) {
+ super(data, status);
+ this.path = path;
+ }
+
+ @Override
+ public ShortestPathData getInputData() {
+ return (ShortestPathData) super.getInputData();
+ }
+
+ /**
+ * @return The path of this solution, if any.
+ */
+ public Path getPath() {
+ return path;
+ }
+
+ @Override
+ public String toString() {
+ String info = null;
+ if (!isFeasible()) {
+ info = String.format("No path found from node #%d to node #%d",
+ getInputData().getOrigin().getId(),
+ getInputData().getDestination().getId());
+ }
+ 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",
+ getInputData().getOrigin().getId(),
+ getInputData().getDestination().getId());
+ if (getInputData().getMode() == Mode.LENGTH) {
+ info = String.format("%s, %.4f kilometers", info, cost / 1000.0);
+ }
+ else {
+ info = String.format("%s, %.4f minutes", info, cost / 60.0);
+ }
+ }
+ info += " in " + getSolvingTime().getSeconds() + " seconds.";
+ return info;
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathTextObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathTextObserver.java
new file mode 100644
index 0000000..e74cc0a
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathTextObserver.java
@@ -0,0 +1,37 @@
+package org.insa.graphs.algorithm.shortestpath;
+
+import java.io.PrintStream;
+
+import org.insa.graphs.model.Node;
+
+public class ShortestPathTextObserver implements ShortestPathObserver {
+
+ private final PrintStream stream;
+
+ public ShortestPathTextObserver(PrintStream stream) {
+ this.stream = stream;
+ }
+
+ @Override
+ public void notifyOriginProcessed(Node node) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void notifyNodeReached(Node node) {
+ stream.println("Node " + node.getId() + " reached.");
+ }
+
+ @Override
+ public void notifyNodeMarked(Node node) {
+ stream.println("Node " + node.getId() + " marked.");
+ }
+
+ @Override
+ public void notifyDestinationReached(Node node) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinaryHeap.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinaryHeap.java
new file mode 100644
index 0000000..a5073cd
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinaryHeap.java
@@ -0,0 +1,200 @@
+package org.insa.graphs.algorithm.utils;
+
+import java.util.ArrayList;
+
+/**
+ * Implements a binary heap containing elements of type E. Note that all comparisons are
+ * based on the compareTo method, hence E must implement Comparable
+ *
+ * @author Mark Allen Weiss
+ * @author DLB
+ */
+public class BinaryHeap> implements PriorityQueue {
+
+ // Number of elements in heap.
+ private int currentSize;
+
+ // The heap array.
+ protected final ArrayList array;
+
+ /**
+ * Construct a new empty binary heap.
+ */
+ public BinaryHeap() {
+ this.currentSize = 0;
+ this.array = new ArrayList();
+ }
+
+ /**
+ * Construct a copy of the given heap.
+ *
+ * @param heap Binary heap to copy.
+ */
+ public BinaryHeap(BinaryHeap heap) {
+ this.currentSize = heap.currentSize;
+ this.array = new ArrayList(heap.array);
+ }
+
+ /**
+ * Set an element at the given index.
+ *
+ * @param index Index at which the element should be set.
+ * @param value Element to set.
+ */
+ private void arraySet(int index, E value) {
+ if (index == this.array.size()) {
+ this.array.add(value);
+ }
+ else {
+ this.array.set(index, value);
+ }
+ }
+
+ /**
+ * @return Index of the parent of the given index.
+ */
+ protected int indexParent(int index) {
+ return (index - 1) / 2;
+ }
+
+ /**
+ * @return Index of the left child of the given index.
+ */
+ protected int indexLeft(int index) {
+ return index * 2 + 1;
+ }
+
+ /**
+ * Internal method to percolate up in the heap.
+ *
+ * @param index Index at which the percolate begins.
+ */
+ private void percolateUp(int index) {
+ E x = this.array.get(index);
+
+ for (; index > 0 && x.compareTo(this.array.get(indexParent(index))) < 0; index =
+ indexParent(index)) {
+ E moving_val = this.array.get(indexParent(index));
+ this.arraySet(index, moving_val);
+ }
+
+ this.arraySet(index, x);
+ }
+
+ /**
+ * Internal method to percolate down in the heap.
+ *
+ * @param index Index at which the percolate begins.
+ */
+ private void percolateDown(int index) {
+ int ileft = indexLeft(index);
+ int iright = ileft + 1;
+
+ if (ileft < this.currentSize) {
+ E current = this.array.get(index);
+ E left = this.array.get(ileft);
+ boolean hasRight = iright < this.currentSize;
+ E right = (hasRight) ? this.array.get(iright) : null;
+
+ if (!hasRight || left.compareTo(right) < 0) {
+ // Left is smaller
+ if (left.compareTo(current) < 0) {
+ this.arraySet(index, left);
+ this.arraySet(ileft, current);
+ this.percolateDown(ileft);
+ }
+ }
+ else {
+ // Right is smaller
+ if (right.compareTo(current) < 0) {
+ this.arraySet(index, right);
+ this.arraySet(iright, current);
+ this.percolateDown(iright);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return this.currentSize == 0;
+ }
+
+ @Override
+ public int size() {
+ return this.currentSize;
+ }
+
+ @Override
+ public void insert(E x) {
+ int index = this.currentSize++;
+ this.arraySet(index, x);
+ this.percolateUp(index);
+ }
+
+ @Override
+ public void remove(E x) throws ElementNotFoundException {
+ // TODO:
+ }
+
+ @Override
+ public E findMin() throws EmptyPriorityQueueException {
+ if (isEmpty())
+ throw new EmptyPriorityQueueException();
+ return this.array.get(0);
+ }
+
+ @Override
+ public E deleteMin() throws EmptyPriorityQueueException {
+ E minItem = findMin();
+ E lastItem = this.array.get(--this.currentSize);
+ this.arraySet(0, lastItem);
+ this.percolateDown(0);
+ return minItem;
+ }
+
+ /**
+ * Creates a multi-lines string representing a sorted view of this binary heap.
+ *
+ * @return a string containing a sorted view this binary heap.
+ */
+ public String toStringSorted() {
+ return BinaryHeapFormatter.toStringSorted(this, -1);
+ }
+
+ /**
+ * Creates a multi-lines string representing a sorted view of this binary heap.
+ *
+ * @param maxElement Maximum number of elements to display. or {@code -1} to display
+ * all the elements.
+ * @return a string containing a sorted view this binary heap.
+ */
+ public String toStringSorted(int maxElement) {
+ return BinaryHeapFormatter.toStringSorted(this, maxElement);
+ }
+
+ /**
+ * Creates a multi-lines string representing a tree view of this binary heap.
+ *
+ * @return a string containing a tree view of this binary heap.
+ */
+ public String toStringTree() {
+ return BinaryHeapFormatter.toStringTree(this, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Creates a multi-lines string representing a tree view of this binary heap.
+ *
+ * @param maxDepth Maximum depth of the tree to display.
+ * @return a string containing a tree view of this binary heap.
+ */
+ public String toStringTree(int maxDepth) {
+ return BinaryHeapFormatter.toStringTree(this, maxDepth);
+ }
+
+ @Override
+ public String toString() {
+ return BinaryHeapFormatter.toStringTree(this, 8);
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinaryHeapFormatter.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinaryHeapFormatter.java
new file mode 100644
index 0000000..3ba4b86
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinaryHeapFormatter.java
@@ -0,0 +1,197 @@
+package org.insa.graphs.algorithm.utils;
+
+import java.util.ArrayList;
+
+public class BinaryHeapFormatter {
+
+ /**
+ * This class is used by {@link #toStringTree}, and simply contains three string
+ * accumulating. This is an immutable class.
+ */
+ private static class Context {
+
+ // Output text:
+ public final String acu;
+
+ // Margin to get back exactly under the current position:
+ public final String margin;
+
+ // Last margin used for the last child of a node. The markers are different:
+ public final String lastmargin;
+
+ /**
+ * Creaet a new {@code Context}.
+ *
+ * @param acu The accumulated string.
+ * @param margin The current margin.
+ * @param lastMargin The last margin used.
+ */
+ public Context(String acu, String margin, String lastMargin) {
+ this.acu = acu;
+ this.margin = margin;
+ this.lastmargin = lastMargin;
+ }
+
+ /**
+ * Creates a new context by appending newlines to this context.
+ *
+ * @param n Number of newlines to append.
+ * @return a new context with {@code n} newlines appended.
+ */
+ public Context appendNewlines(int n) {
+ if (n <= 0) {
+ return this;
+ }
+ else {
+ return (new Context(this.acu + "\n" + this.margin, this.margin,
+ this.lastmargin).appendNewlines(n - 1));
+ }
+ }
+
+ /**
+ * Creates a new context by appending the given string to this context.
+ *
+ * @param count Number of spaces to add to the margin, or {@code null} to use
+ * the length of the string.
+ * @param text String to append.
+ * @return a new context with {@code text} appended.
+ */
+ public Context appendText(Integer count, String text) {
+ int cnt = (count == null) ? text.length() : count;
+ final String spaces = new String(new char[cnt]).replace('\0', ' ');
+ return new Context(this.acu + text, this.margin + spaces,
+ this.lastmargin + spaces);
+ }
+
+ /**
+ * Creates a new context by appending a branch to this context.
+ *
+ * @param n Number of spaces to add to the margin, or {@code null} to use the
+ * length of the string.
+ * @param label Name of the branch.
+ * @return a new context with the branch appended.
+ */
+ public Context appendBranch(Integer count, String label) {
+ final Context ctxt = this.appendText(count, label);
+
+ if (count == null) {
+ return new Context(ctxt.acu + "_", ctxt.margin + "|",
+ ctxt.margin + " ");
+ }
+ else {
+ return new Context(ctxt.acu, ctxt.margin + "|", ctxt.margin + " ")
+ .appendNewlines(1);
+
+ }
+ }
+ }
+
+ /*
+ * Input : ready to write the current node at the current context position. Output :
+ * the last character of acu is the last character of the current node.
+ */
+ protected static > Context toStringLoop(BinaryHeap heap,
+ Context ctxt, int node, int max_depth) {
+
+ if (max_depth < 0) {
+ return ctxt.appendText(null, "...");
+ }
+ else {
+ E nodeval = heap.array.get(node);
+ String nodevals = nodeval.toString();
+
+ ArrayList childs = new ArrayList();
+ // Add childs
+ int index_left = heap.indexLeft(node);
+ int index_right = index_left + 1;
+
+ if (index_left < heap.size()) {
+ childs.add(index_left);
+ }
+ if (index_right < heap.size()) {
+ childs.add(index_right);
+ }
+
+ Context ctxt2 = childs.isEmpty() ? ctxt.appendText(null, nodevals)
+ : ctxt.appendBranch(1, nodevals);
+
+ for (int ch = 0; ch < childs.size(); ch++) {
+ boolean is_last = (ch == childs.size() - 1);
+ int child = childs.get(ch);
+
+ if (is_last) {
+ Context ctxt3 =
+ new Context(ctxt2.acu, ctxt2.lastmargin, ctxt2.lastmargin);
+ ctxt2 = new Context(toStringLoop(heap,
+ ctxt3.appendText(null, "___"), child, max_depth - 1).acu,
+ ctxt2.margin, ctxt2.lastmargin);
+ }
+ else {
+ ctxt2 = new Context(toStringLoop(heap,
+ ctxt2.appendText(null, "___"), child, max_depth - 1).acu,
+ ctxt2.margin, ctxt2.lastmargin).appendNewlines(2);
+ }
+ }
+
+ return ctxt2;
+ }
+ }
+
+ /**
+ * Creates a multi-lines string representing a tree view of the given binary heap.
+ *
+ * @param heap The binary heap to display.
+ * @param maxDepth Maximum depth of the tree to display.
+ * @return a string containing a tree view of the given binary heap.
+ */
+ public static > String toStringTree(BinaryHeap heap,
+ int maxDepth) {
+ final Context init_context = new Context(" ", " ", " ");
+ final Context result = toStringLoop(heap, init_context, 0, maxDepth);
+ return result.acu;
+ }
+
+ /**
+ * Creates a multi-lines string representing a sorted view of the given binary heap.
+ *
+ * @param heap The binary heap to display.
+ * @param max_elements Maximum number of elements to display. or {@code -1} to
+ * display all the elements.
+ * @return a string containing a sorted view the given binary heap.
+ */
+ public static > String toStringSorted(BinaryHeap heap,
+ int max_elements) {
+ String result = "";
+ final BinaryHeap copy = new BinaryHeap(heap);
+
+ final String truncate;
+ if (max_elements < 0 || max_elements >= heap.size()) {
+ truncate = "";
+ }
+ else {
+ truncate = ", only " + max_elements + " elements are shown";
+ }
+
+ result += "======== Sorted HEAP (size = " + heap.size() + truncate
+ + ") ========\n\n";
+
+ while (!copy.isEmpty() && max_elements-- != 0) {
+ result += copy.deleteMin() + "\n";
+ }
+
+ result += "\n-------- End of heap --------";
+
+ return result;
+ }
+
+ public static void main(String[] args) {
+ final BinaryHeap heap = new BinaryHeap();
+
+ for (int i = 0; i < 12; i++) {
+ heap.insert(i);
+ }
+
+ System.out.println(heap.toStringSorted(-1));
+ System.out.println(heap.toStringTree(6));
+ }
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinarySearchTree.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinarySearchTree.java
new file mode 100644
index 0000000..1aa3284
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinarySearchTree.java
@@ -0,0 +1,93 @@
+package org.insa.graphs.algorithm.utils;
+
+import java.util.*;
+
+public class BinarySearchTree> implements PriorityQueue {
+
+ // Underlying implementation
+
+ // Elements, sorted by their value
+ private SortedSet sortedSet;
+
+ // Elements, by their hashcode.
+ private HashSet elems;
+
+ /**
+ * Create a new empty binary search tree.
+ */
+ public BinarySearchTree() {
+ this.sortedSet = new TreeSet<>();
+ this.elems = new HashSet<>();
+ }
+
+ /**
+ * Create a copy of the given binary search tree.
+ *
+ * @param bst Binary search tree to copy.
+ */
+ public BinarySearchTree(BinarySearchTree bst) {
+ this.sortedSet = new TreeSet<>(bst.sortedSet);
+ this.elems = new HashSet<>(bst.elems);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return this.sortedSet.isEmpty();
+ }
+
+ @Override
+ public int size() {
+ return this.sortedSet.size();
+ }
+
+ @Override
+ public void insert(E x) {
+ this.sortedSet.add(x);
+ this.elems.add(x);
+ }
+
+ @Override
+ public void remove(E x) throws ElementNotFoundException {
+
+ if (this.elems.contains(x)) {
+ // x is known to be here.
+
+ boolean removed = this.sortedSet.remove(x) ;
+ this.elems.remove(x) ;
+
+ if (!removed) {
+ // The element x was not found in the sorted tree, because its value has changed.
+ // However, we know it is here.
+
+ // This forces the sorted set to be reorganized
+ SortedSet ts = this.sortedSet ;
+ this.sortedSet = new TreeSet<>() ;
+ for (E y : ts) {
+ this.sortedSet.add(y) ;
+ }
+
+ removed = this.sortedSet.remove(x) ;
+ assert(removed) ;
+ }
+ }
+ else {
+ 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;
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/ElementNotFoundException.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/ElementNotFoundException.java
new file mode 100644
index 0000000..fad7f9d
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/ElementNotFoundException.java
@@ -0,0 +1,32 @@
+package org.insa.graphs.algorithm.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;
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/EmptyPriorityQueueException.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/EmptyPriorityQueueException.java
new file mode 100644
index 0000000..d45aa2e
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/EmptyPriorityQueueException.java
@@ -0,0 +1,15 @@
+package org.insa.graphs.algorithm.utils;
+
+public class EmptyPriorityQueueException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ *
+ */
+ public EmptyPriorityQueueException() {}
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/PriorityQueue.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/PriorityQueue.java
new file mode 100644
index 0000000..c7eb60b
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/PriorityQueue.java
@@ -0,0 +1,71 @@
+package org.insa.graphs.algorithm.utils;
+
+/**
+ * Interface representing a basic priority queue. Implementation should enforce the
+ * required complexity of each method.
+ */
+public interface PriorityQueue> {
+
+ /**
+ * Check if the priority queue is empty.
+ *
+ * Complexity:O(1)
+ *
+ *
+ * @return true if the queue is empty, false otherwise.
+ */
+ public boolean isEmpty();
+
+ /**
+ * Get the number of elements in this queue.
+ *
+ * Complexity:O(1)
+ *
+ *
+ * @return Current size (number of elements) of this queue.
+ */
+ public int size();
+
+ /**
+ * Insert the given element into the queue.
+ *
+ * Complexity:O(log n)
+ *
+ *
+ * @param x Item to insert.
+ */
+ public void insert(E x);
+
+ /**
+ * Remove the given element from the priority queue.
+ *
+ * Complexity:O(log n)
+ *
+ *
+ * @param x Item to remove.
+ */
+ public void remove(E x) throws ElementNotFoundException;
+
+ /**
+ * Retrieve (but not remove) the smallest item in the queue.
+ *
+ * Complexity:O(1)
+ *
+ *
+ * @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.
+ *
+ * Complexity:O(log n)
+ *
+ *
+ * @return The smallest item in the queue.
+ * @throws EmptyPriorityQueueException if this queue is empty.
+ */
+ public E deleteMin() throws EmptyPriorityQueueException;
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentObserver.java
new file mode 100644
index 0000000..e47dbcb
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentObserver.java
@@ -0,0 +1,30 @@
+package org.insa.graphs.algorithm.weakconnectivity;
+
+import java.util.ArrayList;
+
+import org.insa.graphs.model.Node;
+
+public interface WeaklyConnectedComponentObserver {
+
+ /**
+ * Notify that the algorithm is entering a new component.
+ *
+ * @param curNode Starting node for the component.
+ */
+ public void notifyStartComponent(Node curNode);
+
+ /**
+ * Notify that a new node has been found for the current component.
+ *
+ * @param node New node found for the current component.
+ */
+ public void notifyNewNodeInComponent(Node node);
+
+ /**
+ * Notify that the algorithm has computed a new component.
+ *
+ * @param nodes List of nodes in the component.
+ */
+ public void notifyEndComponent(ArrayList nodes);
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentTextObserver.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentTextObserver.java
new file mode 100644
index 0000000..862ebc7
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentTextObserver.java
@@ -0,0 +1,37 @@
+package org.insa.graphs.algorithm.weakconnectivity;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+
+import org.insa.graphs.model.Node;
+
+public class WeaklyConnectedComponentTextObserver
+ implements WeaklyConnectedComponentObserver {
+
+ // Number of the current component.
+ private int numComponent = 1;
+
+ // Output stream
+ PrintStream stream;
+
+ public WeaklyConnectedComponentTextObserver(PrintStream stream) {
+ this.stream = stream;
+ }
+
+ @Override
+ public void notifyStartComponent(Node curNode) {
+ stream.print("Entering component #" + numComponent + " from node #"
+ + curNode.getId() + "... ");
+ }
+
+ @Override
+ public void notifyNewNodeInComponent(Node node) {}
+
+ @Override
+ public void notifyEndComponent(ArrayList nodes) {
+ stream.println(nodes.size() + " nodes found.");
+ stream.flush();
+ numComponent += 1;
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsAlgorithm.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsAlgorithm.java
new file mode 100644
index 0000000..74cc623
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsAlgorithm.java
@@ -0,0 +1,158 @@
+package org.insa.graphs.algorithm.weakconnectivity;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Queue;
+
+import org.insa.graphs.algorithm.AbstractAlgorithm;
+import org.insa.graphs.algorithm.AbstractSolution.Status;
+import org.insa.graphs.model.Arc;
+import org.insa.graphs.model.Graph;
+import org.insa.graphs.model.Node;
+
+public class WeaklyConnectedComponentsAlgorithm
+ extends AbstractAlgorithm {
+
+ /**
+ * @param data Input data for this algorithm.
+ */
+ public WeaklyConnectedComponentsAlgorithm(WeaklyConnectedComponentsData data) {
+ super(data);
+ }
+
+ @Override
+ public WeaklyConnectedComponentsSolution run() {
+ return (WeaklyConnectedComponentsSolution) super.run();
+ }
+
+ @Override
+ public WeaklyConnectedComponentsData getInputData() {
+ return (WeaklyConnectedComponentsData) super.getInputData();
+ }
+
+ /**
+ * Notify all observers that the algorithm is entering a new component.
+ *
+ * @param curNode Starting node for the component.
+ */
+ protected void notifyStartComponent(Node curNode) {
+ for (WeaklyConnectedComponentObserver obs : getObservers()) {
+ obs.notifyStartComponent(curNode);
+ }
+ }
+
+ /**
+ * Notify all observers that a new node has been found for the current component.
+ *
+ * @param node New node found for the current component.
+ */
+ protected void notifyNewNodeInComponent(Node node) {
+ for (WeaklyConnectedComponentObserver obs : getObservers()) {
+ obs.notifyNewNodeInComponent(node);
+ }
+ }
+
+ /**
+ * Notify all observers that the algorithm has computed a new component.
+ *
+ * @param nodes List of nodes in the component.
+ */
+ protected void notifyEndComponent(ArrayList nodes) {
+ for (WeaklyConnectedComponentObserver obs : getObservers()) {
+ obs.notifyEndComponent(nodes);
+ }
+ }
+
+ /**
+ * @return An adjacency list for the undirected graph equivalent to the stored
+ * graph.
+ */
+ protected ArrayList> createUndirectedGraph() {
+ int nNodes = getInputData().getGraph().size();
+ ArrayList> res = new ArrayList>(nNodes);
+ for (int i = 0; i < nNodes; ++i) {
+ res.add(new HashSet());
+ }
+
+ for (Node node : getInputData().getGraph().getNodes()) {
+ for (Arc arc : node.getSuccessors()) {
+ res.get(node.getId()).add(arc.getDestination().getId());
+ if (arc.getRoadInformation().isOneWay()) {
+ res.get(arc.getDestination().getId()).add(node.getId());
+ }
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * Apply a breadth first search algorithm on the given undirected graph (adjacency
+ * list), starting at node cur, and marking nodes in marked.
+ *
+ * @param marked
+ * @param cur
+ * @return
+ */
+ protected ArrayList bfs(ArrayList> ugraph, boolean[] marked,
+ int cur) {
+ Graph graph = getInputData().getGraph();
+ ArrayList component = new ArrayList();
+
+ // Using a queue because we are doing a BFS
+ Queue queue = new LinkedList();
+
+ // Notify observers about the current component.
+ notifyStartComponent(graph.get(cur));
+
+ // Add original node and loop until the queue is empty.
+ queue.add(cur);
+ marked[cur] = true;
+ while (!queue.isEmpty()) {
+ Node node = graph.get(queue.remove());
+ component.add(node);
+
+ // Notify observers
+ notifyNewNodeInComponent(node);
+
+ for (Integer destId : ugraph.get(node.getId())) {
+ Node dest = graph.get(destId);
+ if (!marked[dest.getId()]) {
+ queue.add(destId);
+ marked[destId] = true;
+ }
+ }
+ }
+
+ notifyEndComponent(component);
+
+ return component;
+ }
+
+ @Override
+ protected WeaklyConnectedComponentsSolution doRun() {
+
+ Graph graph = getInputData().getGraph();
+ ArrayList> ugraph = createUndirectedGraph();
+ boolean[] marked = new boolean[graph.size()];
+ Arrays.fill(marked, false);
+
+ ArrayList> components = new ArrayList>();
+
+ // perform algorithm
+ int cur = 0;
+ while (cur < marked.length) {
+ // Apply BFS
+ components.add(this.bfs(ugraph, marked, cur));
+
+ // Find next non-marked
+ for (; cur < marked.length && marked[cur]; ++cur);
+ }
+
+ return new WeaklyConnectedComponentsSolution(getInputData(), Status.OPTIMAL,
+ components);
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsData.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsData.java
new file mode 100644
index 0000000..553a40b
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsData.java
@@ -0,0 +1,20 @@
+package org.insa.graphs.algorithm.weakconnectivity;
+
+import org.insa.graphs.algorithm.AbstractInputData;
+import org.insa.graphs.model.Graph;
+
+public class WeaklyConnectedComponentsData extends AbstractInputData {
+
+ /**
+ * @param graph Graph for which components should be retrieved.
+ */
+ public WeaklyConnectedComponentsData(Graph graph) {
+ super(graph, null);
+ }
+
+ @Override
+ public String toString() {
+ return "Weakly-connected components from #0.";
+ }
+
+}
diff --git a/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsSolution.java b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsSolution.java
new file mode 100644
index 0000000..ac422f4
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsSolution.java
@@ -0,0 +1,58 @@
+package org.insa.graphs.algorithm.weakconnectivity;
+
+import java.util.ArrayList;
+
+import org.insa.graphs.algorithm.AbstractSolution;
+import org.insa.graphs.model.Node;
+
+public class WeaklyConnectedComponentsSolution extends AbstractSolution {
+
+ // Components
+ private ArrayList> components;
+
+ protected WeaklyConnectedComponentsSolution(WeaklyConnectedComponentsData data) {
+ super(data);
+ }
+
+ protected WeaklyConnectedComponentsSolution(WeaklyConnectedComponentsData data,
+ Status status, ArrayList> components) {
+ super(data, status);
+ this.components = components;
+ }
+
+ @Override
+ public WeaklyConnectedComponentsData getInputData() {
+ return (WeaklyConnectedComponentsData) super.getInputData();
+ }
+
+ /**
+ * @return Components of the solution, if any.
+ */
+ public ArrayList> getComponents() {
+ return components;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ int nIsolated = 0;
+ int nGt10 = 0;
+ for (ArrayList component : components) {
+ if (component.size() == 1) {
+ nIsolated += 1;
+ }
+ else if (component.size() > 10) {
+ nGt10 += 1;
+ }
+ }
+ return "Found " + components.size() + " components (" + nGt10
+ + " with more than 10 nodes, " + nIsolated + " isolated nodes) in "
+ + getSolvingTime().getSeconds() + " seconds.";
+
+ }
+
+}
diff --git a/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/BinaryHeapTest.java b/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/BinaryHeapTest.java
new file mode 100644
index 0000000..ba9b9ed
--- /dev/null
+++ b/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/BinaryHeapTest.java
@@ -0,0 +1,16 @@
+package org.insa.graphs.algorithm.utils;
+
+public class BinaryHeapTest extends PriorityQueueTest {
+
+ @Override
+ public PriorityQueue createQueue() {
+ return new BinaryHeap<>();
+ }
+
+ @Override
+ public PriorityQueue createQueue(
+ PriorityQueue queue) {
+ return new BinaryHeap<>((BinaryHeap) queue);
+ }
+
+}
diff --git a/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/BinarySearchTreeTest.java b/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/BinarySearchTreeTest.java
new file mode 100644
index 0000000..102e440
--- /dev/null
+++ b/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/BinarySearchTreeTest.java
@@ -0,0 +1,16 @@
+package org.insa.graphs.algorithm.utils;
+
+public class BinarySearchTreeTest extends PriorityQueueTest {
+
+ @Override
+ public PriorityQueue createQueue() {
+ return new BinarySearchTree<>();
+ }
+
+ @Override
+ public PriorityQueue createQueue(
+ PriorityQueue queue) {
+ return new BinarySearchTree<>((BinarySearchTree) queue);
+ }
+
+}
diff --git a/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/PriorityQueueTest.java b/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/PriorityQueueTest.java
new file mode 100644
index 0000000..aca7b79
--- /dev/null
+++ b/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/PriorityQueueTest.java
@@ -0,0 +1,332 @@
+package org.insa.graphs.algorithm.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public abstract class PriorityQueueTest {
+
+ /**
+ * Needs to be implemented by child class to actually provide priority queue
+ * implementation.
+ *
+ * @return A new instance of a PriorityQueue implementation.
+ */
+ public abstract PriorityQueue createQueue();
+
+ /**
+ * Needs to be implemented by child class to actually provide priority queue
+ * implementation.
+ *
+ * @param queue Queue to copy.
+ * @return Copy of the given queue.
+ */
+ public abstract PriorityQueue createQueue(
+ PriorityQueue queue);
+
+ protected static class MutableInteger implements Comparable {
+
+ // Actual value
+ private int value ;
+
+ // Unique identifier, used to get a hashcode that does not depend on the value (which may change)
+ private int id ;
+
+ private static int counter = 1000 ;
+
+ public MutableInteger(int value) {
+ this.value = value ;
+ this.id = counter++ ;
+ }
+
+ /**
+ * @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) {
+ if (this.id == other.id) return 0 ;
+ else return Integer.compare(this.value, other.value);
+ }
+
+ @Override
+ public String toString() {
+ return "" + this.get() + " [id:" + this.id + "]";
+ }
+
+ };
+
+ protected static class TestParameters> {
+
+ // Data to insert
+ public final E[] data;
+ public final int[] deleteOrder;
+
+ // data contains values
+ // deleteOrder contains indexes in data[]
+ public TestParameters(E[] data, int[] deleteOrder) {
+ this.data = data;
+ this.deleteOrder = deleteOrder;
+ }
+
+ };
+
+ /**
+ * Set of parameters.
+ */
+ @Parameters
+ public static Collection