Refactoring
- added more tests - added more interfaces for the visits - added satellite classes like Vertex - graph interface improved
This commit is contained in:
83
src/berack96/sim/util/graph/Edge.java
Normal file
83
src/berack96/sim/util/graph/Edge.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package berack96.sim.util.graph;
|
||||
|
||||
/**
|
||||
* Class used for retrieving the edges of the graph.
|
||||
*
|
||||
* @param <V> the vertices
|
||||
* @param <W> the weight of the edge
|
||||
* @author Berack96
|
||||
*/
|
||||
public class Edge<V, W extends Number> {
|
||||
|
||||
/**
|
||||
* The source vertex
|
||||
*/
|
||||
private final V source;
|
||||
/**
|
||||
* The destination vertex
|
||||
*/
|
||||
private final V destination;
|
||||
/**
|
||||
* The weight of this edge
|
||||
*/
|
||||
private final W weight;
|
||||
|
||||
/**
|
||||
* Create an final version of this object
|
||||
*
|
||||
* @param source the source of the edge
|
||||
* @param destination the destination of the edge
|
||||
* @param weight the weight od the edge
|
||||
*/
|
||||
public Edge(V source, V destination, W weight) {
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* The vertex where the edge goes
|
||||
*
|
||||
* @return the vertex
|
||||
*/
|
||||
public V getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* The vertex where the edge starts from
|
||||
*
|
||||
* @return the vertex
|
||||
*/
|
||||
public V getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* The weight of the edge
|
||||
*
|
||||
* @return the weight
|
||||
*/
|
||||
public W getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + source + " -> " + destination + ", " + weight + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
try {
|
||||
return obj.getClass().equals(getClass()) && obj.toString().equals(toString());
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
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.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,17 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
*/
|
||||
boolean isDAG();
|
||||
|
||||
/**
|
||||
* Get an instance of the vertex linked with this graph.<br>
|
||||
* 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<V> getVertex(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Add the vertex to the graph. If it's already in the graph it will be replaced.<br>
|
||||
* Of course the vertex added will have no edge to any other vertex nor form any other vertex.
|
||||
@@ -60,24 +72,23 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
boolean addVertexIfAbsent(V vertex) throws NullPointerException;
|
||||
|
||||
/**
|
||||
* Add all the vertices contained in the set to the graph.<br>
|
||||
* If a vertex is contained in the set and in the graph is ignored and it will not be replaced.<br>
|
||||
* Add all the vertices contained in the collection to the graph.<br>
|
||||
* If a vertex is contained in the collection and in the graph is ignored and it will not be replaced.<br>
|
||||
* Null vertices will be ignored and they will not be added to the graph.
|
||||
*
|
||||
* @param vertices a set containing the vertices
|
||||
* @param vertices a collection of the vertices to add
|
||||
* @throws NullPointerException if the set is null
|
||||
*/
|
||||
void addAllVertices(Set<V> vertices) throws NullPointerException;
|
||||
void addAllVertices(Collection<V> vertices) throws NullPointerException;
|
||||
|
||||
/**
|
||||
* Remove the selected vertex from the graph.<br>
|
||||
* 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
|
||||
* @throws IllegalArgumentException if the vertex is not contained in the graph
|
||||
* @throws NullPointerException if the vertex is null
|
||||
*/
|
||||
void removeVertex(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
void removeVertex(V vertex) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Remove all the vertex contained in the graph.<br>
|
||||
@@ -96,6 +107,63 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
*/
|
||||
boolean contains(V vertex) throws NullPointerException;
|
||||
|
||||
/**
|
||||
* Add to the specified vertex the mark passed.<br>
|
||||
* 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, String mark) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Remove the selected mark from the vertex.<br>
|
||||
*
|
||||
* @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, String mark) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Unmark the vertex selected.<br>
|
||||
* 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.<br>
|
||||
* If the vertex doesn't have any mark, then it will return an empty set.<br>
|
||||
* 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<String> 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(String mark) throws NullPointerException;
|
||||
|
||||
/**
|
||||
* Remove all the marker to all the vertex.<br>
|
||||
* 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.<br>
|
||||
* The edge will be created from the vertex V1 and the vertex V2<br>
|
||||
@@ -105,12 +173,25 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
* @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 value of the edge if there was already one
|
||||
* @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.<br>
|
||||
* The edge will be created from the vertex source of the edge and the vertex destination of it<br>
|
||||
* This method will overwrite any existing edge between the two vertex.<br>
|
||||
* 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<V, W> edge) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* This particular function add an edge to the graph.<br>
|
||||
* If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.<br>
|
||||
@@ -121,13 +202,26 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
* @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 value of the edge if there was already one
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* Add all the edges of the set in the graph.<br>
|
||||
* This particular function add an edge to the graph.<br>
|
||||
* If one of the two, or both vertices of the edge aren't contained in the graph, then the vertices will be added.<br>
|
||||
* The edge will be created from the vertex source of the edge and the vertex destination of it<br>
|
||||
* This method will overwrite any existing edge between the two vertex.<br>
|
||||
* 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<V, W> edge) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Add all the edges of the collection to the graph.<br>
|
||||
* If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.<br>
|
||||
* Any null edges will be ignored.<br>
|
||||
* This method will overwrite any existing edge between the two vertex.
|
||||
@@ -135,7 +229,7 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
* @param edges the edges to add
|
||||
* @throws NullPointerException if the set is null
|
||||
*/
|
||||
void addAllEdges(Set<Edge<V, W>> edges) throws NullPointerException;
|
||||
void addAllEdges(Collection<Edge<V, W>> edges) throws NullPointerException;
|
||||
|
||||
/**
|
||||
* Get the weight of the selected edge.<br>
|
||||
@@ -188,7 +282,7 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
*
|
||||
* @param vertex a vertex of the graph
|
||||
* @throws NullPointerException if the vertex is null
|
||||
* @throws IllegalArgumentException if the vertex is not contained in the graph
|
||||
* @throws IllegalArgumentException if one of the vertex is not contained in the graph
|
||||
*/
|
||||
void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
@@ -200,44 +294,66 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
|
||||
/**
|
||||
* Check if the edge between the two vertex passed is contained in the graph or not.<br>
|
||||
* An edge between V1 and V2 is contained in the graph if and only if i can travel from V1 to V2.
|
||||
* An edge between V1 and V2 is contained in the graph if and only if i can travel from V1 to V2.<br>
|
||||
* 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
|
||||
* @throws IllegalArgumentException if one of the vertex is not contained in the graph
|
||||
* @throws NullPointerException if one of the parameters is null
|
||||
*/
|
||||
boolean containsEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException;
|
||||
boolean containsEdge(V vertex1, V vertex2) throws NullPointerException;
|
||||
|
||||
/**
|
||||
* Get all the vertices in the graph.<br>
|
||||
* If the graph doesn't contains vertices, it'll return an empty set.<br>
|
||||
* Note that this set is completely different than the set used for the vertices, so any modification of this set will not change the graph.
|
||||
* If the graph doesn't contains vertices, it'll return an empty collection.<br>
|
||||
* 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 a set that include all the vertices
|
||||
* @return an array that include all the vertices
|
||||
*/
|
||||
Set<V> vertices();
|
||||
Collection<V> vertices();
|
||||
|
||||
/**
|
||||
* Get all the edges in the graph.<br>
|
||||
* If the graph doesn't contains edges, it'll return an empty set.<br>
|
||||
* Note that this set is completely different than the set used for the edges, so any modification of this set will not change the graph.
|
||||
* If the graph doesn't contains edges, it'll return an empty collection.<br>
|
||||
* 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 set that include all the edges
|
||||
* @return a collection that include all the edges
|
||||
*/
|
||||
Set<Edge<V, W>> edges();
|
||||
Collection<Edge<V, W>> edges();
|
||||
|
||||
/**
|
||||
* Retrieve all the edges from a particular vertex.<br>
|
||||
* Note: the edges that is returned are the edges that goes IN this vertex AND the edges that goes OUT of it.
|
||||
* Retrieve all the edges of a particular vertex.<br>
|
||||
* 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 set of edges
|
||||
* @return a collection of edges
|
||||
* @throws NullPointerException if the vertex is null
|
||||
* @throws IllegalArgumentException if the vertex is not contained in the graph
|
||||
*/
|
||||
Set<Edge<V, W>> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
Collection<Edge<V, W>> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Retrieve all the edges of a particular vertex.<br>
|
||||
* 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<Edge<V, W>> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Retrieve all the edges that goes OUT of a particular vertex.<br>
|
||||
* 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<Edge<V, W>> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get all the vertices that are children of the vertex passed as parameter.<br>
|
||||
@@ -245,34 +361,22 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
* where V1 is the source of that edge.
|
||||
*
|
||||
* @param vertex the source vertex
|
||||
* @return a set of vertices
|
||||
* @return an array of vertices
|
||||
* @throws NullPointerException if the vertex is null
|
||||
* @throws IllegalArgumentException if the vertex is not contained in the graph
|
||||
*/
|
||||
Set<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* This method will get all the child of the vertex selected.<br>
|
||||
* The map created will be a {@link java.util.LinkedHashMap LinkedHashMap}<br>
|
||||
* The order in which the vertex are iterated in the map will be from the vertex with the lowest weight to the one with the highest.
|
||||
*
|
||||
* @param vertex a vertex of the graph
|
||||
* @return a map of all the child and their respective weight
|
||||
* @throws NullPointerException if the vertex is null
|
||||
* @throws IllegalArgumentException if the vertex is not contained in the graph
|
||||
*/
|
||||
Map<V, W> getChildrenAndWeight(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
Collection<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Get all the vertices that have the vertex passed as their child.<br>
|
||||
* Basically is the opposite of {@link #getChildren(Object)}
|
||||
*
|
||||
* @param vertex a vertex of the graph
|
||||
* @return a set of ancestors of the vertex
|
||||
* @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
|
||||
*/
|
||||
Set<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
Collection<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tells the degree of all the edges that goes to this vertex.<br>
|
||||
@@ -333,7 +437,7 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
* @throws NullPointerException if one of the parameter is null (except the consumer)
|
||||
* @throws IllegalArgumentException if the vertex is not in the graph
|
||||
*/
|
||||
void visit(V source, VisitStrategy<V, W> strategy, Consumer<V> visit) throws NullPointerException, IllegalArgumentException;
|
||||
VisitInfo<V> visit(V source, VisitStrategy<V, W> strategy, Consumer<V> visit) throws NullPointerException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* This method will create a new Graph that is the transposed version of the original.<br>
|
||||
@@ -356,9 +460,9 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
/**
|
||||
* The strongly connected components or diconnected components of an arbitrary directed graph form a partition into subgraphs that are themselves strongly connected.
|
||||
*
|
||||
* @return a set containing the strongly connected components
|
||||
* @return a collection containing the strongly connected components
|
||||
*/
|
||||
Set<Set<V>> stronglyConnectedComponents();
|
||||
Collection<Collection<V>> stronglyConnectedComponents();
|
||||
|
||||
/**
|
||||
* Get a sub-graph of the current one based on the maximum depth that is given.<br>
|
||||
@@ -371,10 +475,21 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
* @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 null
|
||||
* @throws IllegalArgumentException if the vertex is not contained
|
||||
*/
|
||||
Graph<V, W> 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.<br>
|
||||
* Each vertex will have all his edges, but only the ones with the destination marked with the same marker.<br>
|
||||
* If the marker is null then the returning graph will have all the vertices that are not marked by any marker.<br>
|
||||
* 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<V, W> subGraph(String marker);
|
||||
|
||||
/**
|
||||
* Get the minimum path from the source vertex to the destination vertex.<br>
|
||||
* If the source vertex can't reach the destination, then an exception is thrown.
|
||||
@@ -400,75 +515,4 @@ public interface Graph<V, W extends Number> extends Iterable<V> {
|
||||
|
||||
// TODO maybe -> STATIC saveOnFile(orString) INSTANCE loadFromFile(orString), but need JSON parser
|
||||
// TODO maybe, but i don't think so... STATIC DISTANCE V* -> V*
|
||||
|
||||
/**
|
||||
* Class used for retrieving the edges of the graph.
|
||||
*
|
||||
* @param <V> the vertices
|
||||
* @param <W> the weight of the edge
|
||||
*/
|
||||
class Edge<V, W extends Number> {
|
||||
private final V source;
|
||||
private final V destination;
|
||||
private final W weight;
|
||||
|
||||
/**
|
||||
* Create an final version of this object
|
||||
*
|
||||
* @param source the source of the edge
|
||||
* @param destination the destination of the edge
|
||||
* @param weight the weight od the edge
|
||||
*/
|
||||
public Edge(V source, V destination, W weight) {
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* The vertex where the edge goes
|
||||
*
|
||||
* @return the vertex
|
||||
*/
|
||||
public V getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* The vertex where the edge starts from
|
||||
*
|
||||
* @return the vertex
|
||||
*/
|
||||
public V getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* The weight of the edge
|
||||
*
|
||||
* @return the weight
|
||||
*/
|
||||
public W getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + source + " -> " + destination + ", " + weight + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
try {
|
||||
return obj.getClass().equals(getClass()) && obj.toString().equals(toString());
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ 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.*;
|
||||
@@ -17,6 +18,7 @@ import java.util.function.Consumer;
|
||||
*
|
||||
* @param <V> the vertices
|
||||
* @param <W> the weight of the edges
|
||||
* @author Berack96
|
||||
*/
|
||||
public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
|
||||
@@ -27,6 +29,11 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
*/
|
||||
private final Map<V, Map<V, W>> edges = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Map that contains the vertex as key and all the marker as the value associated with that vertex.
|
||||
*/
|
||||
private final Map<V, Set<String>> marked = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Need this variable for not calculating each time the SCC or the cyclic part if the graph doesn't change
|
||||
*/
|
||||
@@ -47,6 +54,12 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
return !isCyclic();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vertex<V> getVertex(V vertex) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
return new Vertex<>(this, vertex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVertex(V vertex) throws NullPointerException {
|
||||
checkNull(vertex);
|
||||
@@ -63,18 +76,18 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllVertices(Set<V> vertices) throws NullPointerException {
|
||||
public void addAllVertices(Collection<V> vertices) throws NullPointerException {
|
||||
checkNull(vertices);
|
||||
vertices.forEach(this::addVertexIfAbsent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVertex(V vertex) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
|
||||
graphChanged();
|
||||
edges.remove(vertex);
|
||||
edges.forEach((v, map) -> map.remove(vertex));
|
||||
public void removeVertex(V vertex) throws NullPointerException {
|
||||
if (contains(vertex)) {
|
||||
graphChanged();
|
||||
edges.remove(vertex);
|
||||
edges.forEach((v, map) -> map.remove(vertex));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,6 +102,45 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
return edges.containsKey(vertex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(V vertex, String mark) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
checkNull(mark);
|
||||
|
||||
Set<String> set = marked.computeIfAbsent(vertex, (m) -> new HashSet<>());
|
||||
set.add(mark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unMark(V vertex, String 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<String> getMarks(V vertex) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
return marked.computeIfAbsent(vertex, (m) -> new HashSet<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unMarkAll(String 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);
|
||||
@@ -99,6 +151,11 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
return edges.get(vertex1).put(vertex2, weight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public W addEdge(Edge<V, W> 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);
|
||||
@@ -107,7 +164,12 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllEdges(Set<Edge<V, W>> edges) throws NullPointerException {
|
||||
public W addEdgeAndVertices(Edge<V, W> edge) throws NullPointerException, IllegalArgumentException {
|
||||
return addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllEdges(Collection<Edge<V, W>> edges) throws NullPointerException {
|
||||
edges.forEach((edge) -> addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight()));
|
||||
}
|
||||
|
||||
@@ -146,6 +208,7 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
|
||||
@Override
|
||||
public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
removeVertex(vertex);
|
||||
addVertex(vertex);
|
||||
}
|
||||
@@ -157,11 +220,8 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex1);
|
||||
checkNullAndExist(vertex2);
|
||||
|
||||
return edges.get(vertex1).get(vertex2) != null;
|
||||
public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException {
|
||||
return (contains(vertex1) && contains(vertex2)) && edges.get(vertex1).get(vertex2) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -188,6 +248,27 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Edge<V, W>> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
Collection<Edge<V, W>> 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<Edge<V, W>> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
Collection<Edge<V, W>> collection = new HashSet<>();
|
||||
edges.get(vertex).forEach((dest, weight) -> collection.add(new Edge<>(vertex, dest, weight)));
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<V> getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
@@ -195,13 +276,6 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
return new HashSet<>(edges.get(vertex).keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<V, W> getChildrenAndWeight(V vertex) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
|
||||
return new HashMap<>(edges.get(vertex));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<V> getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
|
||||
checkNullAndExist(vertex);
|
||||
@@ -252,8 +326,8 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(V source, VisitStrategy<V, W> strategy, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
strategy.visit(this, source, visit);
|
||||
public VisitInfo<V> visit(V source, VisitStrategy<V, W> strategy, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
return strategy.visit(this, source, visit);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -275,7 +349,7 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Set<V>> stronglyConnectedComponents() {
|
||||
public Collection<Collection<V>> stronglyConnectedComponents() {
|
||||
return getTarjan().getSCC();
|
||||
}
|
||||
|
||||
@@ -302,15 +376,16 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
vertices.add(child);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
strategy.visit(this, source, null);
|
||||
|
||||
sub.addAllVertices(vertices);
|
||||
for (V vertex : vertices)
|
||||
getChildrenAndWeight(vertex).forEach((child, weight) -> {
|
||||
getEdgesOut(vertex).forEach((edge) -> {
|
||||
try {
|
||||
sub.addEdge(vertex, child, weight);
|
||||
sub.addEdge(edge);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
});
|
||||
@@ -318,6 +393,35 @@ public class MapGraph<V, W extends Number> implements Graph<V, W> {
|
||||
return sub;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graph<V, W> subGraph(final String marker) {
|
||||
final Graph<V, W> graph = new MapGraph<>();
|
||||
final Set<V> allVertices = new HashSet<>();
|
||||
|
||||
marked.forEach((vertex, mark) -> {
|
||||
if (mark.contains(marker) || (marker == null && !mark.isEmpty()))
|
||||
allVertices.add(vertex);
|
||||
});
|
||||
|
||||
if (marker == null) {
|
||||
Collection<V> 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<Edge<V, W>> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
|
||||
checkNullAndExist(source);
|
||||
|
||||
264
src/berack96/sim/util/graph/Vertex.java
Normal file
264
src/berack96/sim/util/graph/Vertex.java
Normal file
@@ -0,0 +1,264 @@
|
||||
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.HashSet;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Class used for represent a vertex of the graph.<br>
|
||||
* The vertex contained is linked with the graph, so if any changes are made to
|
||||
* it, then they will be reflected here.
|
||||
*
|
||||
* @param <V> the vertex
|
||||
* @author Berack96
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class Vertex<V> {
|
||||
|
||||
public static final String REMOVED = "The vertex is no longer in the graph";
|
||||
|
||||
/**
|
||||
* The vertex associated
|
||||
*/
|
||||
private final V vertex;
|
||||
/**
|
||||
* The graph associated
|
||||
*/
|
||||
private final Graph<V, Number> graph;
|
||||
|
||||
/**
|
||||
* Get a Vertex linked with the graph
|
||||
*
|
||||
* @param graph the graph of the vertex
|
||||
* @param vertex the vertex
|
||||
* @throws NullPointerException if one of the param is null
|
||||
*/
|
||||
public Vertex(Graph<V, ?> graph, V vertex) throws NullPointerException {
|
||||
if (graph == null || vertex == null)
|
||||
throw new NullPointerException();
|
||||
this.graph = (Graph<V, Number>) graph;
|
||||
this.vertex = vertex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the vertex
|
||||
*
|
||||
* @return the vertex
|
||||
*/
|
||||
public V getValue() {
|
||||
return vertex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the vertex with the associated string
|
||||
*
|
||||
* @param mark the marker
|
||||
* @throws NullPointerException if the marker is null
|
||||
* @throws UnsupportedOperationException if the vertes is not in the graph anymore
|
||||
*/
|
||||
public void mark(String mark) throws NullPointerException, UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
graph.mark(vertex, mark);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all the marker from the vertex
|
||||
*
|
||||
* @throws UnsupportedOperationException if the vertes is not in the graph anymore
|
||||
*/
|
||||
public void unMark() throws UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
graph.unMark(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the marks that are associated with this vertex
|
||||
*
|
||||
* @return a set of marks
|
||||
* @throws UnsupportedOperationException if the vertes is not in the graph anymore
|
||||
*/
|
||||
public Collection<String> getMarks() throws UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
return graph.getMarks(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the vertex children of the current vertex
|
||||
*
|
||||
* @return all the children
|
||||
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
|
||||
*/
|
||||
public Collection<V> getChildren() throws UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
return graph.getChildren(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the children of this vertex like {@link #getChildren()}, but as {@link Vertex}.<br>
|
||||
* In this way they are linked to the graph as this one.<br>
|
||||
* * This method allocate a new object for each vertex, so it is more heavy.
|
||||
*
|
||||
* @return a collection of vertices that are children of the current one
|
||||
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
|
||||
*/
|
||||
public Collection<Vertex<V>> getChildrenAsVertex() throws UnsupportedOperationException {
|
||||
Collection<V> children = getChildren();
|
||||
Collection<Vertex<V>> toReturn = new HashSet<>();
|
||||
for (V vertex : children)
|
||||
toReturn.add(new Vertex<>(graph, vertex));
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the vertex ancestor of this vertex.<br>
|
||||
* The ancestors are all the vertices that have as destination this vertex.
|
||||
*
|
||||
* @return a collection of vertices
|
||||
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
|
||||
*/
|
||||
public Collection<V> getAncestors() throws UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
return graph.getAncestors(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the ancestors of this vertex like {@link #getAncestors()}, but as {@link Vertex}.<br>
|
||||
* In this way they are linked to the graph as this one.<br>
|
||||
* This method allocate a new object for each vertex, so it is more heavy.
|
||||
*
|
||||
* @return a collection of vertices that are children of the current one
|
||||
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
|
||||
*/
|
||||
public Collection<Vertex<V>> getAncestorsAsVertex() throws UnsupportedOperationException {
|
||||
Collection<V> ancestors = getAncestors();
|
||||
Collection<Vertex<V>> toReturn = new HashSet<>();
|
||||
for (V vertex : ancestors)
|
||||
toReturn.add(new Vertex<>(graph, vertex));
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the edge that goes OUT of this vertex
|
||||
*
|
||||
* @return a collection of edges with source this one
|
||||
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
|
||||
*/
|
||||
public Collection<Edge<V, Number>> getEdgesOut() throws UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
return graph.getEdgesOut(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the edge that goes INTO this vertex
|
||||
*
|
||||
* @return a collection of edges with destination this one
|
||||
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
|
||||
*/
|
||||
public Collection<Edge<V, Number>> getEdgesIn() throws UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
return graph.getEdgesIn(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child to this vertex.<br>
|
||||
* The added child must be in the graph or it will return an exception.
|
||||
*
|
||||
* @param child the destination vertex of this edge
|
||||
* @param weight the weight of the edge
|
||||
* @throws NullPointerException if the param is null
|
||||
* @throws IllegalArgumentException if the child vertex is not contained in the graph
|
||||
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
|
||||
*/
|
||||
public void addChild(V child, Number weight) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
graph.addEdge(vertex, child, weight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a child of this vertex.
|
||||
* If the vertex passed as param is not a child, then this call does nothing.
|
||||
*
|
||||
* @param child the child of the current vertex
|
||||
* @throws NullPointerException if the param is null
|
||||
* @throws IllegalArgumentException if the child vertex is not contained in the graph
|
||||
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
|
||||
*/
|
||||
public void removeChild(V child) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
graph.removeEdge(vertex, child);
|
||||
}
|
||||
|
||||
/**
|
||||
* This call tell if the current vertex is still contained in the graph linked.<br>
|
||||
* While this function return false all the other methods will throw an exception.
|
||||
*
|
||||
* @return true if it is, false otherwise
|
||||
*/
|
||||
public boolean isStillContained() {
|
||||
return graph.contains(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the vertex to the graph only if it's not already in the graph.
|
||||
*/
|
||||
public void addIfAbsent() {
|
||||
graph.addVertexIfAbsent(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the vertex from the graph.<br>
|
||||
* After this call all the other methods will throw an exception
|
||||
*/
|
||||
public void remove() {
|
||||
if (graph.contains(vertex))
|
||||
graph.removeVertex(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the graph from this current vertex with the strategy assigned
|
||||
*
|
||||
* @param strategy the strategy of the visit
|
||||
* @param visit the function to apply at each vertex (can be null)
|
||||
* @return an info of the visit if supported by the strategy
|
||||
* @throws NullPointerException if the strategy is null
|
||||
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
|
||||
*/
|
||||
public VisitInfo<V> visit(final VisitStrategy strategy, final Consumer<V> visit) throws NullPointerException, UnsupportedOperationException {
|
||||
throwIfNotContained();
|
||||
return graph.visit(vertex, (VisitStrategy<V, Number>) strategy, visit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return vertex.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return toString().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
try {
|
||||
return obj instanceof Vertex && (this.vertex.equals(obj) || this.vertex.equals(((Vertex) obj).vertex));
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for throwing the UnsupportedOperationException if the vertex is not contained anymore
|
||||
*
|
||||
* @throws UnsupportedOperationException if IllegalArgumentException is thrown by the runnable
|
||||
*/
|
||||
private void throwIfNotContained() throws UnsupportedOperationException {
|
||||
if (!graph.contains(vertex))
|
||||
throw new UnsupportedOperationException(REMOVED);
|
||||
}
|
||||
}
|
||||
@@ -11,42 +11,33 @@ import java.util.function.Consumer;
|
||||
*
|
||||
* @param <V> the vertex of the graph
|
||||
* @param <W> the weight of the graph
|
||||
* @author Berack96
|
||||
*/
|
||||
public class BFS<V, W extends Number> implements VisitStrategy<V, W> {
|
||||
|
||||
private VisitInfo<V> lastVisit = null;
|
||||
|
||||
/**
|
||||
* Retrieve the info of the last visit
|
||||
*
|
||||
* @return an info of the visit
|
||||
*/
|
||||
public VisitInfo<V> getLastVisit() {
|
||||
return lastVisit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
lastVisit = new VisitInfo<>(source);
|
||||
public VisitInfo<V> visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
VisitInfo<V> info = new VisitInfo<>(source);
|
||||
final LinkedList<V> toVisitChildren = new LinkedList<>();
|
||||
|
||||
toVisitChildren.push(source);
|
||||
if (visit != null)
|
||||
visit.accept(source);
|
||||
lastVisit.setVisited(source);
|
||||
info.setVisited(source);
|
||||
|
||||
while (!toVisitChildren.isEmpty()) {
|
||||
V current = toVisitChildren.removeFirst();
|
||||
|
||||
for (V child : graph.getChildren(current))
|
||||
if (!lastVisit.isDiscovered(child)) {
|
||||
if (!info.isDiscovered(child)) {
|
||||
toVisitChildren.addLast(child);
|
||||
|
||||
lastVisit.setVisited(child);
|
||||
lastVisit.setParent(current, child);
|
||||
info.setVisited(child);
|
||||
info.setParent(current, child);
|
||||
if (visit != null)
|
||||
visit.accept(child);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,23 +12,13 @@ import java.util.function.Consumer;
|
||||
*
|
||||
* @param <V> the vertex of the graph
|
||||
* @param <W> the weight of the graph
|
||||
* @author Berack96
|
||||
*/
|
||||
public class DFS<V, W extends Number> implements VisitStrategy<V, W> {
|
||||
|
||||
private VisitInfo<V> lastVisit = null;
|
||||
|
||||
/**
|
||||
* Retrieve the info of the last visit
|
||||
*
|
||||
* @return an info of the visit
|
||||
*/
|
||||
public VisitInfo<V> getLastVisit() {
|
||||
return lastVisit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
lastVisit = new VisitInfo<>(source);
|
||||
public VisitInfo<V> visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
VisitInfo<V> info = new VisitInfo<>(source);
|
||||
final Stack<V> toVisit = new Stack<>();
|
||||
|
||||
toVisit.push(source);
|
||||
@@ -40,19 +30,20 @@ public class DFS<V, W extends Number> implements VisitStrategy<V, W> {
|
||||
|
||||
while (iter.hasNext() && !hasChildToVisit) {
|
||||
V child = iter.next();
|
||||
if (!lastVisit.isDiscovered(child)) {
|
||||
if (!info.isDiscovered(child)) {
|
||||
hasChildToVisit = true;
|
||||
toVisit.push(child);
|
||||
lastVisit.setParent(current, child);
|
||||
info.setParent(current, child);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasChildToVisit) {
|
||||
toVisit.pop();
|
||||
lastVisit.setVisited(current);
|
||||
info.setVisited(current);
|
||||
if (visit != null)
|
||||
visit.accept(current);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,61 @@
|
||||
package berack96.sim.util.graph.visit;
|
||||
|
||||
import berack96.sim.util.graph.Edge;
|
||||
import berack96.sim.util.graph.Graph;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Dijkstra<V, W extends Number> implements VisitStrategy<V, W> {
|
||||
/**
|
||||
* Class that implements the Dijkstra algorithm and uses it for getting all the distance from a source
|
||||
*
|
||||
* @param <V> vertex
|
||||
* @param <W> weight
|
||||
* @author Berack96
|
||||
*/
|
||||
public class Dijkstra<V, W extends Number> implements VisitDistance<V, W> {
|
||||
|
||||
private Map<V, List<Graph.Edge<V, W>>> distance;
|
||||
private Map<V, List<Edge<V, W>>> distance = null;
|
||||
private V source = null;
|
||||
|
||||
/**
|
||||
* Get the last calculated distance to all the possible destinations<br>
|
||||
* The map contains all the possible vertices that are reachable from the source set in the visit<br>
|
||||
* If there is no path between the destination and the source, then null is returned as accordingly to the map interface<br>
|
||||
* If the visit is not already been done, then the map is null.
|
||||
*
|
||||
* @return the last distance
|
||||
*/
|
||||
public Map<V, List<Graph.Edge<V, W>>> getLastDistance() {
|
||||
@Override
|
||||
public Map<V, List<Edge<V, W>>> getLastDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
Queue<QueueEntry<V, Integer>> queue = new PriorityQueue<>();
|
||||
public V getLastSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VisitInfo<V> visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
VisitInfo<V> info = new VisitInfo<>(source);
|
||||
Queue<QueueEntry> queue = new PriorityQueue<>();
|
||||
Map<V, Integer> dist = new HashMap<>();
|
||||
Map<V, V> prev = new HashMap<>();
|
||||
|
||||
this.source = source;
|
||||
dist.put(source, 0); // Initialization
|
||||
queue.add(new QueueEntry<>(source, 0));
|
||||
queue.add(new QueueEntry(source, 0));
|
||||
|
||||
while (!queue.isEmpty()) { // The main loop
|
||||
QueueEntry<V, Integer> u = queue.poll(); // Remove and return best vertex
|
||||
graph.getChildrenAndWeight(u.entry).forEach((vertex, weight) -> {
|
||||
int alt = dist.get(u.entry) + weight.intValue();
|
||||
Integer distCurrent = dist.get(vertex);
|
||||
if (distCurrent == null || alt < distCurrent) {
|
||||
dist.put(vertex, alt);
|
||||
prev.put(vertex, u.entry);
|
||||
QueueEntry u = queue.poll(); // Remove and return best vertex
|
||||
|
||||
QueueEntry<V, Integer> current = new QueueEntry<>(vertex, alt);
|
||||
info.setVisited(u.entry);
|
||||
if (visit != null)
|
||||
visit.accept(u.entry);
|
||||
|
||||
graph.getEdgesOut(u.entry).forEach((edge) -> {
|
||||
V child = edge.getDestination();
|
||||
info.setDiscovered(child);
|
||||
int alt = dist.get(u.entry) + edge.getWeight().intValue();
|
||||
Integer distCurrent = dist.get(child);
|
||||
if (distCurrent == null || alt < distCurrent) {
|
||||
dist.put(child, alt);
|
||||
prev.put(child, u.entry);
|
||||
|
||||
QueueEntry current = new QueueEntry(child, alt);
|
||||
queue.remove(current);
|
||||
queue.add(current);
|
||||
}
|
||||
@@ -49,25 +65,27 @@ public class Dijkstra<V, W extends Number> implements VisitStrategy<V, W> {
|
||||
/* Cleaning up the results */
|
||||
distance = new HashMap<>();
|
||||
for (V vertex : prev.keySet()) {
|
||||
List<Graph.Edge<V, W>> path = new LinkedList<>();
|
||||
List<Edge<V, W>> path = new LinkedList<>();
|
||||
V child = vertex;
|
||||
V father = prev.get(child);
|
||||
do {
|
||||
Graph.Edge<V, W> edge = new Graph.Edge<>(father, child, graph.getWeight(father, child));
|
||||
Edge<V, W> edge = new Edge<>(father, child, graph.getWeight(father, child));
|
||||
path.add(0, edge);
|
||||
info.setParent(father, child);
|
||||
child = father;
|
||||
father = prev.get(child);
|
||||
} while (father != null);
|
||||
|
||||
distance.put(vertex, new ArrayList<>(path));
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
private class QueueEntry<V, W extends Number> implements Comparable<QueueEntry> {
|
||||
private class QueueEntry implements Comparable<QueueEntry> {
|
||||
final V entry;
|
||||
final W weight;
|
||||
final Integer weight;
|
||||
|
||||
QueueEntry(V entry, W weight) {
|
||||
QueueEntry(V entry, Integer weight) {
|
||||
this.entry = entry;
|
||||
this.weight = weight;
|
||||
}
|
||||
@@ -83,7 +101,7 @@ public class Dijkstra<V, W extends Number> implements VisitStrategy<V, W> {
|
||||
|
||||
@Override
|
||||
public int compareTo(QueueEntry queueEntry) {
|
||||
return this.weight.intValue() - queueEntry.weight.intValue();
|
||||
return this.weight - queueEntry.weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,71 +5,77 @@ import berack96.sim.util.graph.Graph;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Tarjan<V, W extends Number> implements VisitStrategy<V, W> {
|
||||
/**
|
||||
* Class that implements the Tarjan algorithm and uses it for getting the SCC and the topological sort
|
||||
*
|
||||
* @param <V> vertex
|
||||
* @param <W> weight
|
||||
* @author Berack96
|
||||
*/
|
||||
public class Tarjan<V, W extends Number> implements VisitSCC<V, W>, VisitTopological<V, W> {
|
||||
|
||||
private Set<Set<V>> SCC = null;
|
||||
private Collection<Collection<V>> SCC = null;
|
||||
private List<V> topologicalSort = null;
|
||||
|
||||
private Map<V, Integer> indices = null;
|
||||
private Map<V, Integer> lowLink = null;
|
||||
private Stack<V> stack = null;
|
||||
private VisitInfo<V> info = null;
|
||||
|
||||
/**
|
||||
* Return the latest calculated strongly connected components of the graph.
|
||||
*
|
||||
* @return the latest SCC
|
||||
*/
|
||||
public Set<Set<V>> getSCC() {
|
||||
@Override
|
||||
public Collection<Collection<V>> getSCC() {
|
||||
return SCC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the latest calculated Topological sort of the graph.<br>
|
||||
* If the latest visited graph is not a DAG, it will return null.
|
||||
*
|
||||
* @return the topological order of the DAG
|
||||
*/
|
||||
@Override
|
||||
public List<V> getTopologicalSort() {
|
||||
return topologicalSort;
|
||||
}
|
||||
|
||||
/**
|
||||
* This particular visit strategy use only the graph, so the other parameters are useless.
|
||||
* This particular visit strategy use only the graph and the visit, so the source param is not needed.
|
||||
*
|
||||
* @param graph the graph to visit
|
||||
* @param source the source of the visit
|
||||
* @param source not needed
|
||||
* @param visit the function to apply at each vertex when they are visited
|
||||
* @throws NullPointerException if the graph is null
|
||||
* @throws IllegalArgumentException doesn't throw this
|
||||
*/
|
||||
@Override
|
||||
public void visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
public VisitInfo<V> visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException {
|
||||
SCC = new HashSet<>();
|
||||
topologicalSort = new LinkedList<>();
|
||||
info = null;
|
||||
|
||||
indices = new HashMap<>();
|
||||
lowLink = new HashMap<>();
|
||||
stack = new Stack<>();
|
||||
Integer index = 0;
|
||||
|
||||
for (V vertex : graph)
|
||||
for (V vertex : graph) {
|
||||
if (info == null)
|
||||
info = new VisitInfo<>(vertex);
|
||||
if (!indices.containsKey(vertex))
|
||||
strongConnect(graph, vertex, index);
|
||||
strongConnect(graph, vertex, index, visit);
|
||||
}
|
||||
|
||||
topologicalSort = (graph.numberOfVertices() == SCC.size()) ? new ArrayList<>(topologicalSort) : null;
|
||||
return info;
|
||||
}
|
||||
|
||||
private void strongConnect(Graph<V, W> graph, V vertex, Integer index) {
|
||||
private void strongConnect(Graph<V, W> graph, V vertex, Integer index, Consumer<V> visit) {
|
||||
// Set the depth index for v to the smallest unused index
|
||||
indices.put(vertex, index);
|
||||
lowLink.put(vertex, index);
|
||||
index++;
|
||||
stack.push(vertex);
|
||||
info.setDiscovered(vertex);
|
||||
|
||||
// Consider successors of v
|
||||
for (V child : graph.getChildren(vertex)) {
|
||||
if (!indices.containsKey(child)) {
|
||||
strongConnect(graph, child, index);
|
||||
info.setParent(vertex, child);
|
||||
strongConnect(graph, child, index, visit);
|
||||
lowLink.put(vertex, Math.min(lowLink.get(vertex), lowLink.get(child)));
|
||||
} else if (stack.contains(child)) {
|
||||
// Successor w is in stack S and hence in the current SCC
|
||||
@@ -88,6 +94,11 @@ public class Tarjan<V, W extends Number> implements VisitStrategy<V, W> {
|
||||
temp = stack.pop();
|
||||
topologicalSort.add(0, temp);
|
||||
newComponent.add(temp);
|
||||
|
||||
info.setVisited(temp);
|
||||
if (visit != null)
|
||||
visit.accept(temp);
|
||||
|
||||
} while (!temp.equals(vertex));
|
||||
|
||||
SCC.add(newComponent);
|
||||
|
||||
29
src/berack96/sim/util/graph/visit/VisitDistSourceDest.java
Normal file
29
src/berack96/sim/util/graph/visit/VisitDistSourceDest.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package berack96.sim.util.graph.visit;
|
||||
|
||||
import berack96.sim.util.graph.Edge;
|
||||
import berack96.sim.util.graph.Graph;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Interface that is helpful for implements visit that needs to retrieve the distance between a vertex to all the others
|
||||
*
|
||||
* @param <V> the vertex
|
||||
* @param <W> the weight
|
||||
* @author Berack96
|
||||
*/
|
||||
public interface VisitDistSourceDest<V, W extends Number> extends VisitStrategy<V, W> {
|
||||
|
||||
/**
|
||||
* Get the distance from the source to the destination<br>
|
||||
* The list contains the minimum path from the vertex marked as source to the destination vertex
|
||||
*
|
||||
* @param graph the graph were to find the min path
|
||||
* @param source the source vertex
|
||||
* @param destination the destination vertex
|
||||
* @return the distance
|
||||
* @throws NullPointerException if one of the vertex is null
|
||||
* @throws IllegalArgumentException if one of the vertex is not contained in the graph
|
||||
*/
|
||||
List<Edge<V, W>> distance(Graph graph, V source, V destination) throws NullPointerException, IllegalArgumentException;
|
||||
}
|
||||
35
src/berack96/sim/util/graph/visit/VisitDistance.java
Normal file
35
src/berack96/sim/util/graph/visit/VisitDistance.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package berack96.sim.util.graph.visit;
|
||||
|
||||
import berack96.sim.util.graph.Edge;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Interface that is helpful for implements visit that needs to retrieve the distance between a vertex to all the others
|
||||
*
|
||||
* @param <V> the vertex
|
||||
* @param <W> the weight
|
||||
* @author Berack96
|
||||
*/
|
||||
public interface VisitDistance<V, W extends Number> extends VisitStrategy<V, W> {
|
||||
|
||||
/**
|
||||
* Get the last calculated distance to all the possible destinations<br>
|
||||
* The map contains all the possible vertices that are reachable from the source set in the visit<br>
|
||||
* If there is no path between the destination and the source, then null is returned as accordingly to the map interface<br>
|
||||
* If the visit is not already been done, then the map is null.
|
||||
*
|
||||
* @return the last distance
|
||||
* @throws NullPointerException if the visit is not already been done
|
||||
*/
|
||||
Map<V, List<Edge<V, W>>> getLastDistance() throws NullPointerException;
|
||||
|
||||
/**
|
||||
* Get the last source vertex of the visit for calculating the destinations.<br>
|
||||
* Returns null if the visit is not already been done
|
||||
*
|
||||
* @return the last vertex
|
||||
*/
|
||||
V getLastSource();
|
||||
}
|
||||
266
src/berack96/sim/util/graph/visit/VisitInfo.java
Normal file
266
src/berack96/sim/util/graph/visit/VisitInfo.java
Normal file
@@ -0,0 +1,266 @@
|
||||
package berack96.sim.util.graph.visit;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* The class used for getting the info of the visit.<br>
|
||||
* It could be used with the algorithm of the visit for set some useful data.
|
||||
*
|
||||
* @param <V> the vertex of the visit
|
||||
* @author Berack96
|
||||
*/
|
||||
public class VisitInfo<V> {
|
||||
private final Map<V, Long> discovered;
|
||||
private final Map<V, Long> visited;
|
||||
private final Map<V, V> parent;
|
||||
private final V source;
|
||||
private long time;
|
||||
|
||||
/**
|
||||
* Need a source for initialize the basic values
|
||||
*
|
||||
* @param source the source of the visit
|
||||
* @throws NullPointerException if the source is null
|
||||
*/
|
||||
public VisitInfo(V source) {
|
||||
if (source == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
discovered = new Hashtable<>();
|
||||
visited = new Hashtable<>();
|
||||
parent = new Hashtable<>();
|
||||
|
||||
this.time = 0;
|
||||
this.source = source;
|
||||
setDiscovered(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time of the vertex when it is discovered in the visit.<br>
|
||||
* For "discovered" i mean when the node is first found by the visit algorithm. It may depends form {@link VisitStrategy}<br>
|
||||
* The time starts at 0 and for each vertex discovered it is increased by one. If a vertex is visited it also increase the time<br>
|
||||
*
|
||||
* @param vertex the vertex needed
|
||||
* @return the time of it's discovery
|
||||
* @throws IllegalArgumentException if the vertex is not discovered
|
||||
* @throws NullPointerException if the vertex is null
|
||||
*/
|
||||
public long getTimeDiscover(V vertex) throws IllegalArgumentException, NullPointerException {
|
||||
Long time = discovered.get(vertex);
|
||||
if (time == null)
|
||||
throw new IllegalArgumentException();
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time when the vertex is visited by the algorithm<br>
|
||||
* For "visited" i mean when the node is finally visited by the visit algorithm. It may depends form {@link VisitStrategy}<br>
|
||||
* The time starts at 0 and for each vertex discovered or visited is increased by one<br>
|
||||
*
|
||||
* @param vertex the vertex needed
|
||||
* @return the time of it's visit
|
||||
* @throws IllegalArgumentException if the vertex is not visited
|
||||
* @throws NullPointerException if the vertex is null
|
||||
*/
|
||||
public long getTimeVisit(V vertex) throws IllegalArgumentException, NullPointerException {
|
||||
Long time = visited.get(vertex);
|
||||
if (time == null)
|
||||
throw new IllegalArgumentException();
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if a vertex is discovered or not
|
||||
*
|
||||
* @param vertex the vertex chosen
|
||||
* @return true if is discovered
|
||||
*/
|
||||
public boolean isDiscovered(V vertex) throws NullPointerException {
|
||||
try {
|
||||
return discovered.containsKey(vertex);
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the vertex is visited or not
|
||||
*
|
||||
* @param vertex the vertex chosen
|
||||
* @return true if is visited
|
||||
*/
|
||||
public boolean isVisited(V vertex) throws NullPointerException {
|
||||
try {
|
||||
return visited.containsKey(vertex);
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a vertex as "visited". After this call the vertex is set as discovered (if not already) and visited.<br>
|
||||
* Next this call it will be possible to get the time of visit of that vertex<br>
|
||||
* Does nothing if the vertex is already been visited.
|
||||
*
|
||||
* @param vertex the vertex that has been visited
|
||||
*/
|
||||
synchronized void setVisited(V vertex) {
|
||||
setDiscovered(vertex);
|
||||
if (!visited.containsKey(vertex))
|
||||
visited.put(vertex, time++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a vertex as "discovered". After this call the vertex is set as discovered and it will be possible to get the time of it's discovery<br>
|
||||
* Does nothing if the vertex is already been discovered.
|
||||
*
|
||||
* @param vertex the vertex that has been discovered
|
||||
*/
|
||||
synchronized void setDiscovered(V vertex) {
|
||||
if (!discovered.containsKey(vertex))
|
||||
discovered.put(vertex, time++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parent of a particular vertex<br>
|
||||
* The parent of a vertex is the one that has discovered it<br>
|
||||
* If the target vertex is not already discovered, then {@link #setDiscovered(Object)} is called<br>
|
||||
*
|
||||
* @param parent the vertex that is the parent
|
||||
* @param child the vertex discovered
|
||||
* @throws IllegalArgumentException if the parent is not already discovered
|
||||
*/
|
||||
synchronized void setParent(V parent, V child) throws IllegalArgumentException {
|
||||
if (!isDiscovered(parent))
|
||||
throw new IllegalArgumentException(parent.toString());
|
||||
|
||||
setDiscovered(child);
|
||||
this.parent.putIfAbsent(child, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source of the visit.
|
||||
*
|
||||
* @return the source vertex where it's started the visit
|
||||
*/
|
||||
public V getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent of a particular vertex.<br>
|
||||
* The parent of a vertex is the one that has discovered it<br>
|
||||
* If the vertex has no parent (it has not been set by the visit algorithm or it's the source) then null is returned.
|
||||
*
|
||||
* @param vertex the child vertex
|
||||
* @return the parent of the child
|
||||
* @throws IllegalArgumentException if the vertex has not been discovered yet
|
||||
*/
|
||||
public V getParentOf(V vertex) throws IllegalArgumentException {
|
||||
if (isDiscovered(vertex))
|
||||
return parent.get(vertex);
|
||||
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the visited vertices so far.
|
||||
*
|
||||
* @return the visited vertices
|
||||
*/
|
||||
public Set<V> getVisited() {
|
||||
return visited.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the discovered vertices so far.
|
||||
*
|
||||
* @return the discovered vertices
|
||||
*/
|
||||
public Set<V> getDiscovered() {
|
||||
return discovered.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all the vertices that are discovered.<br>
|
||||
* The vertices will be ordered by the time of their discover.
|
||||
*
|
||||
* @param consumer the function to apply to each
|
||||
*/
|
||||
public void forEachDiscovered(Consumer<VertexInfo> consumer) {
|
||||
Set<V> vertices = getDiscovered();
|
||||
Queue<VertexInfo> queue = new PriorityQueue<>();
|
||||
|
||||
vertices.forEach((vertex) -> queue.offer(new VertexInfo(vertex, getParentOf(vertex), getTimeDiscover(vertex), isVisited(vertex) ? getTimeVisit(vertex) : -1, false)));
|
||||
|
||||
while (!queue.isEmpty())
|
||||
consumer.accept(queue.poll());
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all the vertices that are visited.<br>
|
||||
* The vertices will be ordered by the time of their visit.
|
||||
*
|
||||
* @param consumer the function to apply to each
|
||||
*/
|
||||
public void forEachVisited(Consumer<VertexInfo> consumer) {
|
||||
Set<V> vertices = getVisited();
|
||||
Queue<VertexInfo> queue = new PriorityQueue<>();
|
||||
|
||||
vertices.forEach((vertex) -> queue.offer(new VertexInfo(vertex, getParentOf(vertex), getTimeDiscover(vertex), getTimeVisit(vertex), true)));
|
||||
|
||||
while (!queue.isEmpty())
|
||||
consumer.accept(queue.poll());
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all the vertices discovered and visited with the correct timeline.<br>
|
||||
* The vertices will be visited in the order that they are discovered and visited, so a vertex can appear two times (one for the discovery, anc the other for the visit)
|
||||
*
|
||||
* @param consumer the function to apply at each vertex
|
||||
*/
|
||||
public void forEach(Consumer<VertexInfo> consumer) {
|
||||
Set<V> discovered = getDiscovered();
|
||||
Set<V> visited = getVisited();
|
||||
Queue<VertexInfo> queue = new PriorityQueue<>();
|
||||
|
||||
discovered.forEach((vertex) -> queue.offer(new VertexInfo(vertex, getParentOf(vertex), getTimeDiscover(vertex), getTimeVisit(vertex), false)));
|
||||
visited.forEach((vertex) -> queue.offer(new VertexInfo(vertex, getParentOf(vertex), getTimeDiscover(vertex), getTimeVisit(vertex), true)));
|
||||
|
||||
while (!queue.isEmpty())
|
||||
consumer.accept(queue.remove());
|
||||
}
|
||||
|
||||
/**
|
||||
* Class used mainly for storing the data of the visit
|
||||
*/
|
||||
public class VertexInfo implements Comparable<VertexInfo> {
|
||||
public final V vertex;
|
||||
public final V parent;
|
||||
public final long timeDiscovered;
|
||||
public final long timeVisited;
|
||||
private final boolean compareVisited;
|
||||
|
||||
private VertexInfo(V vertex, V parent, long timeDiscovered, long timeVisited, boolean compareVisited) {
|
||||
this.vertex = vertex;
|
||||
this.parent = parent;
|
||||
this.timeDiscovered = timeDiscovered;
|
||||
this.timeVisited = timeVisited;
|
||||
this.compareVisited = compareVisited;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(VertexInfo other) {
|
||||
long compareThis = compareVisited ? timeVisited : timeDiscovered;
|
||||
long compareOther = other.compareVisited ? other.timeVisited : other.timeDiscovered;
|
||||
|
||||
return (int) (compareThis - compareOther);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s -> %s [D:%3d, V:%3d]", parent, vertex, timeDiscovered, timeVisited);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/berack96/sim/util/graph/visit/VisitSCC.java
Normal file
21
src/berack96/sim/util/graph/visit/VisitSCC.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package berack96.sim.util.graph.visit;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Interface that is helpful for implements visit that needs to retrieve the SCC
|
||||
*
|
||||
* @param <V> the vertex
|
||||
* @param <W> the weight
|
||||
* @author Berack96
|
||||
*/
|
||||
public interface VisitSCC<V, W extends Number> extends VisitStrategy<V, W> {
|
||||
|
||||
/**
|
||||
* Return the latest calculated strongly connected components of the graph.
|
||||
*
|
||||
* @return the latest SCC
|
||||
* @throws NullPointerException if there is no last calculated SCC
|
||||
*/
|
||||
Collection<Collection<V>> getSCC();
|
||||
}
|
||||
@@ -2,8 +2,6 @@ package berack96.sim.util.graph.visit;
|
||||
|
||||
import berack96.sim.util.graph.Graph;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -23,171 +21,10 @@ public interface VisitStrategy<V, W extends Number> {
|
||||
* @param graph the graph to visit
|
||||
* @param source the source of the visit
|
||||
* @param visit the function to apply at each vertex when they are visited
|
||||
* @return an info of the view
|
||||
* @throws NullPointerException if one of the arguments is null (only the consumers can be null)
|
||||
* @throws IllegalArgumentException if the source vertex is not in the graph
|
||||
* @throws UnsupportedOperationException in the case that the visit algorithm cannot be applied to the graph
|
||||
*/
|
||||
void visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException;
|
||||
|
||||
/**
|
||||
* The class used for getting the info of the visit.<br>
|
||||
* It could be used with the algorithm of the visit for set some useful data.
|
||||
*
|
||||
* @param <V> the vertex of the visit
|
||||
* @author Berack96
|
||||
*/
|
||||
class VisitInfo<V> {
|
||||
private final Map<V, Long> discovered;
|
||||
private final Map<V, Long> visited;
|
||||
private final Map<V, V> parent;
|
||||
private final V source;
|
||||
private long time;
|
||||
|
||||
/**
|
||||
* Need a source for initialize the basic values
|
||||
*
|
||||
* @param source the source of the visit
|
||||
* @throws NullPointerException if the source is null
|
||||
*/
|
||||
public VisitInfo(V source) {
|
||||
if (source == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
discovered = new Hashtable<>();
|
||||
visited = new Hashtable<>();
|
||||
parent = new Hashtable<>();
|
||||
|
||||
this.time = 0;
|
||||
this.source = source;
|
||||
setDiscovered(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time of the vertex when it is discovered in the visit.<br>
|
||||
* For "discovered" i mean when the node is first found by the visit algorithm. It may depends form {@link VisitStrategy}<br>
|
||||
* The time starts at 0 and for each vertex discovered it is increased by one. If a vertex is visited it also increase the time<br>
|
||||
*
|
||||
* @param vertex the vertex needed
|
||||
* @return the time of it's discovery
|
||||
* @throws IllegalArgumentException if the vertex is not discovered
|
||||
* @throws NullPointerException if the vertex is null
|
||||
*/
|
||||
public long getTimeDiscover(V vertex) throws IllegalArgumentException, NullPointerException {
|
||||
Long time = discovered.get(vertex);
|
||||
if (time == null)
|
||||
throw new IllegalArgumentException();
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time when the vertex is visited by the algorithm<br>
|
||||
* For "visited" i mean when the node is finally visited by the visit algorithm. It may depends form {@link VisitStrategy}<br>
|
||||
* The time starts at 0 and for each vertex discovered or visited is increased by one<br>
|
||||
*
|
||||
* @param vertex the vertex needed
|
||||
* @return the time of it's visit
|
||||
* @throws IllegalArgumentException if the vertex is not visited
|
||||
* @throws NullPointerException if the vertex is null
|
||||
*/
|
||||
public long getTimeVisit(V vertex) throws IllegalArgumentException, NullPointerException {
|
||||
Long time = visited.get(vertex);
|
||||
if (time == null)
|
||||
throw new IllegalArgumentException();
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if a vertex is discovered or not
|
||||
*
|
||||
* @param vertex the vertex chosen
|
||||
* @return true if is discovered
|
||||
*/
|
||||
public boolean isDiscovered(V vertex) throws NullPointerException {
|
||||
try {
|
||||
return discovered.containsKey(vertex);
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the vertex is visited or not
|
||||
*
|
||||
* @param vertex the vertex chosen
|
||||
* @return true if is visited
|
||||
*/
|
||||
public boolean isVisited(V vertex) throws NullPointerException {
|
||||
try {
|
||||
return visited.containsKey(vertex);
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a vertex as "visited". After this call the vertex is set as discovered (if not already) and visited.<br>
|
||||
* Next this call it will be possible to get the time of visit of that vertex<br>
|
||||
* Does nothing if the vertex is already been visited.
|
||||
*
|
||||
* @param vertex the vertex that has been visited
|
||||
*/
|
||||
public synchronized void setVisited(V vertex) {
|
||||
setDiscovered(vertex);
|
||||
if (!visited.containsKey(vertex))
|
||||
visited.put(vertex, time++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a vertex as "discovered". After this call the vertex is set as discovered and it will be possible to get the time of it's discovery<br>
|
||||
* Does nothing if the vertex is already been discovered.
|
||||
*
|
||||
* @param vertex the vertex that has been discovered
|
||||
*/
|
||||
public synchronized void setDiscovered(V vertex) {
|
||||
if (!discovered.containsKey(vertex))
|
||||
discovered.put(vertex, time++);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parent of a particular vertex<br>
|
||||
* The parent of a vertex is the one that has discovered it<br>
|
||||
* If the target vertex is not already discovered, then {@link #setDiscovered(Object)} is called<br>
|
||||
*
|
||||
* @param parent the vertex that is the parent
|
||||
* @param child the vertex discovered
|
||||
* @throws IllegalArgumentException if the parent is not already discovered
|
||||
*/
|
||||
public synchronized void setParent(V parent, V child) throws IllegalArgumentException {
|
||||
if (!isDiscovered(parent))
|
||||
throw new IllegalArgumentException(parent.toString());
|
||||
|
||||
setDiscovered(child);
|
||||
this.parent.putIfAbsent(child, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source of the visit.
|
||||
*
|
||||
* @return the source vertex where it's started the visit
|
||||
*/
|
||||
public V getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent of a particular vertex.<br>
|
||||
* The parent of a vertex is the one that has discovered it<br>
|
||||
* If the vertex has no parent (it has not been set by the visit algorithm or it's the source) then null is returned.
|
||||
*
|
||||
* @param vertex the child vertex
|
||||
* @return the parent of the child
|
||||
* @throws IllegalArgumentException if the vertex has not been discovered yet
|
||||
*/
|
||||
public V getParentOf(V vertex) throws IllegalArgumentException {
|
||||
if (isDiscovered(vertex))
|
||||
return parent.get(vertex);
|
||||
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
VisitInfo<V> visit(Graph<V, W> graph, V source, Consumer<V> visit) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException;
|
||||
}
|
||||
|
||||
22
src/berack96/sim/util/graph/visit/VisitTopological.java
Normal file
22
src/berack96/sim/util/graph/visit/VisitTopological.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package berack96.sim.util.graph.visit;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Interface that is helpful for implements visit that needs to retrieve the topological sort
|
||||
*
|
||||
* @param <V> the vertex
|
||||
* @param <W> the weight
|
||||
* @author Berack96
|
||||
*/
|
||||
public interface VisitTopological<V, W extends Number> extends VisitStrategy<V, W> {
|
||||
|
||||
/**
|
||||
* Return the latest calculated Topological sort of the graph.<br>
|
||||
* If the latest visited graph is not a DAG, it will return null.
|
||||
*
|
||||
* @return the topological order of the DAG
|
||||
* @throws NullPointerException if there is no last calculated topological sort
|
||||
*/
|
||||
List<V> getTopologicalSort();
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
package berack96.test.sim;
|
||||
|
||||
import berack96.sim.util.graph.Edge;
|
||||
import berack96.sim.util.graph.Graph;
|
||||
import berack96.sim.util.graph.MapGraph;
|
||||
import berack96.sim.util.graph.Vertex;
|
||||
import berack96.sim.util.graph.visit.BFS;
|
||||
import berack96.sim.util.graph.visit.DFS;
|
||||
import berack96.sim.util.graph.visit.VisitStrategy;
|
||||
import berack96.sim.util.graph.visit.VisitInfo;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -18,6 +21,7 @@ public class TestGraph {
|
||||
|
||||
private final Exception nullException = new NullPointerException(Graph.PARAM_NULL);
|
||||
private final Exception notException = new IllegalArgumentException(Graph.VERTEX_NOT_CONTAINED);
|
||||
private final Exception unsuppException = new UnsupportedOperationException(Vertex.REMOVED);
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
@@ -90,6 +94,10 @@ public class TestGraph {
|
||||
shouldThrow(nullException, () -> graph.addEdge(null, "2", 1));
|
||||
shouldThrow(nullException, () -> graph.addEdge(null, null, 1));
|
||||
shouldThrow(nullException, () -> graph.addEdge("1", null, 1));
|
||||
shouldThrow(new NullPointerException(), () -> graph.addEdge(null));
|
||||
shouldThrow(nullException, () -> graph.addEdge(new Edge<>("1", null, 1)));
|
||||
shouldThrow(nullException, () -> graph.addEdge(new Edge<>(null, null, 1)));
|
||||
shouldThrow(nullException, () -> graph.addEdge(new Edge<>(null, "2", 1)));
|
||||
shouldThrow(nullException, () -> graph.containsEdge(null, "2"));
|
||||
shouldThrow(nullException, () -> graph.containsEdge(null, null));
|
||||
shouldThrow(nullException, () -> graph.containsEdge("1", null));
|
||||
@@ -103,9 +111,6 @@ public class TestGraph {
|
||||
shouldThrow(notException, () -> graph.addEdge("0", "2", 1));
|
||||
shouldThrow(notException, () -> graph.addEdge("2", "8", 1));
|
||||
shouldThrow(notException, () -> graph.addEdge("9", "6", 1));
|
||||
shouldThrow(notException, () -> graph.containsEdge("01", "4"));
|
||||
shouldThrow(notException, () -> graph.containsEdge("3", "8132"));
|
||||
shouldThrow(notException, () -> graph.containsEdge("9423", "516"));
|
||||
shouldThrow(notException, () -> graph.removeEdge("012", "2"));
|
||||
shouldThrow(notException, () -> graph.removeEdge("2", "28"));
|
||||
shouldThrow(notException, () -> graph.removeEdge("4329", "62"));
|
||||
@@ -116,14 +121,18 @@ public class TestGraph {
|
||||
assertEquals(0, graph.numberOfEdges());
|
||||
|
||||
assertNull(graph.addEdge("1", "2", 1));
|
||||
assertNull(graph.addEdge("1", "3", 1));
|
||||
assertNull(graph.addEdge(new Edge<>("1", "3", 1)));
|
||||
assertNull(graph.addEdge("2", "5", 4));
|
||||
assertNull(graph.addEdge("3", "5", 2));
|
||||
assertNull(graph.addEdge("5", "3", 2));
|
||||
assertNull(graph.addEdge(new Edge<>("3", "5", 2)));
|
||||
assertNull(graph.addEdge(new Edge<>("5", "3", 2)));
|
||||
assertNull(graph.addEdge("5", "4", 3));
|
||||
|
||||
assertEquals(6, graph.numberOfEdges());
|
||||
|
||||
assertFalse(graph.containsEdge("01", "4"));
|
||||
assertFalse(graph.containsEdge("3", "8132"));
|
||||
assertFalse(graph.containsEdge("9423", "516"));
|
||||
|
||||
// All this calls should do nothing
|
||||
graph.removeEdge("1", "5");
|
||||
graph.removeEdge("1", "4");
|
||||
@@ -145,6 +154,9 @@ public class TestGraph {
|
||||
assertEquals(new Integer(1), graph.addEdge("1", "2", 102));
|
||||
assertEquals(new Integer(102), graph.addEdge("1", "2", 3));
|
||||
assertEquals(new Integer(3), graph.addEdge("1", "2", 1));
|
||||
assertEquals(new Integer(1), graph.addEdge(new Edge<>("1", "2", 102)));
|
||||
assertEquals(new Integer(102), graph.addEdge(new Edge<>("1", "2", 3)));
|
||||
assertEquals(new Integer(3), graph.addEdge(new Edge<>("1", "2", 1)));
|
||||
|
||||
assertEquals(6, graph.numberOfEdges());
|
||||
assertTrue(graph.containsEdge("1", "2"));
|
||||
@@ -196,19 +208,45 @@ public class TestGraph {
|
||||
assertFalse(graph.containsEdge("5", "4"));
|
||||
assertEquals(0, graph.numberOfEdges());
|
||||
|
||||
shouldThrow(notException, () -> graph.containsEdge("2", "323"));
|
||||
graph.addEdgeAndVertices("2", "323", 3);
|
||||
assertFalse(graph.containsEdge("2", "323"));
|
||||
assertNull(graph.addEdgeAndVertices("2", "323", 3));
|
||||
assertTrue(graph.containsEdge("2", "323"));
|
||||
shouldThrow(notException, () -> graph.containsEdge("2aa", "323"));
|
||||
graph.addEdgeAndVertices("2aa", "323", 3);
|
||||
assertFalse(graph.containsEdge("2aa", "323"));
|
||||
assertNull(graph.addEdgeAndVertices("2aa", "323", 35));
|
||||
assertTrue(graph.containsEdge("2aa", "323"));
|
||||
shouldThrow(notException, () -> graph.containsEdge("2bbb", "323bbb"));
|
||||
graph.addEdgeAndVertices("2bbb", "323bbb", 3);
|
||||
assertFalse(graph.containsEdge("2bbb", "323bbb"));
|
||||
assertNull(graph.addEdgeAndVertices("2bbb", "323bbb", 135));
|
||||
assertTrue(graph.containsEdge("2bbb", "323bbb"));
|
||||
|
||||
shouldThrow(nullException, () -> graph.addEdgeAndVertices(null, "1", 1));
|
||||
shouldThrow(nullException, () -> graph.addEdgeAndVertices(null, null, 1));
|
||||
shouldThrow(nullException, () -> graph.addEdgeAndVertices("2", null, 1));
|
||||
|
||||
assertEquals(3, graph.addEdgeAndVertices("2", "323", 50).intValue());
|
||||
assertEquals(35, graph.addEdgeAndVertices("2aa", "323", 5).intValue());
|
||||
assertEquals(50, graph.addEdgeAndVertices("2", "323", 500).intValue());
|
||||
|
||||
graph.removeAllEdge();
|
||||
|
||||
assertFalse(graph.containsEdge("2", "323"));
|
||||
assertNull(graph.addEdgeAndVertices(new Edge<>("2", "323", 3)));
|
||||
assertTrue(graph.containsEdge("2", "323"));
|
||||
assertFalse(graph.containsEdge("2aa", "323"));
|
||||
assertNull(graph.addEdgeAndVertices(new Edge<>("2aa", "323", 35)));
|
||||
assertTrue(graph.containsEdge("2aa", "323"));
|
||||
assertFalse(graph.containsEdge("2bbb", "323bbb"));
|
||||
assertNull(graph.addEdgeAndVertices(new Edge<>("2bbb", "323bbb", 135)));
|
||||
assertTrue(graph.containsEdge("2bbb", "323bbb"));
|
||||
|
||||
shouldThrow(nullException, () -> graph.addEdgeAndVertices(new Edge<>(null, "1", 1)));
|
||||
shouldThrow(nullException, () -> graph.addEdgeAndVertices(new Edge<>(null, null, 1)));
|
||||
shouldThrow(nullException, () -> graph.addEdgeAndVertices(new Edge<>("2", null, 1)));
|
||||
shouldThrow(new NullPointerException(), () -> graph.addEdgeAndVertices(null));
|
||||
|
||||
assertEquals(3, graph.addEdgeAndVertices(new Edge<>("2", "323", 50)).intValue());
|
||||
assertEquals(35, graph.addEdgeAndVertices(new Edge<>("2aa", "323", 5)).intValue());
|
||||
assertEquals(50, graph.addEdgeAndVertices(new Edge<>("2", "323", 500)).intValue());
|
||||
|
||||
graph.removeAllVertex();
|
||||
graph.addVertex("aaa");
|
||||
graph.addVertex("1");
|
||||
@@ -217,19 +255,19 @@ public class TestGraph {
|
||||
shouldContain(graph.vertices(), "1", "2", "aaa");
|
||||
shouldContain(graph.edges());
|
||||
|
||||
Set<Graph.Edge<String, Integer>> edges = new HashSet<>();
|
||||
edges.add(new Graph.Edge<>("aaa", "bbb", 3));
|
||||
edges.add(new Graph.Edge<>("bbb", "ccc", 4));
|
||||
edges.add(new Graph.Edge<>("ccc", "aaa", 5));
|
||||
edges.add(new Graph.Edge<>("1", "2", 2));
|
||||
Set<Edge<String, Integer>> edges = new HashSet<>();
|
||||
edges.add(new Edge<>("aaa", "bbb", 3));
|
||||
edges.add(new Edge<>("bbb", "ccc", 4));
|
||||
edges.add(new Edge<>("ccc", "aaa", 5));
|
||||
edges.add(new Edge<>("1", "2", 2));
|
||||
graph.addAllEdges(edges);
|
||||
|
||||
shouldContain(graph.vertices(), "1", "2", "aaa", "bbb", "ccc");
|
||||
shouldContain(graph.edges(),
|
||||
new Graph.Edge<>("aaa", "bbb", 3),
|
||||
new Graph.Edge<>("bbb", "ccc", 4),
|
||||
new Graph.Edge<>("ccc", "aaa", 5),
|
||||
new Graph.Edge<>("1", "2", 2));
|
||||
new Edge<>("aaa", "bbb", 3),
|
||||
new Edge<>("bbb", "ccc", 4),
|
||||
new Edge<>("ccc", "aaa", 5),
|
||||
new Edge<>("1", "2", 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -276,12 +314,19 @@ public class TestGraph {
|
||||
shouldContain(graph.getAncestors("5"), "2", "3");
|
||||
shouldContain(graph.getAncestors("6"), "2", "4");
|
||||
|
||||
shouldContain(graph.getChildrenAndWeight("1").entrySet(), new AbstractMap.SimpleEntry<>("2", 1), new AbstractMap.SimpleEntry<>("3", 1));
|
||||
shouldContain(graph.getChildrenAndWeight("2").entrySet(), new AbstractMap.SimpleEntry<>("5", 4), new AbstractMap.SimpleEntry<>("6", 5));
|
||||
shouldContain(graph.getChildrenAndWeight("3").entrySet(), new AbstractMap.SimpleEntry<>("5", 2));
|
||||
shouldContain(graph.getChildrenAndWeight("4").entrySet(), new AbstractMap.SimpleEntry<>("6", 6));
|
||||
shouldContain(graph.getChildrenAndWeight("5").entrySet(), new AbstractMap.SimpleEntry<>("3", 9), new AbstractMap.SimpleEntry<>("4", 5));
|
||||
shouldContain(graph.getChildrenAndWeight("6").entrySet());
|
||||
shouldContain(graph.getEdgesOut("1"), new Edge<>("1", "2", 1), new Edge<>("1", "3", 1));
|
||||
shouldContain(graph.getEdgesOut("2"), new Edge<>("2", "5", 4), new Edge<>("2", "6", 5));
|
||||
shouldContain(graph.getEdgesOut("3"), new Edge<>("3", "5", 2));
|
||||
shouldContain(graph.getEdgesOut("4"), new Edge<>("4", "6", 6));
|
||||
shouldContain(graph.getEdgesOut("5"), new Edge<>("5", "3", 9), new Edge<>("5", "4", 5));
|
||||
shouldContain(graph.getEdgesOut("6"));
|
||||
|
||||
shouldContain(graph.getEdgesIn("1"));
|
||||
shouldContain(graph.getEdgesIn("2"), new Edge<>("1", "2", 1));
|
||||
shouldContain(graph.getEdgesIn("3"), new Edge<>("1", "3", 1), new Edge<>("5", "3", 9));
|
||||
shouldContain(graph.getEdgesIn("4"), new Edge<>("5", "4", 5));
|
||||
shouldContain(graph.getEdgesIn("5"), new Edge<>("2", "5", 4), new Edge<>("3", "5", 2));
|
||||
shouldContain(graph.getEdgesIn("6"), new Edge<>("4", "6", 6), new Edge<>("2", "6", 5));
|
||||
|
||||
assertEquals(0, graph.degreeIn("1"));
|
||||
assertEquals(1, graph.degreeIn("2"));
|
||||
@@ -305,27 +350,27 @@ public class TestGraph {
|
||||
assertEquals(2, graph.degree("6"));
|
||||
|
||||
shouldContain(graph.edges(),
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("1", "3", 1),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("2", "6", 5),
|
||||
new Graph.Edge<>("3", "5", 2),
|
||||
new Graph.Edge<>("4", "6", 6),
|
||||
new Graph.Edge<>("5", "3", 9),
|
||||
new Graph.Edge<>("5", "4", 5));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("1", "3", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("2", "6", 5),
|
||||
new Edge<>("3", "5", 2),
|
||||
new Edge<>("4", "6", 6),
|
||||
new Edge<>("5", "3", 9),
|
||||
new Edge<>("5", "4", 5));
|
||||
|
||||
shouldThrow(nullException, () -> graph.edgesOf(null));
|
||||
shouldThrow(notException, () -> graph.edgesOf("rew"));
|
||||
shouldContain(graph.edgesOf("5"),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("3", "5", 2),
|
||||
new Graph.Edge<>("5", "3", 9),
|
||||
new Graph.Edge<>("5", "4", 5));
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("3", "5", 2),
|
||||
new Edge<>("5", "3", 9),
|
||||
new Edge<>("5", "4", 5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preBasicVisit() {
|
||||
VisitStrategy.VisitInfo<Integer> info = new VisitStrategy.VisitInfo<>(0);
|
||||
VisitInfo<Integer> info = new VisitInfo<>(0);
|
||||
assertTrue(info.isDiscovered(0));
|
||||
assertFalse(info.isVisited(0));
|
||||
assertEquals(0, info.getTimeDiscover(0));
|
||||
@@ -383,8 +428,7 @@ public class TestGraph {
|
||||
shouldThrow(notException, () -> graph.visit("1010", new DFS<>(), null));
|
||||
|
||||
DFS<String, Integer> dfs = new DFS<>();
|
||||
graph.visit("1", dfs, null);
|
||||
VisitStrategy.VisitInfo<String> visitDFS = dfs.getLastVisit();
|
||||
VisitInfo<String> visitDFS = graph.visit("1", dfs, null);
|
||||
assertEquals(0, visitDFS.getTimeDiscover("1"));
|
||||
assertEquals(1, visitDFS.getTimeDiscover("2"));
|
||||
assertEquals(2, visitDFS.getTimeDiscover("5"));
|
||||
@@ -400,9 +444,25 @@ public class TestGraph {
|
||||
assertFalse(visitDFS.isDiscovered("7"));
|
||||
assertFalse(visitDFS.isDiscovered("8"));
|
||||
|
||||
int[] discoverTime = {0, 1, 2, 3, 5, 6};
|
||||
String[] verticesDiscovered = {"1", "2", "5", "3", "4", "6"};
|
||||
AtomicInteger integer = new AtomicInteger(0);
|
||||
visitDFS.forEachDiscovered(vertexInfo -> {
|
||||
assertEquals(discoverTime[integer.get()], vertexInfo.timeDiscovered);
|
||||
assertEquals(verticesDiscovered[integer.get()], vertexInfo.vertex);
|
||||
integer.incrementAndGet();
|
||||
});
|
||||
integer.set(0);
|
||||
int[] visitTime = {4, 7, 8, 9, 10, 11};
|
||||
String[] verticesVisited = {"3", "6", "4", "5", "2", "1"};
|
||||
visitDFS.forEachVisited(vertexInfo -> {
|
||||
assertEquals(visitTime[integer.get()], vertexInfo.timeVisited);
|
||||
assertEquals(verticesVisited[integer.get()], vertexInfo.vertex);
|
||||
integer.incrementAndGet();
|
||||
});
|
||||
|
||||
BFS<String, Integer> bfs = new BFS<>();
|
||||
graph.visit("1", bfs, null);
|
||||
VisitStrategy.VisitInfo<String> visitBFS = bfs.getLastVisit();
|
||||
VisitInfo<String> visitBFS = graph.visit("1", bfs, null);
|
||||
assertEquals(0, visitBFS.getTimeDiscover("1"));
|
||||
assertEquals(1, visitBFS.getTimeVisit("1"));
|
||||
assertEquals(2, visitBFS.getTimeDiscover("2"));
|
||||
@@ -642,8 +702,7 @@ public class TestGraph {
|
||||
Graph<String, Integer> transposed = graph.transpose();
|
||||
|
||||
DFS<String, Integer> dfs = new DFS<>();
|
||||
transposed.visit("6", dfs, null);
|
||||
VisitStrategy.VisitInfo<String> visitDFS = dfs.getLastVisit();
|
||||
VisitInfo<String> visitDFS = transposed.visit("6", dfs, null);
|
||||
assertEquals(0, visitDFS.getTimeDiscover("6"));
|
||||
assertEquals(1, visitDFS.getTimeDiscover("4"));
|
||||
assertEquals(2, visitDFS.getTimeDiscover("5"));
|
||||
@@ -658,8 +717,7 @@ public class TestGraph {
|
||||
assertFalse(visitDFS.isDiscovered("7"));
|
||||
assertFalse(visitDFS.isDiscovered("8"));
|
||||
|
||||
transposed.visit("8", dfs, null);
|
||||
visitDFS = dfs.getLastVisit();
|
||||
visitDFS = transposed.visit("8", dfs, null);
|
||||
assertEquals(0, visitDFS.getTimeDiscover("8"));
|
||||
assertEquals(1, visitDFS.getTimeDiscover("7"));
|
||||
assertEquals(2, visitDFS.getTimeVisit("7"));
|
||||
@@ -733,23 +791,23 @@ public class TestGraph {
|
||||
graph.addEdge("6", "2", 2);
|
||||
graph.addEdge("7", "8", 8);
|
||||
|
||||
List<Graph.Edge<String, Integer>> distance = graph.distance("1", "6");
|
||||
int sum = distance.stream().mapToInt(Graph.Edge::getWeight).sum();
|
||||
List<Edge<String, Integer>> distance = graph.distance("1", "6");
|
||||
int sum = distance.stream().mapToInt(Edge::getWeight).sum();
|
||||
assertEquals(13, sum);
|
||||
shouldContainInOrder(distance,
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("5", "4", 3),
|
||||
new Graph.Edge<>("4", "6", 5));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("5", "4", 3),
|
||||
new Edge<>("4", "6", 5));
|
||||
distance = graph.distance("1", "3");
|
||||
sum = distance.stream().mapToInt(Graph.Edge::getWeight).sum();
|
||||
sum = distance.stream().mapToInt(Edge::getWeight).sum();
|
||||
assertEquals(8, sum);
|
||||
shouldContainInOrder(distance,
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("5", "3", 3));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("5", "3", 3));
|
||||
|
||||
shouldContainInOrder(graph.distance("7", "8"), new Graph.Edge<>("7", "8", 8));
|
||||
shouldContainInOrder(graph.distance("7", "8"), new Edge<>("7", "8", 8));
|
||||
|
||||
shouldThrow(nullException, () -> graph.distance(null, "1"));
|
||||
shouldThrow(nullException, () -> graph.distance(null, null));
|
||||
@@ -792,32 +850,146 @@ public class TestGraph {
|
||||
graph.addEdge("6", "2", 2);
|
||||
graph.addEdge("7", "8", 8);
|
||||
|
||||
Map<String, List<Graph.Edge<String, Integer>>> distance = graph.distance("1");
|
||||
Map<String, List<Edge<String, Integer>>> distance = graph.distance("1");
|
||||
assertNull(distance.get("1"));
|
||||
shouldContainInOrder(distance.get("2"),
|
||||
new Graph.Edge<>("1", "2", 1));
|
||||
new Edge<>("1", "2", 1));
|
||||
shouldContainInOrder(distance.get("3"),
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("5", "3", 3));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("5", "3", 3));
|
||||
shouldContain(distance.get("4"),
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("5", "4", 3));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("5", "4", 3));
|
||||
shouldContain(distance.get("5"),
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("2", "5", 4));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("2", "5", 4));
|
||||
shouldContain(distance.get("6"),
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("5", "4", 3),
|
||||
new Graph.Edge<>("4", "6", 5));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("5", "4", 3),
|
||||
new Edge<>("4", "6", 5));
|
||||
assertNull(distance.get("7"));
|
||||
shouldContain(distance.get("8"),
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("5", "4", 3),
|
||||
new Graph.Edge<>("4", "8", 2));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("5", "4", 3),
|
||||
new Edge<>("4", "8", 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void marker() {
|
||||
/*
|
||||
* This graph should be like this
|
||||
*
|
||||
* 1 -> 2 <- 6 7
|
||||
* ^ ^
|
||||
* | | | |
|
||||
* v v v
|
||||
* 3 <- 5 -> 4 8
|
||||
*/
|
||||
|
||||
graph.addVertexIfAbsent("1");
|
||||
graph.addVertexIfAbsent("2");
|
||||
graph.addVertexIfAbsent("3");
|
||||
graph.addVertexIfAbsent("4");
|
||||
graph.addVertexIfAbsent("5");
|
||||
graph.addVertexIfAbsent("6");
|
||||
graph.addVertexIfAbsent("7");
|
||||
graph.addVertexIfAbsent("8");
|
||||
|
||||
graph.addEdge("1", "2", 1);
|
||||
graph.addEdge("1", "3", 1);
|
||||
graph.addEdge("2", "5", 4);
|
||||
graph.addEdge("4", "6", 5);
|
||||
graph.addEdge("5", "3", 6);
|
||||
graph.addEdge("5", "4", 3);
|
||||
graph.addEdge("6", "2", 2);
|
||||
graph.addEdge("7", "8", 8);
|
||||
graph.addEdge("8", "7", 8);
|
||||
|
||||
shouldThrow(nullException, () -> graph.mark(null, null));
|
||||
shouldThrow(nullException, () -> graph.mark("1", null));
|
||||
shouldThrow(nullException, () -> graph.mark(null, "yellow"));
|
||||
shouldThrow(nullException, () -> graph.unMark(null));
|
||||
shouldThrow(nullException, () -> graph.getMarks(null));
|
||||
shouldThrow(nullException, () -> graph.unMark(null, null));
|
||||
shouldThrow(nullException, () -> graph.unMark("1", null));
|
||||
shouldThrow(nullException, () -> graph.unMark(null, "blue"));
|
||||
shouldThrow(nullException, () -> graph.unMarkAll(null));
|
||||
|
||||
shouldThrow(notException, () -> graph.mark("324", "yellow"));
|
||||
shouldThrow(notException, () -> graph.unMark("32423"));
|
||||
shouldThrow(notException, () -> graph.getMarks("hw7389"));
|
||||
|
||||
shouldContain(graph.getMarks("1"));
|
||||
graph.mark("1", "red");
|
||||
shouldContain(graph.getMarks("1"), "red");
|
||||
graph.mark("1", "yellow");
|
||||
graph.mark("1", "blue");
|
||||
shouldContain(graph.getMarks("1"), "red", "yellow", "blue");
|
||||
graph.mark("1", "red");
|
||||
shouldContain(graph.getMarks("1"), "red", "yellow", "blue");
|
||||
|
||||
shouldContain(graph.getMarks("2"));
|
||||
graph.mark("2", "red");
|
||||
shouldContain(graph.getMarks("8"));
|
||||
graph.mark("8", "blue");
|
||||
shouldContain(graph.getMarks("2"), "red");
|
||||
shouldContain(graph.getMarks("8"), "blue");
|
||||
|
||||
graph.unMark("2");
|
||||
shouldContain(graph.getMarks("2"));
|
||||
graph.unMark("1");
|
||||
shouldContain(graph.getMarks("1"));
|
||||
|
||||
graph.mark("2", "red");
|
||||
graph.mark("2", "blue");
|
||||
shouldContain(graph.getMarks("2"), "red", "blue");
|
||||
graph.mark("4", "green");
|
||||
shouldContain(graph.getMarks("4"), "green");
|
||||
graph.mark("5", "green");
|
||||
shouldContain(graph.getMarks("5"), "green");
|
||||
|
||||
graph.unMarkAll();
|
||||
shouldContain(graph.getMarks("1"));
|
||||
shouldContain(graph.getMarks("2"));
|
||||
shouldContain(graph.getMarks("3"));
|
||||
shouldContain(graph.getMarks("4"));
|
||||
shouldContain(graph.getMarks("5"));
|
||||
shouldContain(graph.getMarks("6"));
|
||||
shouldContain(graph.getMarks("7"));
|
||||
shouldContain(graph.getMarks("8"));
|
||||
|
||||
graph.mark("1", "mark");
|
||||
graph.mark("2", "mark");
|
||||
graph.mark("3", "mark2");
|
||||
graph.mark("1", "mark2");
|
||||
shouldContain(graph.getMarks("1"), "mark", "mark2");
|
||||
shouldContain(graph.getMarks("2"), "mark");
|
||||
shouldContain(graph.getMarks("3"), "mark2");
|
||||
|
||||
graph.unMark("1", "mark");
|
||||
shouldContain(graph.getMarks("1"), "mark2");
|
||||
shouldContain(graph.getMarks("2"), "mark");
|
||||
shouldContain(graph.getMarks("3"), "mark2");
|
||||
|
||||
graph.unMarkAll("mark2");
|
||||
shouldContain(graph.getMarks("1"));
|
||||
shouldContain(graph.getMarks("2"), "mark");
|
||||
shouldContain(graph.getMarks("3"));
|
||||
|
||||
graph.unMark("1", "mark");
|
||||
graph.unMark("2", "mark2");
|
||||
shouldContain(graph.getMarks("1"));
|
||||
shouldContain(graph.getMarks("2"), "mark");
|
||||
shouldContain(graph.getMarks("3"));
|
||||
|
||||
graph.unMark("2", "mark");
|
||||
shouldContain(graph.getMarks("1"));
|
||||
shouldContain(graph.getMarks("2"));
|
||||
shouldContain(graph.getMarks("3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -847,6 +1019,24 @@ public class TestGraph {
|
||||
graph.addEdge("5", "4", 5);
|
||||
graph.addEdge("6", "2", 2);
|
||||
|
||||
graph.mark("1", "blue");
|
||||
graph.mark("3", "blue");
|
||||
graph.mark("5", "blue");
|
||||
|
||||
graph.mark("2", "even");
|
||||
graph.mark("4", "even");
|
||||
graph.mark("6", "even");
|
||||
|
||||
graph.mark("2", "circle");
|
||||
graph.mark("4", "circle");
|
||||
graph.mark("5", "circle");
|
||||
graph.mark("6", "circle");
|
||||
|
||||
graph.mark("1", "z");
|
||||
graph.mark("2", "z");
|
||||
graph.mark("5", "z");
|
||||
graph.mark("4", "z");
|
||||
|
||||
Graph<String, Integer> sub = graph.subGraph("1", -541);
|
||||
shouldContain(sub.vertices(), "1");
|
||||
shouldContain(sub.edges());
|
||||
@@ -858,34 +1048,175 @@ public class TestGraph {
|
||||
sub = graph.subGraph("1", 1);
|
||||
shouldContain(sub.vertices(), "1", "2", "3");
|
||||
shouldContain(sub.edges(),
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("1", "3", 1));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("1", "3", 1));
|
||||
|
||||
sub = graph.subGraph("1", 3);
|
||||
shouldContain(sub.vertices(), "1", "2", "3", "5", "4");
|
||||
shouldContain(sub.edges(),
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("1", "3", 1),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("5", "3", 2),
|
||||
new Graph.Edge<>("5", "4", 5));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("1", "3", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("5", "3", 2),
|
||||
new Edge<>("5", "4", 5));
|
||||
|
||||
sub = graph.subGraph("6", 2);
|
||||
shouldContain(sub.vertices(), "6", "2", "5");
|
||||
shouldContain(sub.edges(),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("6", "2", 2));
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("6", "2", 2));
|
||||
|
||||
sub = graph.subGraph("1", 77689);
|
||||
shouldContain(sub.vertices(), "1", "2", "3", "5", "4", "6");
|
||||
shouldContain(sub.edges(),
|
||||
new Graph.Edge<>("1", "2", 1),
|
||||
new Graph.Edge<>("1", "3", 1),
|
||||
new Graph.Edge<>("2", "5", 4),
|
||||
new Graph.Edge<>("4", "6", 6),
|
||||
new Graph.Edge<>("5", "3", 2),
|
||||
new Graph.Edge<>("5", "4", 5),
|
||||
new Graph.Edge<>("6", "2", 2));
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("1", "3", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("4", "6", 6),
|
||||
new Edge<>("5", "3", 2),
|
||||
new Edge<>("5", "4", 5),
|
||||
new Edge<>("6", "2", 2));
|
||||
|
||||
/* MARKED */
|
||||
sub = graph.subGraph("z");
|
||||
shouldContain(sub.vertices(), "1", "2", "5", "4");
|
||||
shouldContain(sub.edges(),
|
||||
new Edge<>("1", "2", 1),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("5", "4", 5));
|
||||
|
||||
sub = graph.subGraph("circle");
|
||||
shouldContain(sub.vertices(), "2", "5", "4", "6");
|
||||
shouldContain(sub.edges(),
|
||||
new Edge<>("2", "5", 4),
|
||||
new Edge<>("4", "6", 6),
|
||||
new Edge<>("5", "4", 5),
|
||||
new Edge<>("6", "2", 2));
|
||||
|
||||
sub = graph.subGraph("blue");
|
||||
shouldContain(sub.vertices(), "1", "3", "5");
|
||||
shouldContain(sub.edges(),
|
||||
new Edge<>("1", "3", 1),
|
||||
new Edge<>("5", "3", 2));
|
||||
|
||||
sub = graph.subGraph("even");
|
||||
shouldContain(sub.vertices(), "2", "4", "6");
|
||||
shouldContain(sub.edges(),
|
||||
new Edge<>("4", "6", 6),
|
||||
new Edge<>("6", "2", 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void vertexClass() {
|
||||
Vertex<String> vertex = new Vertex<>(graph, "stronzo");
|
||||
|
||||
assertEquals("stronzo", vertex.getValue());
|
||||
assertEquals(0, graph.numberOfVertices());
|
||||
|
||||
shouldThrow(unsuppException, () -> vertex.addChild(null, null));
|
||||
shouldThrow(unsuppException, () -> vertex.mark(null));
|
||||
shouldThrow(unsuppException, () -> vertex.removeChild(null));
|
||||
shouldThrow(unsuppException, () -> vertex.visit(null, null));
|
||||
shouldThrow(unsuppException, vertex::unMark);
|
||||
shouldThrow(unsuppException, vertex::getAncestors);
|
||||
shouldThrow(unsuppException, vertex::getChildren);
|
||||
shouldThrow(unsuppException, vertex::getEdgesOut);
|
||||
shouldThrow(unsuppException, vertex::getEdgesIn);
|
||||
shouldThrow(unsuppException, vertex::getChildrenAsVertex);
|
||||
shouldThrow(unsuppException, vertex::getAncestorsAsVertex);
|
||||
shouldThrow(unsuppException, vertex::getMarks);
|
||||
|
||||
vertex.addIfAbsent();
|
||||
assertEquals(1, graph.numberOfVertices());
|
||||
vertex.addIfAbsent();
|
||||
assertEquals(1, graph.numberOfVertices());
|
||||
vertex.addIfAbsent();
|
||||
assertEquals(1, graph.numberOfVertices());
|
||||
|
||||
assertEquals(vertex, graph.getVertex("stronzo"));
|
||||
shouldThrow(nullException, () -> graph.getVertex(null));
|
||||
shouldThrow(notException, () -> graph.getVertex("stronzo1"));
|
||||
|
||||
shouldThrow(nullException, () -> vertex.addChild(null, 3));
|
||||
shouldThrow(nullException, () -> vertex.addChild(null, null));
|
||||
shouldThrow(nullException, () -> vertex.mark(null));
|
||||
shouldThrow(nullException, () -> vertex.removeChild(null));
|
||||
shouldThrow(new NullPointerException(), () -> vertex.visit(null, null));
|
||||
|
||||
shouldThrow(notException, () -> vertex.addChild("1", null));
|
||||
shouldThrow(notException, () -> vertex.addChild("ssdsad", 2));
|
||||
shouldThrow(notException, () -> vertex.removeChild("234"));
|
||||
|
||||
shouldContain(vertex.getMarks());
|
||||
shouldContain(vertex.getAncestors());
|
||||
shouldContain(vertex.getChildren());
|
||||
shouldContain(vertex.getChildrenAsVertex());
|
||||
shouldContain(vertex.getEdgesIn());
|
||||
shouldContain(vertex.getEdgesOut());
|
||||
|
||||
graph.addVertex("1");
|
||||
graph.addVertex("2");
|
||||
graph.addVertex("3");
|
||||
|
||||
graph.addEdge("1", "2", 2);
|
||||
graph.addEdge("3", "stronzo", 6);
|
||||
graph.addEdge("stronzo", "2", 1);
|
||||
graph.addEdge("stronzo", "1", 3);
|
||||
|
||||
shouldContain(vertex.getMarks());
|
||||
shouldContain(vertex.getAncestors(), "3");
|
||||
shouldContain(vertex.getChildren(), "1", "2");
|
||||
shouldContain(vertex.getChildrenAsVertex(), new Vertex<>(graph, "1"), new Vertex<>(graph, "2"));
|
||||
shouldContain(vertex.getAncestorsAsVertex(), new Vertex<>(graph, "3"));
|
||||
shouldContain(vertex.getEdgesIn(),
|
||||
new Edge<>("3", "stronzo", 6));
|
||||
shouldContain(graph.getEdgesIn(vertex.getValue()),
|
||||
new Edge<>("3", "stronzo", 6));
|
||||
shouldContain(vertex.getEdgesOut(),
|
||||
new Edge<>("stronzo", "1", 3),
|
||||
new Edge<>("stronzo", "2", 1));
|
||||
shouldContain(graph.getEdgesOut(vertex.getValue()),
|
||||
new Edge<>("stronzo", "1", 3),
|
||||
new Edge<>("stronzo", "2", 1));
|
||||
|
||||
vertex.mark("ciao");
|
||||
vertex.mark("ciao2");
|
||||
shouldContain(vertex.getMarks(), "ciao", "ciao2");
|
||||
shouldContain(graph.getMarks(vertex.getValue()), "ciao", "ciao2");
|
||||
vertex.unMark();
|
||||
shouldContain(vertex.getMarks());
|
||||
|
||||
vertex.removeChild("1");
|
||||
shouldContain(vertex.getChildren(), "2");
|
||||
vertex.addChild("3", 23);
|
||||
shouldContain(vertex.getChildren(), "2", "3");
|
||||
shouldContain(vertex.getAncestors(), "3");
|
||||
shouldContain(vertex.getEdgesOut(), new Edge<>("stronzo", "3", 23), new Edge<>("stronzo", "2", 1));
|
||||
shouldContain(graph.getEdgesOut(vertex.getValue()), new Edge<>("stronzo", "3", 23), new Edge<>("stronzo", "2", 1));
|
||||
shouldContain(vertex.getEdgesIn(), new Edge<>("3", "stronzo", 6));
|
||||
shouldContain(graph.getEdgesIn(vertex.getValue()), new Edge<>("3", "stronzo", 6));
|
||||
|
||||
assertTrue(vertex.isStillContained());
|
||||
vertex.remove();
|
||||
assertFalse(vertex.isStillContained());
|
||||
assertFalse(graph.contains(vertex.getValue()));
|
||||
assertEquals(3, graph.numberOfVertices());
|
||||
|
||||
shouldThrow(unsuppException, () -> vertex.addChild(null, null));
|
||||
shouldThrow(unsuppException, () -> vertex.mark(null));
|
||||
shouldThrow(unsuppException, () -> vertex.removeChild(null));
|
||||
shouldThrow(unsuppException, () -> vertex.visit(null, null));
|
||||
shouldThrow(unsuppException, vertex::unMark);
|
||||
shouldThrow(unsuppException, vertex::getAncestors);
|
||||
shouldThrow(unsuppException, vertex::getChildren);
|
||||
shouldThrow(unsuppException, vertex::getEdgesOut);
|
||||
shouldThrow(unsuppException, vertex::getEdgesIn);
|
||||
shouldThrow(unsuppException, vertex::getChildrenAsVertex);
|
||||
shouldThrow(unsuppException, vertex::getAncestorsAsVertex);
|
||||
shouldThrow(unsuppException, vertex::getMarks);
|
||||
|
||||
vertex.addIfAbsent();
|
||||
assertEquals(4, graph.numberOfVertices());
|
||||
}
|
||||
|
||||
// TODO test saveFile
|
||||
|
||||
Reference in New Issue
Block a user