diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b24c5a0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,62 @@
+# Graph & Algorithm project — INSA Toulouse
+
+## How to start?
+
+You will not be able to use this repository to save your work, you need to copy / import / fork it to
+your favorite Git platform.
+
+### Importing to [Github](https://github.com), [Bitbucket](https://bitbucket.org) or [Gitlab](https://gitlab.com):
+
+You first need to register and then log in to the platform you want. The steps to import the project are detailed below:
+
+#### Github
+
+1. In the upper-right corner of any page, click the **"+"** icon, then click **Import repository**, or go to [https://github.com/new/import](https://github.com/new/import).
+2. Paste the following URL in the first input:
+ [https://gitea.typename.fr/INSA/be-graphes.git](https://gitea.typename.fr/INSA/be-graphes.git)
+3. Choose the name you want for the repository.
+4. Click *Begin import*.
+5. Wait for completion... Done!
+
+#### Bitbucket
+
+1. On the left panel of any page, click the **"+"** icon, then **Repository**, and then **Import**, or directly go to [https://bitbucket.org/repo/import](https://bitbucket.org/repo/import).
+2. Paste the following URL in the first input (select Git as source if not already selected):
+ [https://gitea.typename.fr/INSA/be-graphes.git](https://gitea.typename.fr/INSA/be-graphes.git)
+3. Choose the name you want for repository, and select Git as the *Version control system*.
+4. Click *Import repository*.
+5. Wait for completion... Done!
+
+#### Gitlab
+
+1. In the upper-right corner of any page, click the **"+"** icon, then **New project**, or directly go to [https://gitlab.com/projects/new](https://gitlab.com/projects/new).
+2. Select the **Import project** tab, and then click **Repo by URL** (right-most option).
+3. Paste the following URL in the first input:
+ [https://gitea.typename.fr/INSA/be-graphes.git](https://gitea.typename.fr/INSA/be-graphes.git)
+4. Choose the name you want for the repository.
+5. Click *Create project*.
+6. Wait for completion... Done!
+
+### Importing to another repository provider *[not recommended]*:
+
+1. Create a new **empty** repository (no README, no LICENSE) on your provider. Let's assume the URL of your repository is `$URL_REPOSITORY`.
+2. Clone this repository somewhere:
+
+ ```bash
+ git clone https://gitea.typename.fr/INSA/be-graphes.git
+ ```
+
+3. Go inside the newly cloned repository and update the **remote**:
+
+ ```bash
+ cd be-graphes
+ git remote set-url origin $URL_REPOSITORY
+ ```
+
+4. Push to your repository:
+
+ ```bash
+ push -u origin master
+ ```
+
+Another way is to do a bare clone and then mirror it to your repository: [https://help.github.com/articles/importing-a-git-repository-using-the-command-line/](https://help.github.com/articles/importing-a-git-repository-using-the-command-line/)
\ No newline at end of file
diff --git a/be-graphes-algos/pom.xml b/be-graphes-algos/pom.xml
new file mode 100644
index 0000000..d66075a
--- /dev/null
+++ b/be-graphes-algos/pom.xml
@@ -0,0 +1,25 @@
+
+
+ 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..10fe8c4
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractAlgorithm.java
@@ -0,0 +1,87 @@
+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..3ef1ee0
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractInputData.java
@@ -0,0 +1,101 @@
+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.
+ */
+
+ /* Apparently, getMaximumSpeed is never initialized in arcInspectors.
+ * => Do not use.
+ public int getMaximumSpeed() {
+ return this.arcInspector.getMaximumSpeed();
+ }
+ */
+
+ /**
+ * 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..0d271eb
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AbstractSolution.java
@@ -0,0 +1,88 @@
+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..4dde531
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/AlgorithmFactory.java
@@ -0,0 +1,128 @@
+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..57010bd
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/ArcInspector.java
@@ -0,0 +1,43 @@
+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..ab42c7d
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/ArcInspectorFactory.java
@@ -0,0 +1,189 @@
+package org.insa.graphs.algorithm;
+
+import java.util.ArrayList;
+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 {
+
+ /**
+ * @return List of all arc filters in this factory.
+ */
+ public static List getAllFilters() {
+ List 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 true;
+ }
+
+ @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, all roads allowed";
+ }
+ });
+
+ 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() {
+
+ 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;
+ }
+ });
+
+ // Add your own filters here (do not forget to implement toString()
+ // to get an understandable output!):
+
+ return filters;
+ }
+
+}
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..a895e38
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/carpooling/CarPoolingAlgorithm.java
@@ -0,0 +1,24 @@
+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..191e927
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/packageswitch/PackageSwitchAlgorithm.java
@@ -0,0 +1,29 @@
+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..42986aa
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/BellmanFordAlgorithm.java
@@ -0,0 +1,100 @@
+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..bacb8e3
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java
@@ -0,0 +1,17 @@
+package org.insa.graphs.algorithm.shortestpath;
+
+public class DijkstraAlgorithm extends ShortestPathAlgorithm {
+
+ public DijkstraAlgorithm(ShortestPathData data) {
+ super(data);
+ }
+
+ @Override
+ protected ShortestPathSolution doRun() {
+ final ShortestPathData data = getInputData();
+ ShortestPathSolution solution = null;
+ // TODO:
+ 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..005e40c
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathAlgorithm.java
@@ -0,0 +1,69 @@
+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..7b3d014
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathData.java
@@ -0,0 +1,47 @@
+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..d56d2dc
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathObserver.java
@@ -0,0 +1,37 @@
+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..9122ac4
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/ShortestPathSolution.java
@@ -0,0 +1,74 @@
+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..2c1a239
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinaryHeap.java
@@ -0,0 +1,205 @@
+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..861e1c3
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinaryHeapFormatter.java
@@ -0,0 +1,198 @@
+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..32dfbb1
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/BinarySearchTree.java
@@ -0,0 +1,64 @@
+package org.insa.graphs.algorithm.utils;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+public class BinarySearchTree> implements PriorityQueue {
+
+ // Underlying implementation
+ private final SortedSet 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 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;
+ }
+
+}
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..3fb2729
--- /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..bf09c5d
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/EmptyPriorityQueueException.java
@@ -0,0 +1,16 @@
+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..104f79e
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/utils/PriorityQueue.java
@@ -0,0 +1,81 @@
+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..e7b0a5a
--- /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..1a725c7
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentTextObserver.java
@@ -0,0 +1,36 @@
+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..42462bb
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsAlgorithm.java
@@ -0,0 +1,159 @@
+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..a0b2d4a
--- /dev/null
+++ b/be-graphes-algos/src/main/java/org/insa/graphs/algorithm/weakconnectivity/WeaklyConnectedComponentsSolution.java
@@ -0,0 +1,57 @@
+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..df91636
--- /dev/null
+++ b/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/BinaryHeapTest.java
@@ -0,0 +1,15 @@
+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..803846d
--- /dev/null
+++ b/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/BinarySearchTreeTest.java
@@ -0,0 +1,15 @@
+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..c796598
--- /dev/null
+++ b/be-graphes-algos/src/test/java/org/insa/graphs/algorithm/utils/PriorityQueueTest.java
@@ -0,0 +1,320 @@
+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;
+
+ 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);
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toString(get());
+ }
+
+ };
+
+ protected static class TestParameters> {
+
+ // Data to insert
+ public final E[] data;
+ public final int[] deleteOrder;
+
+ public TestParameters(E[] data, int[] deleteOrder) {
+ this.data = data;
+ this.deleteOrder = deleteOrder;
+ }
+
+ };
+
+ /**
+ * Set of parameters.
+ *
+ */
+ @Parameters
+ public static Collection