diff --git a/.gitignore b/.gitignore
index c2b7620..408ed1e 100644
Binary files a/.gitignore and b/.gitignore differ
diff --git a/src/berack96/sim/util/graph/Graph.java b/src/berack96/sim/util/graph/Graph.java
index 44e2747..5ae7afa 100644
--- a/src/berack96/sim/util/graph/Graph.java
+++ b/src/berack96/sim/util/graph/Graph.java
@@ -1,518 +1,546 @@
-package berack96.sim.util.graph;
-
-import berack96.sim.util.graph.visit.VisitInfo;
-import berack96.sim.util.graph.visit.VisitStrategy;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-
-/**
- * An interface for the graphs.
- * This interface is used for the graphs with Directed edges.
- * A directed edge between V1 and V2 is an edge that has V1 as source and V2 as destination.
- *
- * @param The Object that represent a vertex
- * @param The Object that represent the edge (more specifically the weight of the edge)
- * @author Berack96
- */
-public interface Graph extends Iterable {
-
- String NOT_DAG = "The graph is not a DAG";
- String NOT_CONNECTED = "The source vertex doesn't have a path that reach the destination";
- String PARAM_NULL = "The parameter must not be null";
- String VERTEX_NOT_CONTAINED = "The vertex must be contained in the graph";
-
- /**
- * Tells if the graph has some cycle.
- * A cycle is detected if visiting the graph G starting from V1 (that is any of the vertex of G),
- * the visit can return to V1 in any point.
- *
- * @return true if has cycle, false otherwise
- */
- boolean isCyclic();
-
- /**
- * Tells if the graph has the property of DAG (Directed Acyclic Graph).
- * A graph is a DAG only if absent of any cycle. ( see {@link #isCyclic()} )
- *
- * @return true if is a DAG, false otherwise
- */
- boolean isDAG();
-
- /**
- * Get an instance of the vertex linked with this graph.
- * For more info see {@link Vertex}
- *
- * @param vertex the vertex
- * @return a vertex
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- Vertex getVertex(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Add the vertex to the graph. If it's already in the graph it will be replaced.
- * Of course the vertex added will have no edge to any other vertex nor form any other vertex.
- *
- * @param vertex the vertex to add
- * @throws NullPointerException if the vertex is null
- */
- void addVertex(V vertex) throws NullPointerException;
-
- /**
- * Add the specified vertex to the graph only if the graph doesn't contains it.
- * The graph contains a vertex only if the method {@link #contains(V)} returns true.
- *
- * @param vertex the vertex to add
- * @return true if the vertex is added, false if the graph contains the vertex and therefore the new one is not added
- * @throws NullPointerException if the vertex is null
- */
- boolean addVertexIfAbsent(V vertex) throws NullPointerException;
-
- /**
- * Add all the vertices contained in the collection to the graph.
- * If a vertex is contained in the collection and in the graph is ignored and it will not be replaced.
- * Null vertices will be ignored and they will not be added to the graph.
- *
- * @param vertices a collection of the vertices to add
- * @throws NullPointerException if the set is null
- */
- void addAllVertices(Collection vertices) throws NullPointerException;
-
- /**
- * Remove the selected vertex from the graph.
- * After this method's call the vertex will be no longer present in the graph, and nether all his edges.
- *
- * @param vertex the vertex to remove
- * @throws NullPointerException if the vertex is null
- */
- void removeVertex(V vertex) throws IllegalArgumentException;
-
- /**
- * Remove all the vertex contained in the graph.
- * After this method's call the graph will be empty; no vertices nor edges.
- */
- void removeAllVertex();
-
- /**
- * Check if the vertex passed is contained in the graph or not.
- * The vertex V1 is contained in the graph G, if and only if:
- * exist V2 in G such that V2.equals(V1)
- *
- * @param vertex the vertex to check
- * @return true if the vertex is contained, false otherwise
- * @throws NullPointerException if the vertex is null
- */
- boolean contains(V vertex) throws NullPointerException;
-
- /**
- * Add to the specified vertex the mark passed.
- * A vertex can have multiple marker.
- *
- * @param vertex the vertex to mark
- * @param mark the mark to add
- * @throws NullPointerException if one of the param is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Remove the selected mark from the vertex.
- *
- * @param vertex the vertex where remove the mark
- * @param mark the mark to remove
- * @throws NullPointerException if a param is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Unmark the vertex selected.
- * After this call the vertex will not have any marked object to himself.
- *
- * @param vertex the vertex
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- void unMark(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Get all the marker of this vertex.
- * If the vertex doesn't have any mark, then it will return an empty set.
- * Note: this set is linked to the marked vertex, so any changes to the set returned are reflected to the graph.
- *
- * @param vertex the vertex
- * @return all the mark to the vertex or an empty collection if none
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- Collection getMarks(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Remove the selected mark from all the vertices
- *
- * @param mark the mark to remove
- * @throws NullPointerException if the mark is null
- */
- void unMarkAll(Object mark) throws NullPointerException;
-
- /**
- * Remove all the marker to all the vertex.
- * After this call the {@link #getMarks(Object)} applied to any vertex will return an empty set
- */
- void unMarkAll();
-
- /**
- * Add an edge between the two vertex.
- * The edge will be created from the vertex V1 and the vertex V2
- * This method will overwrite any existing edge between the two vertex.
- * If there was a previous edge then it is returned
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @param weight the weight of the edge
- * @return null or the previous weight of the edge if there was already one
- * @throws NullPointerException if one of the parameter is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- W addEdge(V vertex1, V vertex2, W weight) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Add an edge between the two vertex.
- * The edge will be created from the vertex source of the edge and the vertex destination of it
- * This method will overwrite any existing edge between the two vertex.
- * If there was a previous edge then it is returned
- *
- * @param edge the edge to add
- * @return null or the previous weight of the edge if there was already one
- * @throws NullPointerException if one of the parameter is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- W addEdge(Edge edge) throws NullPointerException, IllegalArgumentException;
-
- /**
- * This particular function add an edge to the graph.
- * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
- * The edge will be created from the vertex V1 and the vertex V2
- * This method will overwrite any existing edge between the two vertex.
- * If there was a previous edge then it is returned
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @param weight the weight of the edge
- * @return null or the previous weight of the edge if there was already one
- * @throws NullPointerException if one of the parameter is null
- */
- W addEdgeAndVertices(V vertex1, V vertex2, W weight) throws NullPointerException;
-
- /**
- * This particular function add an edge to the graph.
- * If one of the two, or both vertices of the edge aren't contained in the graph, then the vertices will be added.
- * The edge will be created from the vertex source of the edge and the vertex destination of it
- * This method will overwrite any existing edge between the two vertex.
- * If there was a previous edge then it is returned
- *
- * @param edge the edge to add
- * @return null or the previous weight of the edge if there was already one
- * @throws NullPointerException if one of the parameter is null
- */
- W addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Add all the edges of the collection to the graph.
- * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
- * Any null edges will be ignored.
- * This method will overwrite any existing edge between the two vertex.
- *
- * @param edges the edges to add
- * @throws NullPointerException if the set is null
- */
- void addAllEdges(Collection> edges) throws NullPointerException;
-
- /**
- * Get the weight of the selected edge.
- * If the edge doesn't exist, then null is returned
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @return the weight previously set, or null if the edge doesn't exist
- * @throws NullPointerException if one of the parameters is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- W getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Remove the edge between the two vertex.
- * If the edge doesn't exist, then this call does nothing.
- * After this method's call it will be no longer possible to travel from V1 to V2, nether from V2 to V1.
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @throws NullPointerException if one of the parameters is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Remove all the edges that goes in the vertex.
- * After this method's call it will be no longer possible travel to this vertex.
- *
- * @param vertex a vertex of the graph
- * @throws NullPointerException if one of the parameters is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- void removeAllInEdge(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Remove all the edges that start from this vertex.
- * After this method's call it will be no longer possible travel to any vertex from this one.
- *
- * @param vertex a vertex of the graph
- * @throws NullPointerException if one of the parameters is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- void removeAllOutEdge(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Remove all edges form a particular vertex of the graph.
- * After this method's call the selected vertex will have 0 edges.
- * It will be no longer possible to reach this vertex from any other vertex, and vice versa.
- *
- * @param vertex a vertex of the graph
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Remove all the edges of the graph.
- * After this method's call the graph will have only vertices, and no edge.
- */
- void removeAllEdge();
-
- /**
- * Check if the edge between the two vertex passed is contained in the graph or not.
- * An edge between V1 and V2 is contained in the graph if and only if i can travel from V1 to V2.
- * If one of the two vertices is not contained in the graph, then even the edge isn't
- *
- * @param vertex1 a vertex of the graph
- * @param vertex2 a vertex of the graph
- * @return true if the edge is contained, false otherwise
- * @throws NullPointerException if one of the parameters is null
- */
- boolean containsEdge(V vertex1, V vertex2) throws NullPointerException;
-
- /**
- * Get all the vertices in the graph.
- * If the graph doesn't contains vertices, it'll return an empty collection.
- * Note that this collection is completely different the object used for the vertices, so any modification to this collection will not change the graph.
- *
- * @return an array that include all the vertices
- */
- Collection vertices();
-
- /**
- * Get all the edges in the graph.
- * If the graph doesn't contains edges, it'll return an empty collection.
- * Note that this collection is completely different than the object used for the edges, so any modification to this collection will not change the graph.
- *
- * @return a collection that include all the edges
- */
- Collection> edges();
-
- /**
- * Retrieve all the edges of a particular vertex.
- * Note: the edges that are returned are the one that goes IN this vertex AND the edges that goes OUT of it.
- *
- * @param vertex a vertex of the graph
- * @return a collection of edges
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Retrieve all the edges of a particular vertex.
- * Note: the edges that are returned are the one that have this vertex as destination and another as source.
- *
- * @param vertex a vertex of the graph
- * @return a collection of edges
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Retrieve all the edges that goes OUT of a particular vertex.
- * Note: the edges that are returned are the one that have this vertex as source and another one as destination.
- *
- * @param vertex a vertex of the graph
- * @return a collection of edges
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Get all the vertices that are children of the vertex passed as parameter.
- * The vertices V(0-N) that are 'children' of a vertex V1, are all the vertices that have an edge
- * where V1 is the source of that edge.
- *
- * @param vertex the source vertex
- * @return an array of vertices
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Get all the vertices that have the vertex passed as their child.
- * Basically is the opposite of {@link #getChildren(Object)}
- *
- * @param vertex a vertex of the graph
- * @return an array of ancestors of the vertex
- * @throws NullPointerException if one of the parameters is null
- * @throws IllegalArgumentException if one of the vertex is not contained in the graph
- */
- Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Tells the degree of all the edges that goes to this vertex.
- * Basically, it'll count how many edge towards himself it have.
- *
- * @param vertex a vertex of the graph
- * @return the in degree of the vertex
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Tells the degree of all the edges that goes form this vertex to others.
- * Basically, it'll count how many edge towards any other vertex it have.
- *
- * @param vertex a vertex of the graph
- * @return the out degree of the vertex
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Tells the degree of a vertex.
- * The degree of a vertex is the quantity of edges that have.
- * Basically, it'll count how many edge it have.
- *
- * @param vertex a vertex of the graph
- * @return the degree of the vertex
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained in the graph
- */
- int degree(V vertex) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Tells how many vertices are in the graph.
- *
- * @return the number of vertices
- */
- int numberOfVertices();
-
- /**
- * Tells how many edges are in the graph.
- *
- * @return the number of edges
- */
- int numberOfEdges();
-
- /**
- * Visit the graph accordingly to the strategy that is passed.
- * This method visit the graph from the source to all the vertex that are reachable form the source.
- * Some strategy can accept a source vertex null, because they visit all the graph anyway.
- *
- * @param source the source vertex of the visit
- * @param strategy the algorithm for visiting the graph
- * @param visit the function to apply at each vertex
- * @throws NullPointerException if one of the parameter is null (except the consumer)
- * @throws IllegalArgumentException if the vertex is not in the graph
- */
- VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, IllegalArgumentException;
-
- /**
- * This method will create a new Graph that is the transposed version of the original.
- * At the end of this method the new graph will have all the edges inverted in orientation.
- * Example: if the graph G contains (V1, V2, V3) as vertex, and (V1->V2, V3->V2) as edges, the transpose graph G' will contain (V1, V2, V3) as vertex, and (V2->V1, V2->V3) as edges.
- *
- * @return a transposed graph of this instance
- */
- Graph transpose();
-
- /**
- * If the current graph is a DAG, it returns a topological sort of this graph.
- * A topological ordering of a graph is a linear ordering of its vertices such that for every directed edge (V1, V2) from vertex V1 to vertex V2, V2 comes before V1 in the ordering.
- *
- * @return an array containing the topological order of the vertices
- * @throws UnsupportedOperationException if the graph is not a DAG (see {@link #isDAG()})
- */
- List topologicalSort() throws UnsupportedOperationException;
-
- /**
- * The strongly connected components or diconnected components of an arbitrary directed graph form a partition into subgraphs that are themselves strongly connected.
- *
- * @return a collection containing the strongly connected components
- */
- Collection> stronglyConnectedComponents();
-
- /**
- * Get a sub-graph of the current one based on the maximum depth that is given.
- * If the depth is 1 then only the source and it's children will be in the sub-graph.
- * If the depth is 2 then only the source, it's children and it's children of it's children will be in the sub-graph.
- * And so on.
- * Of course the sub-graph will contain the edges that link the vertices, but only the one selected.
- *
- * @param source the source vertex
- * @param depth the maximum depth (must be a positive number, if >=0 a graph containing only the source is returned)
- * @return a sub-graph of the original
- * @throws NullPointerException if the vertex is null
- * @throws IllegalArgumentException if the vertex is not contained
- */
- Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException;
-
- /**
- * Get a sub-graph of the current one with only the vertex marked with the selected marker.
- * Each vertex will have all his edges, but only the ones with the destination marked with the same marker.
- * If the marker is null then the returning graph will have all the vertices that are not marked by any marker.
- * If the graph doesn't contain any vertex with that marker then an empty graph is returned.
- *
- * @param marker the marker
- * @return a sub-graph of the current graph
- */
- Graph subGraph(Object marker);
-
- /**
- * Get the minimum path from the source vertex to the destination vertex.
- * If the source vertex can't reach the destination, then an exception is thrown.
- *
- * @param source the vertex where to start
- * @param destination the destination chosen
- * @return an ordered list of edges from source to destination that represent the minimum path between the two vertices
- * @throws NullPointerException if one of the parameter is null (except the consumer)
- * @throws IllegalArgumentException if the vertex is not in the graph
- * @throws UnsupportedOperationException if from the source it's not possible to reach the destination
- */
- List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException;
-
- /**
- * Get the minimum path from the source vertex to all the possible reachable vertices.
- *
- * @param source the vertex where to start
- * @return a map containing all the possible reachable vertices from the source and the minimum path to reach them
- * @throws NullPointerException if one of the parameter is null (except the consumer)
- * @throws IllegalArgumentException if the vertex is not in the graph
- */
- Map>> distance(V source) throws NullPointerException, IllegalArgumentException;
-
- // TODO maybe -> STATIC saveOnFile(orString) INSTANCE loadFromFile(orString), but need JSON parser
- // TODO maybe, but i don't think so... STATIC DISTANCE V* -> V*
-}
+package berack96.sim.util.graph;
+
+import berack96.sim.util.graph.visit.VisitInfo;
+import berack96.sim.util.graph.visit.VisitStrategy;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+/**
+ * An interface for the graphs.
+ * This interface is used for the graphs with Directed edges.
+ * A directed edge between V1 and V2 is an edge that has V1 as source and V2 as destination.
+ *
+ * @param The Object that represent a vertex
+ * @param The Object that represent the edge (more specifically the weight of the edge)
+ * @author Berack96
+ */
+public interface Graph extends Iterable {
+
+ String NOT_DAG = "The graph is not a DAG";
+ String NOT_CONNECTED = "The source vertex doesn't have a path that reach the destination";
+ String PARAM_NULL = "The parameter must not be null";
+ String VERTEX_NOT_CONTAINED = "The vertex must be contained in the graph";
+
+ /**
+ * Tells if the graph has some cycle.
+ * A cycle is detected if visiting the graph G starting from V1 (that is any of the vertex of G),
+ * the visit can return to V1 in any point.
+ *
+ * @return true if has cycle, false otherwise
+ */
+ boolean isCyclic();
+
+ /**
+ * Tells if the graph has the property of DAG (Directed Acyclic Graph).
+ * A graph is a DAG only if absent of any cycle. ( see {@link #isCyclic()} )
+ *
+ * @return true if is a DAG, false otherwise
+ */
+ boolean isDAG();
+
+ /**
+ * Get an instance of the vertex linked with this graph.
+ * For more info see {@link Vertex}
+ *
+ * @param vertex the vertex
+ * @return a vertex
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ Vertex getVertex(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Add the vertex to the graph. If it's already in the graph it will be replaced.
+ * Of course the vertex added will have no edge to any other vertex nor form any other vertex.
+ *
+ * @param vertex the vertex to add
+ * @throws NullPointerException if the vertex is null
+ */
+ void addVertex(V vertex) throws NullPointerException;
+
+ /**
+ * Add the specified vertex to the graph only if the graph doesn't contains it.
+ * The graph contains a vertex only if the method {@link #contains(V)} returns true.
+ *
+ * @param vertex the vertex to add
+ * @return true if the vertex is added, false if the graph contains the vertex and therefore the new one is not added
+ * @throws NullPointerException if the vertex is null
+ */
+ boolean addVertexIfAbsent(V vertex) throws NullPointerException;
+
+ /**
+ * Add all the vertices contained in the collection to the graph.
+ * If a vertex is contained in the collection and in the graph is ignored and it will not be replaced.
+ * Null vertices will be ignored and they will not be added to the graph.
+ *
+ * @param vertices a collection of the vertices to add
+ * @throws NullPointerException if the set is null
+ */
+ void addAllVertices(Collection vertices) throws NullPointerException;
+
+ /**
+ * Remove the selected vertex from the graph.
+ * After this method's call the vertex will be no longer present in the graph, and nether all his edges.
+ *
+ * @param vertex the vertex to remove
+ * @throws NullPointerException if the vertex is null
+ */
+ void removeVertex(V vertex) throws IllegalArgumentException;
+
+ /**
+ * Remove all the vertex contained in the graph.
+ * After this method's call the graph will be empty; no vertices nor edges.
+ */
+ void removeAllVertex();
+
+ /**
+ * Check if the vertex passed is contained in the graph or not.
+ * The vertex V1 is contained in the graph G, if and only if:
+ * exist V2 in G such that V2.equals(V1)
+ *
+ * @param vertex the vertex to check
+ * @return true if the vertex is contained, false otherwise
+ * @throws NullPointerException if the vertex is null
+ */
+ boolean contains(V vertex) throws NullPointerException;
+
+ /**
+ * Add to the specified vertex the mark passed.
+ * A vertex can have multiple marker.
+ *
+ * @param vertex the vertex to mark
+ * @param mark the mark to add
+ * @throws NullPointerException if one of the param is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Remove the selected mark from the vertex.
+ *
+ * @param vertex the vertex where remove the mark
+ * @param mark the mark to remove
+ * @throws NullPointerException if a param is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Unmark the vertex selected.
+ * After this call the vertex will not have any marked object to himself.
+ *
+ * @param vertex the vertex
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ void unMark(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Get all the vertices that are marked with the specific mark passed.
+ * If there aren't vertices with that mark then it is returned an empty set.
+ * Note: depending on the implementation, modifying the returned collection
+ * could affect the graph behavior and the changes could be reflected to the graph.
+ *
+ * @param mark the mark
+ * @return all the vertices that are marked with that specific mark
+ * @throws NullPointerException if the mark is null
+ */
+ Collection getMarkedWith(Object mark) throws NullPointerException;
+
+ /**
+ * Get all the marker of this vertex.
+ * If the vertex doesn't have any mark, then it will return an empty set.
+ * Note: depending on the implementation, modifying the returned collection
+ * could affect the graph behavior and the changes could be reflected to the graph.
+ *
+ * @param vertex the vertex
+ * @return all the mark to the vertex or an empty collection if none
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ Collection getMarks(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Remove the selected mark from all the vertices
+ *
+ * @param mark the mark to remove
+ * @throws NullPointerException if the mark is null
+ */
+ void unMarkAll(Object mark) throws NullPointerException;
+
+ /**
+ * Remove all the marker to all the vertex.
+ * After this call the {@link #getMarks(Object)} applied to any vertex will return an empty set
+ */
+ void unMarkAll();
+
+ /**
+ * Add an edge between the two vertex.
+ * The edge will be created from the vertex V1 and the vertex V2
+ * This method will overwrite any existing edge between the two vertex.
+ * If there was a previous edge then it is returned
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @param weight the weight of the edge
+ * @return null or the previous weight of the edge if there was already one
+ * @throws NullPointerException if one of the parameter is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ W addEdge(V vertex1, V vertex2, W weight) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Add an edge between the two vertex.
+ * The edge will be created from the vertex source of the edge and the vertex destination of it
+ * This method will overwrite any existing edge between the two vertex.
+ * If there was a previous edge then it is returned
+ *
+ * @param edge the edge to add
+ * @return null or the previous weight of the edge if there was already one
+ * @throws NullPointerException if one of the parameter is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ W addEdge(Edge edge) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * This particular function add an edge to the graph.
+ * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
+ * The edge will be created from the vertex V1 and the vertex V2
+ * This method will overwrite any existing edge between the two vertex.
+ * If there was a previous edge then it is returned
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @param weight the weight of the edge
+ * @return null or the previous weight of the edge if there was already one
+ * @throws NullPointerException if one of the parameter is null
+ */
+ W addEdgeAndVertices(V vertex1, V vertex2, W weight) throws NullPointerException;
+
+ /**
+ * This particular function add an edge to the graph.
+ * If one of the two, or both vertices of the edge aren't contained in the graph, then the vertices will be added.
+ * The edge will be created from the vertex source of the edge and the vertex destination of it
+ * This method will overwrite any existing edge between the two vertex.
+ * If there was a previous edge then it is returned
+ *
+ * @param edge the edge to add
+ * @return null or the previous weight of the edge if there was already one
+ * @throws NullPointerException if one of the parameter is null
+ */
+ W addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Add all the edges of the collection to the graph.
+ * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
+ * Any null edges will be ignored.
+ * This method will overwrite any existing edge between the two vertex.
+ *
+ * @param edges the edges to add
+ * @throws NullPointerException if the set is null
+ */
+ void addAllEdges(Collection> edges) throws NullPointerException;
+
+ /**
+ * Get the weight of the selected edge.
+ * If the edge doesn't exist, then null is returned
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @return the weight previously set, or null if the edge doesn't exist
+ * @throws NullPointerException if one of the parameters is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ W getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Remove the edge between the two vertex.
+ * If the edge doesn't exist, then this call does nothing.
+ * After this method's call it will be no longer possible to travel from V1 to V2, nether from V2 to V1.
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @throws NullPointerException if one of the parameters is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Remove all the edges that goes in the vertex.
+ * After this method's call it will be no longer possible travel to this vertex.
+ *
+ * @param vertex a vertex of the graph
+ * @throws NullPointerException if one of the parameters is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ void removeAllInEdge(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Remove all the edges that start from this vertex.
+ * After this method's call it will be no longer possible travel to any vertex from this one.
+ *
+ * @param vertex a vertex of the graph
+ * @throws NullPointerException if one of the parameters is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ void removeAllOutEdge(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Remove all edges form a particular vertex of the graph.
+ * After this method's call the selected vertex will have 0 edges.
+ * It will be no longer possible to reach this vertex from any other vertex, and vice versa.
+ *
+ * @param vertex a vertex of the graph
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Remove all the edges of the graph.
+ * After this method's call the graph will have only vertices, and no edge.
+ */
+ void removeAllEdge();
+
+ /**
+ * Check if the edge between the two vertex passed is contained in the graph or not.
+ * An edge between V1 and V2 is contained in the graph if and only if i can travel from V1 to V2.
+ * If one of the two vertices is not contained in the graph, then even the edge isn't
+ *
+ * @param vertex1 a vertex of the graph
+ * @param vertex2 a vertex of the graph
+ * @return true if the edge is contained, false otherwise
+ * @throws NullPointerException if one of the parameters is null
+ */
+ boolean containsEdge(V vertex1, V vertex2) throws NullPointerException;
+
+ /**
+ * Get all the vertices in the graph.
+ * If the graph doesn't contains vertices, it'll return an empty collection.
+ * Note: depending on the implementation, modifying the returned collection
+ * could affect the graph behavior and the changes could be reflected to the graph.
+ *
+ * @return an array that include all the vertices
+ */
+ Collection vertices();
+
+ /**
+ * Get all the edges in the graph.
+ * If the graph doesn't contains edges, it'll return an empty collection.
+ * Note: depending on the implementation, modifying the returned collection
+ * could affect the graph behavior and the changes could be reflected to the graph.
+ *
+ * @return a collection that include all the edges
+ */
+ Collection> edges();
+
+ /**
+ * Retrieve all the edges of a particular vertex.
+ * Note: the edges that are returned are the one that goes IN this vertex AND the edges that goes OUT of it.
+ * Note2: depending on the implementation, modifying the returned collection
+ * could affect the graph behavior and the changes could be reflected to the graph.
+ *
+ * @param vertex a vertex of the graph
+ * @return a collection of edges
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Retrieve all the edges of a particular vertex.
+ * Note: the edges that are returned are the one that have this vertex as destination and another as source.
+ * Note2: depending on the implementation, modifying the returned collection
+ * could affect the graph behavior and the changes could be reflected to the graph.
+ *
+ * @param vertex a vertex of the graph
+ * @return a collection of edges
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Retrieve all the edges that goes OUT of a particular vertex.
+ * Note: the edges that are returned are the one that have this vertex as source and another one as destination.
+ * Note2: depending on the implementation, modifying the returned collection
+ * could affect the graph behavior and the changes could be reflected to the graph.
+ *
+ * @param vertex a vertex of the graph
+ * @return a collection of edges
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Get all the vertices that are children of the vertex passed as parameter.
+ * The vertices V(0-N) that are 'children' of a vertex V1, are all the vertices that have an edge
+ * where V1 is the source of that edge.
+ * Note: depending on the implementation, modifying the returned collection
+ * could affect the graph behavior and the changes could be reflected to the graph.
+ *
+ * @param vertex the source vertex
+ * @return an array of vertices
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Get all the vertices that have the vertex passed as their child.
+ * Basically is the opposite of {@link #getChildren(Object)}
+ * Note: depending on the implementation, modifying the returned collection
+ * could affect the graph behavior and the changes could be reflected to the graph.
+ *
+ * @param vertex a vertex of the graph
+ * @return an array of ancestors of the vertex
+ * @throws NullPointerException if one of the parameters is null
+ * @throws IllegalArgumentException if one of the vertex is not contained in the graph
+ */
+ Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Tells the degree of all the edges that goes to this vertex.
+ * Basically, it'll count how many edge towards himself it have.
+ *
+ * @param vertex a vertex of the graph
+ * @return the in degree of the vertex
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Tells the degree of all the edges that goes form this vertex to others.
+ * Basically, it'll count how many edge towards any other vertex it have.
+ *
+ * @param vertex a vertex of the graph
+ * @return the out degree of the vertex
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Tells the degree of a vertex.
+ * The degree of a vertex is the quantity of edges that have.
+ * Basically, it'll count how many edge it have.
+ *
+ * @param vertex a vertex of the graph
+ * @return the degree of the vertex
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained in the graph
+ */
+ int degree(V vertex) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Tells how many vertices are in the graph.
+ *
+ * @return the number of vertices
+ */
+ int numberOfVertices();
+
+ /**
+ * Tells how many edges are in the graph.
+ *
+ * @return the number of edges
+ */
+ int numberOfEdges();
+
+ /**
+ * Visit the graph accordingly to the strategy that is passed.
+ * This method visit the graph from the source to all the vertex that are reachable form the source.
+ * Some strategy can accept a source vertex null, because they visit all the graph anyway.
+ *
+ * @param source the source vertex of the visit
+ * @param strategy the algorithm for visiting the graph
+ * @param visit the function to apply at each vertex
+ * @throws NullPointerException if one of the parameter is null (except the consumer)
+ * @throws IllegalArgumentException if the vertex is not in the graph
+ */
+ VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * This method will create a new Graph that is the transposed version of the original.
+ * At the end of this method the new graph will have all the edges inverted in orientation.
+ * Example: if the graph G contains (V1, V2, V3) as vertex, and (V1->V2, V3->V2) as edges,
+ * the transpose graph G' will contain (V1, V2, V3) as vertex, and (V2->V1, V2->V3) as edges.
+ *
+ * @return a transposed graph of this instance
+ */
+ Graph transpose();
+
+ /**
+ * If the current graph is a DAG, it returns a topological sort of this graph.
+ * A topological ordering of a graph is a linear ordering of its vertices such that for
+ * every directed edge (V1, V2) from vertex V1 to vertex V2, V2 comes before V1 in the ordering.
+ *
+ * @return an array containing the topological order of the vertices
+ * @throws UnsupportedOperationException if the graph is not a DAG (see {@link #isDAG()})
+ */
+ List topologicalSort() throws UnsupportedOperationException;
+
+ /**
+ * The strongly connected components or disconnected components of an arbitrary directed graph
+ * form a partition into subgraphs that are themselves strongly connected.
+ *
+ * @return a collection containing the strongly connected components
+ */
+ Collection> stronglyConnectedComponents();
+
+ /**
+ * Get a sub-graph of the current one based on the maximum depth that is given.
+ * If the depth is 1 then only the source and it's children will be in the sub-graph.
+ * If the depth is 2 then only the source, it's children and it's children of it's children will be in the sub-graph.
+ * And so on.
+ * Of course the sub-graph will contain the edges that link the vertices, but only the one selected.
+ *
+ * @param source the source vertex
+ * @param depth the maximum depth (must be a positive number, if >=0 a graph containing only the source is returned)
+ * @return a sub-graph of the original
+ * @throws NullPointerException if the vertex is null
+ * @throws IllegalArgumentException if the vertex is not contained
+ */
+ Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException;
+
+ /**
+ * Get a sub-graph of the current one with only the vertex marked with the selected marker.
+ * Each vertex will have all his edges, but only the ones with the destination marked with the same marker.
+ * If the marker is null then the returning graph will have all the vertices that are not marked by any marker.
+ * If the graph doesn't contain any vertex with that marker then an empty graph is returned.
+ *
+ * @param marker the marker
+ * @return a sub-graph of the current graph
+ */
+ Graph subGraph(Object marker);
+
+ /**
+ * Get the minimum path from the source vertex to the destination vertex.
+ * If the source vertex can't reach the destination, then an exception is thrown.
+ *
+ * @param source the vertex where to start
+ * @param destination the destination chosen
+ * @return an ordered list of edges from source to destination that represent the minimum path between the two vertices
+ * @throws NullPointerException if one of the parameter is null (except the consumer)
+ * @throws IllegalArgumentException if the vertex is not in the graph
+ * @throws UnsupportedOperationException if from the source it's not possible to reach the destination
+ */
+ List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException;
+
+ /**
+ * Get the minimum path from the source vertex to all the possible reachable vertices.
+ *
+ * @param source the vertex where to start
+ * @return a map containing all the possible reachable vertices from the source and the minimum path to reach them
+ * @throws NullPointerException if one of the parameter is null (except the consumer)
+ * @throws IllegalArgumentException if the vertex is not in the graph
+ */
+ Map>> distance(V source) throws NullPointerException, IllegalArgumentException;
+
+ // TODO maybe -> STATIC saveOnFile(orString) INSTANCE loadFromFile(orString), but need JSON parser
+ // TODO maybe, but i don't think so... STATIC DISTANCE V* -> V*
+}
diff --git a/src/berack96/sim/util/graph/MapGraph.java b/src/berack96/sim/util/graph/MapGraph.java
index d13b04d..6e50cce 100644
--- a/src/berack96/sim/util/graph/MapGraph.java
+++ b/src/berack96/sim/util/graph/MapGraph.java
@@ -1,488 +1,500 @@
-package berack96.sim.util.graph;
-
-import berack96.sim.util.graph.visit.Dijkstra;
-import berack96.sim.util.graph.visit.Tarjan;
-import berack96.sim.util.graph.visit.VisitInfo;
-import berack96.sim.util.graph.visit.VisitStrategy;
-
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
-
-/**
- * Graph that uses HashMap for vertices and edges
- * More specifically it utilizes a Map containing all the vertices mapped to all their edges
- * Technically this version of the graph combine the fast adding/removing of the edges of the Matrix implementation,
- * with the low memory and fast adding/removing of vertices of the Linked List implementation.
- * This happen if the HashMap is not reallocated. So in the end each operation of adding or removing has O(n)
- *
- * @param the vertices
- * @param the weight of the edges
- * @author Berack96
- */
-public class MapGraph implements Graph {
-
- /**
- * Map that contains the edges from a vertex to another
- * The first vertex is the vertex where start the edge, the second one is where the edge goes
- * If an edge exist, then it's weight is returned
- */
- private final Map> edges = new HashMap<>();
-
- /**
- * Map that contains the vertex as key and all the marker as the value associated with that vertex.
- */
- private final Map> marked = new HashMap<>();
-
- /**
- * Need this variable for not calculating each time the SCC or the cyclic part if the graph doesn't change
- */
- private Tarjan tarjan = null;
-
- /**
- * Need this variable for not calculating each time the distance from a vertex to all his destinations if the graph doesn't change
- */
- private Map> dijkstra = null;
-
- @Override
- public boolean isCyclic() {
- return stronglyConnectedComponents().size() != numberOfVertices();
- }
-
- @Override
- public boolean isDAG() {
- return !isCyclic();
- }
-
- @Override
- public Vertex getVertex(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- return new Vertex<>(this, vertex);
- }
-
- @Override
- public void addVertex(V vertex) throws NullPointerException {
- checkNull(vertex);
- graphChanged();
- edges.put(vertex, new HashMap<>());
- }
-
- @Override
- public boolean addVertexIfAbsent(V vertex) throws NullPointerException {
- if (contains(vertex))
- return false;
- addVertex(vertex);
- return true;
- }
-
- @Override
- public void addAllVertices(Collection vertices) throws NullPointerException {
- checkNull(vertices);
- vertices.forEach(this::addVertexIfAbsent);
- }
-
- @Override
- public void removeVertex(V vertex) throws NullPointerException {
- if (contains(vertex)) {
- graphChanged();
- edges.remove(vertex);
- edges.forEach((v, map) -> map.remove(vertex));
- }
- }
-
- @Override
- public void removeAllVertex() {
- graphChanged();
- edges.clear();
- }
-
- @Override
- public boolean contains(V vertex) throws NullPointerException {
- checkNull(vertex);
- return edges.containsKey(vertex);
- }
-
- @Override
- public void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- checkNull(mark);
-
- Set set = marked.computeIfAbsent(vertex, (m) -> new HashSet<>());
- set.add(mark);
- }
-
- @Override
- public void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- checkNull(mark);
- marked.get(vertex).remove(mark);
- }
-
- @Override
- public void unMark(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- marked.get(vertex).clear();
- }
-
- @Override
- public Set getMarks(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- return marked.computeIfAbsent(vertex, (m) -> new HashSet<>());
- }
-
- @Override
- public void unMarkAll(Object mark) {
- checkNull(mark);
- marked.forEach((v, m) -> m.remove(mark));
- }
-
- @Override
- public void unMarkAll() {
- marked.clear();
- }
-
- @Override
- public W addEdge(V vertex1, V vertex2, W weight) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex1);
- checkNullAndExist(vertex2);
- checkNull(weight);
-
- graphChanged();
- return edges.get(vertex1).put(vertex2, weight);
- }
-
- @Override
- public W addEdge(Edge edge) throws NullPointerException, IllegalArgumentException {
- return addEdge(edge.getSource(), edge.getDestination(), edge.getWeight());
- }
-
- @Override
- public W addEdgeAndVertices(V vertex1, V vertex2, W weight) throws NullPointerException {
- addVertexIfAbsent(vertex1);
- addVertexIfAbsent(vertex2);
- return addEdge(vertex1, vertex2, weight);
- }
-
- @Override
- public W addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException {
- return addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight());
- }
-
- @Override
- public void addAllEdges(Collection> edges) throws NullPointerException {
- edges.forEach((edge) -> addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight()));
- }
-
- @Override
- public W getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex1);
- checkNullAndExist(vertex2);
-
- return edges.get(vertex1).get(vertex2);
- }
-
- @Override
- public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex1);
- checkNullAndExist(vertex2);
-
- graphChanged();
- edges.get(vertex1).remove(vertex2);
- }
-
- @Override
- public void removeAllInEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- graphChanged();
- edges.forEach((v, map) -> map.remove(vertex));
- }
-
- @Override
- public void removeAllOutEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- graphChanged();
- edges.put(vertex, new HashMap<>());
- }
-
- @Override
- public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- removeVertex(vertex);
- addVertex(vertex);
- }
-
- @Override
- public void removeAllEdge() {
- graphChanged();
- edges.forEach((v, map) -> map.clear());
- }
-
- @Override
- public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException {
- return (contains(vertex1) && contains(vertex2)) && edges.get(vertex1).get(vertex2) != null;
- }
-
- @Override
- public Set vertices() {
- return new HashSet<>(edges.keySet());
- }
-
- @Override
- public Set> edges() {
- Set> allEdges = new HashSet<>();
- edges.forEach((source, map) -> map.forEach((destination, weight) -> allEdges.add(new Edge<>(source, destination, weight))));
- return allEdges;
- }
-
- @Override
- public Set> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- Set> set = new HashSet<>();
- edges.forEach((source, map) -> map.forEach((destination, weight) -> {
- if (destination.equals(vertex) || source.equals(vertex))
- set.add(new Edge<>(source, destination, weight));
- }));
- return set;
- }
-
- @Override
- public Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- Collection> collection = new HashSet<>();
- edges.forEach((source, edge) -> {
- if (edge.get(vertex) != null)
- collection.add(new Edge<>(source, vertex, edge.get(vertex)));
- });
-
- return collection;
- }
-
- @Override
- public Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- Collection> collection = new HashSet<>();
- edges.get(vertex).forEach((dest, weight) -> collection.add(new Edge<>(vertex, dest, weight)));
-
- return collection;
- }
-
- @Override
- public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- return new HashSet<>(edges.get(vertex).keySet());
- }
-
- @Override
- public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- Set set = new HashSet<>();
- edges.forEach((v, map) -> {
- if (map.containsKey(vertex)) set.add(v);
- });
- return set;
- }
-
- @Override
- public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- AtomicInteger sum = new AtomicInteger();
- edges.forEach((v, map) -> {
- if (map.containsKey(vertex))
- sum.getAndIncrement();
- });
-
- return sum.get();
- }
-
- @Override
- public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- return edges.get(vertex).size();
- }
-
- @Override
- public int degree(V vertex) throws NullPointerException, IllegalArgumentException {
- return degreeIn(vertex) + degreeOut(vertex);
- }
-
- @Override
- public int numberOfVertices() {
- return edges.size();
- }
-
- @Override
- public int numberOfEdges() {
- AtomicInteger sum = new AtomicInteger(0);
- edges.forEach((v, map) -> sum.getAndAdd(map.size()));
-
- return sum.get();
- }
-
- @Override
- public VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, IllegalArgumentException {
- return strategy.visit(this, source, visit);
- }
-
- @Override
- public Graph transpose() {
- Graph graph = new MapGraph<>();
- for (V vertex : edges.keySet())
- graph.addVertex(vertex);
-
- edges.forEach((source, map) -> map.forEach((destination, weight) -> graph.addEdge(destination, source, weight)));
-
- return graph;
- }
-
- @Override
- public List topologicalSort() throws UnsupportedOperationException {
- if (!isDAG())
- throw new UnsupportedOperationException(NOT_DAG);
- return getTarjan().getTopologicalSort();
- }
-
- @Override
- public Collection> stronglyConnectedComponents() {
- return getTarjan().getSCC();
- }
-
- @Override
- public Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException {
- Graph sub = new MapGraph<>();
- Set vertices = new HashSet<>();
-
- int finalDepth = depth > 0 ? depth : 0;
- VisitStrategy strategy = (graph, sourceVertex, visit) -> {
- int currentDepth = 0;
- final LinkedList> toVisitChildren = new LinkedList<>();
- toVisitChildren.add(new AbstractMap.SimpleEntry<>(sourceVertex, 0));
- vertices.add(source);
-
- while (!toVisitChildren.isEmpty() && currentDepth + 1 <= finalDepth) {
- final Map.Entry current = toVisitChildren.removeFirst();
- currentDepth = current.getValue() + 1;
- final int finalCurrentDepth = currentDepth;
-
- for (V child : graph.getChildren(current.getKey()))
- if (!vertices.contains(child)) {
- toVisitChildren.addLast(new AbstractMap.SimpleEntry<>(child, finalCurrentDepth));
- vertices.add(child);
- }
- }
- return null;
- };
-
- strategy.visit(this, source, null);
-
- sub.addAllVertices(vertices);
- for (V vertex : vertices)
- getEdgesOut(vertex).forEach((edge) -> {
- try {
- sub.addEdge(edge);
- } catch (Exception ignored) {
- }
- });
-
- return sub;
- }
-
- @Override
- public Graph subGraph(final Object marker) {
- final Graph graph = new MapGraph<>();
- final Set allVertices = new HashSet<>();
-
- marked.forEach((vertex, mark) -> {
- if (mark.contains(marker) || (marker == null && !mark.isEmpty()))
- allVertices.add(vertex);
- });
-
- if (marker == null) {
- Collection toAdd = graph.vertices();
- toAdd.removeAll(allVertices);
- allVertices.clear();
- allVertices.addAll(toAdd);
- }
-
- graph.addAllVertices(allVertices);
- for (V vertex : graph.vertices())
- getEdgesOut(vertex).forEach((edge) -> {
- try {
- graph.addEdge(edge);
- } catch (Exception ignored) {
- }
- });
-
- return graph;
- }
-
- @Override
- public List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
- checkNullAndExist(source);
- checkNullAndExist(destination);
-
- Dijkstra dijkstra = getDijkstra(source);
- List> path = dijkstra.getLastDistance().get(destination);
- if (path == null)
- throw new UnsupportedOperationException(NOT_CONNECTED);
- return new ArrayList<>(path);
- }
-
- @Override
- public Map>> distance(V source) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(source);
- return new HashMap<>(getDijkstra(source).getLastDistance());
- }
-
- @Override
- public Iterator iterator() {
- return edges.keySet().iterator();
- }
-
-
- /**
- * Simple function that set all the memory vars at null if the graph changed
- */
- private void graphChanged() {
- tarjan = null;
- dijkstra = null;
- }
-
- private Dijkstra getDijkstra(V source) {
- if (dijkstra == null)
- dijkstra = new HashMap<>();
- if (dijkstra.get(source) == null) {
- Dijkstra newDijkstra = new Dijkstra<>();
- newDijkstra.visit(this, source, null);
- dijkstra.put(source, newDijkstra);
- }
-
- return dijkstra.get(source);
- }
-
- private Tarjan getTarjan() {
- if (tarjan == null) {
- tarjan = new Tarjan<>();
- tarjan.visit(this, null, null);
- }
-
- return tarjan;
- }
-
- private void checkNull(Object object) {
- if (object == null)
- throw new NullPointerException(PARAM_NULL);
- }
-
- private void checkNullAndExist(V vertex) {
- checkNull(vertex);
- if (!edges.containsKey(vertex))
- throw new IllegalArgumentException(VERTEX_NOT_CONTAINED);
- }
-}
+package berack96.sim.util.graph;
+
+import berack96.sim.util.graph.visit.Dijkstra;
+import berack96.sim.util.graph.visit.Tarjan;
+import berack96.sim.util.graph.visit.VisitInfo;
+import berack96.sim.util.graph.visit.VisitStrategy;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+
+/**
+ * Graph that uses HashMap for vertices and edges
+ * More specifically it utilizes a Map containing all the vertices mapped to all their edges
+ * Technically this version of the graph combine the fast adding/removing of the edges of the Matrix implementation,
+ * with the low memory and fast adding/removing of vertices of the Linked List implementation.
+ * This happen if the HashMap is not reallocated. So in the end each operation of adding or removing has O(n)
+ *
+ * @param the vertices
+ * @param the weight of the edges
+ * @author Berack96
+ */
+public class MapGraph implements Graph {
+
+ /**
+ * Map that contains the edges from a vertex to another
+ * The first vertex is the vertex where start the edge, the second one is where the edge goes
+ * If an edge exist, then it's weight is returned
+ */
+ private final Map> edges = new HashMap<>();
+
+ /**
+ * Map that contains the vertex as key and all the marker as the value associated with that vertex.
+ */
+ private final Map> marked = new HashMap<>();
+
+ /**
+ * Need this variable for not calculating each time the SCC or the cyclic part if the graph doesn't change
+ */
+ private Tarjan tarjan = null;
+
+ /**
+ * Need this variable for not calculating each time the distance from a vertex to all his destinations if the graph doesn't change
+ */
+ private Map> dijkstra = null;
+
+ @Override
+ public boolean isCyclic() {
+ return stronglyConnectedComponents().size() != numberOfVertices();
+ }
+
+ @Override
+ public boolean isDAG() {
+ return !isCyclic();
+ }
+
+ @Override
+ public Vertex getVertex(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ return new Vertex<>(this, vertex);
+ }
+
+ @Override
+ public void addVertex(V vertex) throws NullPointerException {
+ checkNull(vertex);
+ graphChanged();
+ edges.put(vertex, new HashMap<>());
+ }
+
+ @Override
+ public boolean addVertexIfAbsent(V vertex) throws NullPointerException {
+ if (contains(vertex))
+ return false;
+ addVertex(vertex);
+ return true;
+ }
+
+ @Override
+ public void addAllVertices(Collection vertices) throws NullPointerException {
+ checkNull(vertices);
+ vertices.forEach(this::addVertexIfAbsent);
+ }
+
+ @Override
+ public void removeVertex(V vertex) throws NullPointerException {
+ if (contains(vertex)) {
+ graphChanged();
+ edges.remove(vertex);
+ edges.forEach((v, map) -> map.remove(vertex));
+ }
+ }
+
+ @Override
+ public void removeAllVertex() {
+ graphChanged();
+ edges.clear();
+ }
+
+ @Override
+ public boolean contains(V vertex) throws NullPointerException {
+ checkNull(vertex);
+ return edges.containsKey(vertex);
+ }
+
+ @Override
+ public void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ checkNull(mark);
+
+ Set set = marked.computeIfAbsent(vertex, (m) -> new HashSet<>());
+ set.add(mark);
+ }
+
+ @Override
+ public void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ checkNull(mark);
+ marked.get(vertex).remove(mark);
+ }
+
+ @Override
+ public void unMark(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ marked.get(vertex).clear();
+ }
+
+ @Override
+ public Collection getMarkedWith(Object mark) throws NullPointerException {
+ checkNull(mark);
+ Collection ret = new HashSet();
+ marked.forEach((v, set) -> {
+ if(set.contains(mark))
+ ret.add(v);
+ });
+
+ return ret;
+ }
+
+ @Override
+ public Set getMarks(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ return marked.computeIfAbsent(vertex, (m) -> new HashSet<>());
+ }
+
+ @Override
+ public void unMarkAll(Object mark) {
+ checkNull(mark);
+ marked.forEach((v, m) -> m.remove(mark));
+ }
+
+ @Override
+ public void unMarkAll() {
+ marked.clear();
+ }
+
+ @Override
+ public W addEdge(V vertex1, V vertex2, W weight) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex1);
+ checkNullAndExist(vertex2);
+ checkNull(weight);
+
+ graphChanged();
+ return edges.get(vertex1).put(vertex2, weight);
+ }
+
+ @Override
+ public W addEdge(Edge edge) throws NullPointerException, IllegalArgumentException {
+ return addEdge(edge.getSource(), edge.getDestination(), edge.getWeight());
+ }
+
+ @Override
+ public W addEdgeAndVertices(V vertex1, V vertex2, W weight) throws NullPointerException {
+ addVertexIfAbsent(vertex1);
+ addVertexIfAbsent(vertex2);
+ return addEdge(vertex1, vertex2, weight);
+ }
+
+ @Override
+ public W addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException {
+ return addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight());
+ }
+
+ @Override
+ public void addAllEdges(Collection> edges) throws NullPointerException {
+ edges.forEach((edge) -> addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight()));
+ }
+
+ @Override
+ public W getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex1);
+ checkNullAndExist(vertex2);
+
+ return edges.get(vertex1).get(vertex2);
+ }
+
+ @Override
+ public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex1);
+ checkNullAndExist(vertex2);
+
+ graphChanged();
+ edges.get(vertex1).remove(vertex2);
+ }
+
+ @Override
+ public void removeAllInEdge(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ graphChanged();
+ edges.forEach((v, map) -> map.remove(vertex));
+ }
+
+ @Override
+ public void removeAllOutEdge(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ graphChanged();
+ edges.put(vertex, new HashMap<>());
+ }
+
+ @Override
+ public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ removeVertex(vertex);
+ addVertex(vertex);
+ }
+
+ @Override
+ public void removeAllEdge() {
+ graphChanged();
+ edges.forEach((v, map) -> map.clear());
+ }
+
+ @Override
+ public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException {
+ return (contains(vertex1) && contains(vertex2)) && edges.get(vertex1).get(vertex2) != null;
+ }
+
+ @Override
+ public Set vertices() {
+ return new HashSet<>(edges.keySet());
+ }
+
+ @Override
+ public Set> edges() {
+ Set> allEdges = new HashSet<>();
+ edges.forEach((source, map) -> map.forEach((destination, weight) -> allEdges.add(new Edge<>(source, destination, weight))));
+ return allEdges;
+ }
+
+ @Override
+ public Set> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ Set> set = new HashSet<>();
+ edges.forEach((source, map) -> map.forEach((destination, weight) -> {
+ if (destination.equals(vertex) || source.equals(vertex))
+ set.add(new Edge<>(source, destination, weight));
+ }));
+ return set;
+ }
+
+ @Override
+ public Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ Collection> collection = new HashSet<>();
+ edges.forEach((source, edge) -> {
+ if (edge.get(vertex) != null)
+ collection.add(new Edge<>(source, vertex, edge.get(vertex)));
+ });
+
+ return collection;
+ }
+
+ @Override
+ public Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ Collection> collection = new HashSet<>();
+ edges.get(vertex).forEach((dest, weight) -> collection.add(new Edge<>(vertex, dest, weight)));
+
+ return collection;
+ }
+
+ @Override
+ public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ return new HashSet<>(edges.get(vertex).keySet());
+ }
+
+ @Override
+ public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ Set set = new HashSet<>();
+ edges.forEach((v, map) -> {
+ if (map.containsKey(vertex)) set.add(v);
+ });
+ return set;
+ }
+
+ @Override
+ public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ AtomicInteger sum = new AtomicInteger();
+ edges.forEach((v, map) -> {
+ if (map.containsKey(vertex))
+ sum.getAndIncrement();
+ });
+
+ return sum.get();
+ }
+
+ @Override
+ public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ return edges.get(vertex).size();
+ }
+
+ @Override
+ public int degree(V vertex) throws NullPointerException, IllegalArgumentException {
+ return degreeIn(vertex) + degreeOut(vertex);
+ }
+
+ @Override
+ public int numberOfVertices() {
+ return edges.size();
+ }
+
+ @Override
+ public int numberOfEdges() {
+ AtomicInteger sum = new AtomicInteger(0);
+ edges.forEach((v, map) -> sum.getAndAdd(map.size()));
+
+ return sum.get();
+ }
+
+ @Override
+ public VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, IllegalArgumentException {
+ return strategy.visit(this, source, visit);
+ }
+
+ @Override
+ public Graph transpose() {
+ Graph graph = new MapGraph<>();
+ for (V vertex : edges.keySet())
+ graph.addVertex(vertex);
+
+ edges.forEach((source, map) -> map.forEach((destination, weight) -> graph.addEdge(destination, source, weight)));
+
+ return graph;
+ }
+
+ @Override
+ public List topologicalSort() throws UnsupportedOperationException {
+ if (!isDAG())
+ throw new UnsupportedOperationException(NOT_DAG);
+ return getTarjan().getTopologicalSort();
+ }
+
+ @Override
+ public Collection> stronglyConnectedComponents() {
+ return getTarjan().getSCC();
+ }
+
+ @Override
+ public Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException {
+ Graph sub = new MapGraph<>();
+ Set vertices = new HashSet<>();
+
+ int finalDepth = depth > 0 ? depth : 0;
+ VisitStrategy strategy = (graph, sourceVertex, visit) -> {
+ int currentDepth = 0;
+ final LinkedList> toVisitChildren = new LinkedList<>();
+ toVisitChildren.add(new AbstractMap.SimpleEntry<>(sourceVertex, 0));
+ vertices.add(source);
+
+ while (!toVisitChildren.isEmpty() && currentDepth + 1 <= finalDepth) {
+ final Map.Entry current = toVisitChildren.removeFirst();
+ currentDepth = current.getValue() + 1;
+ final int finalCurrentDepth = currentDepth;
+
+ for (V child : graph.getChildren(current.getKey()))
+ if (!vertices.contains(child)) {
+ toVisitChildren.addLast(new AbstractMap.SimpleEntry<>(child, finalCurrentDepth));
+ vertices.add(child);
+ }
+ }
+ return null;
+ };
+
+ strategy.visit(this, source, null);
+
+ sub.addAllVertices(vertices);
+ for (V vertex : vertices)
+ getEdgesOut(vertex).forEach((edge) -> {
+ try {
+ sub.addEdge(edge);
+ } catch (Exception ignored) {
+ }
+ });
+
+ return sub;
+ }
+
+ @Override
+ public Graph subGraph(final Object marker) {
+ final Graph graph = new MapGraph<>();
+ final Set allVertices = new HashSet<>();
+
+ marked.forEach((vertex, mark) -> {
+ if (mark.contains(marker) || (marker == null && !mark.isEmpty()))
+ allVertices.add(vertex);
+ });
+
+ if (marker == null) {
+ Collection toAdd = graph.vertices();
+ toAdd.removeAll(allVertices);
+ allVertices.clear();
+ allVertices.addAll(toAdd);
+ }
+
+ graph.addAllVertices(allVertices);
+ for (V vertex : graph.vertices())
+ getEdgesOut(vertex).forEach((edge) -> {
+ try {
+ graph.addEdge(edge);
+ } catch (Exception ignored) {
+ }
+ });
+
+ return graph;
+ }
+
+ @Override
+ public List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
+ checkNullAndExist(source);
+ checkNullAndExist(destination);
+
+ Dijkstra dijkstra = getDijkstra(source);
+ List> path = dijkstra.getLastDistance().get(destination);
+ if (path == null)
+ throw new UnsupportedOperationException(NOT_CONNECTED);
+ return new ArrayList<>(path);
+ }
+
+ @Override
+ public Map>> distance(V source) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(source);
+ return new HashMap<>(getDijkstra(source).getLastDistance());
+ }
+
+ @Override
+ public Iterator iterator() {
+ return edges.keySet().iterator();
+ }
+
+
+ /**
+ * Simple function that set all the memory vars at null if the graph changed
+ */
+ private void graphChanged() {
+ tarjan = null;
+ dijkstra = null;
+ }
+
+ private Dijkstra getDijkstra(V source) {
+ if (dijkstra == null)
+ dijkstra = new HashMap<>();
+ if (dijkstra.get(source) == null) {
+ Dijkstra newDijkstra = new Dijkstra<>();
+ newDijkstra.visit(this, source, null);
+ dijkstra.put(source, newDijkstra);
+ }
+
+ return dijkstra.get(source);
+ }
+
+ private Tarjan getTarjan() {
+ if (tarjan == null) {
+ tarjan = new Tarjan<>();
+ tarjan.visit(this, null, null);
+ }
+
+ return tarjan;
+ }
+
+ private void checkNull(Object object) {
+ if (object == null)
+ throw new NullPointerException(PARAM_NULL);
+ }
+
+ private void checkNullAndExist(V vertex) {
+ checkNull(vertex);
+ if (!edges.containsKey(vertex))
+ throw new IllegalArgumentException(VERTEX_NOT_CONTAINED);
+ }
+}
diff --git a/src/berack96/sim/util/graph/Vertex.java b/src/berack96/sim/util/graph/Vertex.java
index 3e29425..d369555 100644
--- a/src/berack96/sim/util/graph/Vertex.java
+++ b/src/berack96/sim/util/graph/Vertex.java
@@ -15,7 +15,7 @@ import java.util.function.Consumer;
* @param the vertex
* @author Berack96
*/
-@SuppressWarnings("unchecked")
+@SuppressWarnings({"unchecked", "rawtypes"})
public class Vertex {
public static final String REMOVED = "The vertex is no longer in the graph";
@@ -240,7 +240,7 @@ public class Vertex {
* @throws NullPointerException if the strategy is null
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
*/
- public VisitInfo visit(final VisitStrategy strategy, final Consumer visit) throws NullPointerException, UnsupportedOperationException {
+ public VisitInfo visit(final VisitStrategy strategy, final Consumer visit) throws NullPointerException, UnsupportedOperationException {
throwIfNotContained();
return graph.visit(vertex, (VisitStrategy) strategy, visit);
}
diff --git a/src/berack96/sim/util/graph/view/GraphInfo.java b/src/berack96/sim/util/graph/view/GraphInfo.java
new file mode 100644
index 0000000..7794dca
--- /dev/null
+++ b/src/berack96/sim/util/graph/view/GraphInfo.java
@@ -0,0 +1,162 @@
+package berack96.sim.util.graph.view;
+
+import berack96.sim.util.graph.Graph;
+import berack96.sim.util.graph.view.edge.EdgeListener;
+import berack96.sim.util.graph.view.vertex.VertexListener;
+import berack96.sim.util.graph.visit.VisitStrategy;
+
+import javax.swing.*;
+import javax.swing.border.BevelBorder;
+import java.awt.*;
+import java.awt.event.ItemEvent;
+import java.util.*;
+import java.util.List;
+
+public class GraphInfo extends JPanel {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Map> visits;
+
+ public GraphInfo(GraphPanel graphPanel, VertexListener vListener, EdgeListener eListener, Set> visits) {
+ this.visits = new HashMap<>();
+
+ /* ZERO (DESCRIPTION) */
+ JLabel listenerDescription = new JLabel();
+
+ JPanel panelDescription = new JPanel();
+ panelDescription.setOpaque(false);
+ panelDescription.add(listenerDescription);
+
+ /* FIRST (GRAPH INFO) */
+
+ JLabel vNumber = new JLabel(String.valueOf(graphPanel.getGraph().numberOfVertices()));
+ JLabel eNumber = new JLabel(String.valueOf(graphPanel.getGraph().numberOfEdges()));
+ JLabel gCyclic = new JLabel(String.valueOf(graphPanel.getGraph().isCyclic()));
+
+ List components = new LinkedList<>();
+ JLabel selected = new JLabel();
+ JComboBox comboBox = new JComboBox<>();
+ comboBox.addItemListener(e -> {
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ try {
+ String clazz = (String) e.getItem();
+ VisitListener listener = this.visits.get(clazz);
+
+ selected.setText(listener != null? "visit":"nothing");
+ listenerDescription.setText(listener != null? listener.getDescription():"");
+
+ graphPanel.getGraph().unMarkAll();
+ graphPanel.repaint();
+ graphPanel.setGraphListener(listener);
+
+ } catch (Exception ignore) {}
+ }
+
+ });
+
+ comboBox.addItem("None");
+ for(VisitStrategy strategy: visits) {
+ String clazz = strategy.getClass().getSimpleName();
+ VisitListener visit = new VisitListener<>(graphPanel, strategy);
+ comboBox.addItem(clazz);
+ this.visits.put(clazz, visit);
+ }
+
+ components.add(new JLabel("Visit Strategy: "));
+ components.add(comboBox);
+ components.add(new JLabel("Selected modality: "));
+ components.add(selected);
+ components.add(new JLabel("Vertex Number: "));
+ components.add(vNumber);
+ components.add(new JLabel("Edge Number: "));
+ components.add(eNumber);
+ components.add(new JLabel("Is Cyclic: "));
+ components.add(gCyclic);
+
+ JPanel panelInfo = new JPanel();
+ panelInfo.setOpaque(false);
+ panelInfo.setBorder(BorderFactory.createLineBorder(Color.RED));
+ panelInfo.setLayout(new GridLayout(components.size()/2, 2, 2*2, 2*2));
+ components.forEach(panelInfo::add);
+ components.clear();
+
+ /* SECOND (VERTEX) */
+ JLabel vVertex = new JLabel();
+ JLabel vEdgesNumber = new JLabel();
+ JLabel vEdgesInNumber = new JLabel();
+ JLabel vEdgesOutNumber = new JLabel();
+
+ JButton modVertex = new JButton("Modify Vertices");
+ modVertex.addActionListener(a -> {
+ comboBox.setSelectedIndex(0);
+ listenerDescription.setText(vListener.getDescription());
+ graphPanel.setGraphListener(vListener);
+ graphPanel.getGraph().unMarkAll();
+ graphPanel.repaint();
+ selected.setText("vertices");
+ });
+
+ JButton modEdge = new JButton("Modify Edges");
+ modEdge.addActionListener(a -> {
+ comboBox.setSelectedIndex(0);
+ listenerDescription.setText(eListener.getDescription());
+ graphPanel.setGraphListener(eListener);
+ graphPanel.getGraph().unMarkAll();
+ graphPanel.repaint();
+ selected.setText("edges");
+ });
+
+ components.add(modVertex);
+ components.add(modEdge);
+ components.add(new JLabel("Vertex name: "));
+ components.add(vVertex);
+ components.add(new JLabel("Edges: "));
+ components.add(vEdgesNumber);
+ components.add(new JLabel("Edges IN: "));
+ components.add(vEdgesInNumber);
+ components.add(new JLabel("Edges OUT: "));
+ components.add(vEdgesOutNumber);
+
+ JPanel panelVertex = new JPanel();
+ panelVertex.setOpaque(false);
+ panelVertex.setLayout(new GridLayout(components.size()/2, 2, 2*2, 2*2));
+ components.forEach(panelVertex::add);
+
+ /* Save/Load
+ JPanel panelSave = new JPanel(); */
+
+
+ /* ADDING COMPONENTS */
+ this.setBackground(Color.LIGHT_GRAY);
+ this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+ this.setOpaque(true);
+ this.setBorder(BorderFactory.createSoftBevelBorder(BevelBorder.RAISED, Color.GRAY, Color.DARK_GRAY));
+ this.add(panelDescription);
+ this.add(panelInfo);
+ this.add(panelVertex);
+ this.add(Box.createVerticalGlue());
+
+ modVertex.doClick();
+
+ graphPanel.addObserver((o, arg) -> {
+ Graph graph = graphPanel.getGraph();
+ if(arg.equals(graph)) {
+ vNumber.setText(String.valueOf(graph.numberOfVertices()));
+ eNumber.setText(String.valueOf(graph.numberOfEdges()));
+ gCyclic.setText(String.valueOf(graph.isCyclic()));
+
+ /* There should be only one */
+ for(V v : graph.getMarkedWith("selected")) {
+ int inE = graph.getEdgesIn(v).size();
+ int outE = graph.getEdgesOut(v).size();
+
+ vEdgesInNumber.setText(String.valueOf(inE));
+ vEdgesOutNumber.setText(String.valueOf(outE));
+ vEdgesNumber.setText(String.valueOf(inE + outE));
+ vVertex.setText(v.toString());
+ }
+ }
+ });
+ }
+}
diff --git a/src/berack96/sim/util/graph/view/GraphListener.java b/src/berack96/sim/util/graph/view/GraphListener.java
new file mode 100644
index 0000000..364d289
--- /dev/null
+++ b/src/berack96/sim/util/graph/view/GraphListener.java
@@ -0,0 +1,27 @@
+package berack96.sim.util.graph.view;
+
+import java.awt.event.KeyListener;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+/**
+ * An interface for creating a listener of the Graph.
+ *
+ * @author Berack96
+ */
+public interface GraphListener extends MouseListener, MouseMotionListener, KeyListener {
+
+ /**
+ * Remove the listener to the graph.
+ * This function is called when the listener is removed to the graph.
+ * Here you could remove any other thing that you have done.
+ */
+ public void remove();
+
+ /**
+ * Get the description of this listener, in a way to interact with the user.
+ *
+ * @return a string describing the functionalities of this listener
+ */
+ public String getDescription();
+}
diff --git a/src/berack96/sim/util/graph/view/GraphPanel.java b/src/berack96/sim/util/graph/view/GraphPanel.java
new file mode 100644
index 0000000..b547089
--- /dev/null
+++ b/src/berack96/sim/util/graph/view/GraphPanel.java
@@ -0,0 +1,174 @@
+package berack96.sim.util.graph.view;
+
+import berack96.sim.util.graph.Graph;
+import berack96.sim.util.graph.MapGraph;
+import berack96.sim.util.graph.Vertex;
+import berack96.sim.util.graph.view.edge.EdgeComponent;
+import berack96.sim.util.graph.view.vertex.VertexComponent;
+
+import java.awt.*;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Observer;
+import java.util.Set;
+
+@SuppressWarnings("unchecked")
+public class GraphPanel extends Component {
+
+ private static final long serialVersionUID = 1L;
+ private final GraphicalView> vertexRender;
+ private final GraphicalView> edgeRender;
+
+ private final Container vertices = new Container();
+ private final Container edges = new Container();
+
+ private final Graph graph = new MapGraph<>();
+ private final Set observers = new HashSet<>();
+
+ private GraphListener old = null;
+
+ public GraphPanel(GraphicalView> vertexRender, GraphicalView> edgeRender) {
+ this.vertexRender = vertexRender;
+ this.edgeRender = edgeRender;
+ }
+
+ public Graph getGraph() {
+ return graph;
+ }
+
+ public void setGraphListener(GraphListener listener) {
+ if(old != null)
+ old.remove();
+ for (MouseListener l : getMouseListeners())
+ removeMouseListener(l);
+ for (MouseMotionListener l : getMouseMotionListeners())
+ removeMouseMotionListener(l);
+ for (KeyListener l : getKeyListeners())
+ removeKeyListener(l);
+
+ old = listener;
+ addMouseListener(listener);
+ addMouseMotionListener(listener);
+ addKeyListener(listener);
+ }
+
+ public void addVertex(Point center, V vertex) {
+ VertexComponent component = getVertexAt(center);
+
+ if (component == null) {
+ VertexComponent v = new VertexComponent<>(new Vertex<>(graph, vertex));
+ if (!graph.contains(vertex)) {
+ v.vertex.addIfAbsent();
+ v.setBounds(vertexRender.getBox(v, center));
+ vertices.add(v);
+ }
+ }
+ }
+
+ public void removeVertex(Point center) {
+ try {
+ VertexComponent component = getVertexAt(center);
+ component.vertex.remove();
+ vertices.remove(component);
+ } catch (Exception ignore) {}
+ }
+
+ public void moveVertex(VertexComponent vertex, Point destination) {
+ Rectangle rectangle = vertexRender.getBox(vertex, destination);
+ vertex.setLocation(rectangle.x, rectangle.y);
+ }
+
+ public void addEdge(VertexComponent source, VertexComponent dest, W weight) {
+ try {
+ Point center = new Point(Math.abs(source.getX() - dest.getY()), Math.abs(source.getY() - dest.getY()));
+ EdgeComponent edgeComponent = new EdgeComponent<>(source, dest, weight);
+ edgeComponent.setBounds(edgeRender.getBox(edgeComponent, center));
+ edges.add(edgeComponent);
+ graph.addEdge(edgeComponent.edge);
+ } catch (Exception ignore) {}
+ }
+
+ public void removeEdge(VertexComponent source, VertexComponent dest) {
+ try {
+ graph.removeEdge(source.vertex.getValue(), dest.vertex.getValue());
+ EdgeComponent toRemove = null;
+ for (Component c : edges.getComponents()) {
+ EdgeComponent edge = (EdgeComponent) c;
+ if (edge.source.equals(source) && edge.destination.equals(dest))
+ toRemove = edge;
+ }
+ edges.remove(toRemove);
+
+ } catch (Exception ignore) {}
+ }
+
+ public void modEdge(VertexComponent source, VertexComponent dest, W weight) {
+ removeEdge(source, dest);
+ addEdge(source, dest, weight);
+ }
+
+ public VertexComponent getVertexAt(Point point) {
+ Component component = vertices.getComponentAt(point);
+ return component instanceof VertexComponent ? (VertexComponent) component : null;
+ }
+
+ public EdgeComponent getEdgeAt(Point point) {
+ Component component = edges.getComponentAt(point);
+ return component instanceof EdgeComponent ? (EdgeComponent) component : null;
+ }
+
+ public void addObserver(Observer observer) {
+ observers.add(observer);
+ }
+
+ public void removeObserver(Observer observer) {
+ observers.remove(observer);
+ }
+
+
+ @Override
+ public void setBounds(int x, int y, int width, int height) {
+ super.setBounds(x, y, width, height);
+ vertices.setBounds(x, y, width, height);
+ edges.setBounds(x, y, width, height);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g.create();
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ Collection> toRemove = new HashSet<>();
+ for (Component component : edges.getComponents()) {
+ EdgeComponent edge = (EdgeComponent) component;
+ Vertex source = edge.source.vertex;
+ Vertex dest = edge.destination.vertex;
+ if (source.isStillContained() && dest.isStillContained() && graph.containsEdge(source.getValue(), dest.getValue())) {
+ Point center = new Point(edge.getX() + edge.getWidth() / 2, edge.getY() + edge.getHeight() / 2);
+ edge.setBounds(edgeRender.getBox(edge, center));
+ edgeRender.paint((Graphics2D) g2.create(), edge, center);
+ }
+ else
+ toRemove.add(edge);
+ }
+ toRemove.forEach(edges::remove);
+
+ for (Component component : vertices.getComponents()) {
+ VertexComponent vertex = (VertexComponent) component;
+ if (graph.contains(vertex.vertex.getValue())) {
+ Point center = new Point(vertex.getX() + vertex.getWidth() / 2, vertex.getY() + vertex.getHeight() / 2);
+ vertexRender.paint((Graphics2D) g2.create(), vertex, center);
+ }
+ }
+
+ updateObservers();
+ }
+
+ private void updateObservers() {
+ observers.forEach(observer -> observer.update(null, this.graph));
+ }
+
+}
diff --git a/src/berack96/sim/util/graph/view/GraphWindow.java b/src/berack96/sim/util/graph/view/GraphWindow.java
new file mode 100644
index 0000000..f64c821
--- /dev/null
+++ b/src/berack96/sim/util/graph/view/GraphWindow.java
@@ -0,0 +1,65 @@
+package berack96.sim.util.graph.view;
+
+import berack96.sim.util.graph.view.edge.EdgeIntListener;
+import berack96.sim.util.graph.view.edge.EdgeListener;
+import berack96.sim.util.graph.view.edge.EdgeView;
+import berack96.sim.util.graph.view.vertex.VertexIntListener;
+import berack96.sim.util.graph.view.vertex.VertexListener;
+import berack96.sim.util.graph.view.vertex.VertexView;
+import berack96.sim.util.graph.visit.*;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * This class is the Window that appear for building the graph and playing around with it
+ *
+ * @author Berack96
+ */
+public class GraphWindow extends JFrame {
+
+ private static final long serialVersionUID = 1L;
+
+ public static void main(String[] args) {
+ GraphPanel panel = new GraphPanel<>(new VertexView<>(), new EdgeView<>());
+ GraphWindow win = new GraphWindow<>(panel, new VertexIntListener(panel), new EdgeIntListener<>(panel));
+ Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // full screen
+ dim.setSize(dim.width / 2, dim.height / 2);
+ win.setSize(dim);
+ win.setLocationRelativeTo(null); //centered
+ win.visitRefresh(500);
+
+ win.setVisible(true);
+ }
+
+ private final GraphPanel graphPanel;
+ private final GraphInfo infoPanel;
+
+ private GraphWindow(GraphPanel graphPanel, VertexListener vListener, EdgeListener eListener) {
+ this.setTitle("Grafo");
+ this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ this.setLayout(new BorderLayout());
+
+ Set> strats = new LinkedHashSet<>();
+ strats.add(new DFS<>());
+ strats.add(new BFS<>());
+ strats.add(new Dijkstra<>());
+ strats.add(new Tarjan<>());
+
+ this.infoPanel = new GraphInfo<>(graphPanel, vListener, eListener, strats);
+ this.graphPanel = graphPanel;
+
+ this.add(infoPanel, BorderLayout.EAST);
+ this.add(graphPanel);
+ }
+
+ public void visitRefresh(int millisec) {
+ VisitListener.changeRefresh(millisec);
+ }
+
+ public GraphPanel getGraphPanel() {
+ return graphPanel;
+ }
+}
diff --git a/src/berack96/sim/util/graph/view/GraphicalView.java b/src/berack96/sim/util/graph/view/GraphicalView.java
new file mode 100644
index 0000000..9d29e2f
--- /dev/null
+++ b/src/berack96/sim/util/graph/view/GraphicalView.java
@@ -0,0 +1,29 @@
+package berack96.sim.util.graph.view;
+
+import java.awt.*;
+
+/**
+ * An interface for divide the "hitbox" and the "paint" of the various items
+ *
+ * @param the object to paint
+ * @author Berack96
+ */
+public interface GraphicalView {
+ /**
+ * Box where the object is sensible at listeners (like Hitbox)
+ *
+ * @param obj the object to draw
+ * @param center the center point of the object
+ * @return a rectangle where the object is sensible to the listeners
+ */
+ Rectangle getBox(O obj, Point center);
+
+ /**
+ * The paint function, aka the part where you can draw things (like Mesh)
+ *
+ * @param g2 the graphics object used for painting
+ * @param obj the object to paint
+ * @param center the center point of the object
+ */
+ void paint(Graphics2D g2, O obj, Point center);
+}
diff --git a/src/berack96/sim/util/graph/view/VisitListener.java b/src/berack96/sim/util/graph/view/VisitListener.java
new file mode 100644
index 0000000..9dd40a3
--- /dev/null
+++ b/src/berack96/sim/util/graph/view/VisitListener.java
@@ -0,0 +1,112 @@
+package berack96.sim.util.graph.view;
+
+import berack96.sim.util.graph.Graph;
+import berack96.sim.util.graph.view.vertex.VertexComponent;
+import berack96.sim.util.graph.visit.VisitInfo;
+import berack96.sim.util.graph.visit.VisitStrategy;
+
+import javax.swing.*;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class VisitListener implements GraphListener {
+
+ private final GraphPanel panel;
+ private final VisitStrategy strategy;
+ private final Set timers = new HashSet<>();
+
+ private static int refreshTime = 1000;
+
+ public VisitListener(GraphPanel panel, VisitStrategy strategy) {
+ this.panel = panel;
+ this.strategy = strategy;
+ }
+
+ public static void changeRefresh(int millisec) {
+ refreshTime = millisec;
+ }
+
+ @Override
+ public void remove() {
+ timers.forEach(t -> t.stop());
+ timers.clear();
+ }
+
+ @Override
+ public String getDescription() {
+ return ""
+ + "Start a visit by pressing "
+ + "with the mouse SX on the root vertex "
+ + "";
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ this.remove();
+
+ Graph graph = panel.getGraph();
+ graph.unMarkAll();
+ panel.repaint();
+
+ if (e.getButton() == MouseEvent.BUTTON1)
+ try {
+ VertexComponent vertex = panel.getVertexAt(e.getPoint());
+ AtomicInteger count = new AtomicInteger(0);
+ VisitInfo info = vertex.vertex.visit(strategy, null);
+
+ info.forEach(v -> {
+ final boolean visited = v.timeVisited == count.get();
+ Timer timer = new Timer(count.getAndIncrement() * refreshTime, e1 -> {
+ if (visited && v.parent !=null)
+ graph.mark(v.vertex, v.parent);
+ graph.mark(v.vertex, visited ? "visited" : "discovered");
+ panel.repaint();
+ });
+
+ timers.add(timer);
+ timer.setRepeats(false);
+ timer.start();
+ });
+
+ } catch (Exception ignore) {}
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+ }
+}
diff --git a/src/berack96/sim/util/graph/view/edge/EdgeComponent.java b/src/berack96/sim/util/graph/view/edge/EdgeComponent.java
new file mode 100644
index 0000000..cd52048
--- /dev/null
+++ b/src/berack96/sim/util/graph/view/edge/EdgeComponent.java
@@ -0,0 +1,22 @@
+package berack96.sim.util.graph.view.edge;
+
+import berack96.sim.util.graph.Edge;
+import berack96.sim.util.graph.view.vertex.VertexComponent;
+
+import java.awt.*;
+
+public class EdgeComponent extends Component {
+ private static final long serialVersionUID = 1L;
+
+ public final VertexComponent source;
+ public final VertexComponent destination;
+ public final W weight;
+ public final Edge edge;
+
+ public EdgeComponent(VertexComponent source, VertexComponent destination, W weight) {
+ this.source = source;
+ this.destination = destination;
+ this.weight = weight;
+ this.edge = new Edge<>(source.vertex.getValue(), destination.vertex.getValue(), weight);
+ }
+}
diff --git a/src/berack96/sim/util/graph/view/edge/EdgeIntListener.java b/src/berack96/sim/util/graph/view/edge/EdgeIntListener.java
new file mode 100644
index 0000000..03c61e1
--- /dev/null
+++ b/src/berack96/sim/util/graph/view/edge/EdgeIntListener.java
@@ -0,0 +1,24 @@
+package berack96.sim.util.graph.view.edge;
+
+import berack96.sim.util.graph.Vertex;
+import berack96.sim.util.graph.view.GraphPanel;
+
+public class EdgeIntListener extends EdgeListener {
+
+ public EdgeIntListener(GraphPanel graphPanel) {
+ super(graphPanel);
+ }
+
+ @Override
+ public void remove() {}
+
+ @Override
+ protected Integer buildNewEdge(Vertex vertex, Vertex vertex1) {
+ return (int) (Math.random() * 100);
+ }
+
+ @Override
+ protected Integer buildEdgeFrom(String string) {
+ return Integer.parseInt(string.replaceAll("[^0-9]+", ""));
+ }
+}
diff --git a/src/berack96/sim/util/graph/view/edge/EdgeListener.java b/src/berack96/sim/util/graph/view/edge/EdgeListener.java
new file mode 100644
index 0000000..fee506a
--- /dev/null
+++ b/src/berack96/sim/util/graph/view/edge/EdgeListener.java
@@ -0,0 +1,128 @@
+package berack96.sim.util.graph.view.edge;
+
+import berack96.sim.util.graph.Vertex;
+import berack96.sim.util.graph.view.GraphListener;
+import berack96.sim.util.graph.view.GraphPanel;
+import berack96.sim.util.graph.view.vertex.VertexComponent;
+
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.util.concurrent.atomic.AtomicReference;
+
+public abstract class EdgeListener implements GraphListener {
+
+ private final GraphPanel graphPanel;
+ private final AtomicReference> componentPressed = new AtomicReference<>();
+ private final AtomicReference buttonPressed = new AtomicReference<>();
+ private final AtomicReference> edge = new AtomicReference<>();
+ private final StringBuilder string = new StringBuilder();
+
+ public EdgeListener(GraphPanel graphPanel) {
+ this.graphPanel = graphPanel;
+ }
+
+ protected abstract W buildNewEdge(Vertex vertex, Vertex