From 7f16252890f95d979a277045270689af180c7c62 Mon Sep 17 00:00:00 2001
From: Giacomo Bertolazzi <20015159@studenti.uniupo.it>
Date: Wed, 6 Jan 2021 16:28:01 +0100
Subject: [PATCH] Updating graph
* Implemented MatrixGraph
* Changed save/load logics (test not passing)
---
build.gradle | 15 +-
src/berack96/lib/graph/Graph.java | 133 +---
src/berack96/lib/graph/Vertex.java | 14 +-
src/berack96/lib/graph/impl/AGraph.java | 579 ++++++++++++++++++
src/berack96/lib/graph/impl/AdjGraph.java | 319 ----------
src/berack96/lib/graph/impl/ListGraph.java | 144 +++++
src/berack96/lib/graph/impl/MapGraph.java | 560 ++---------------
src/berack96/lib/graph/impl/MatrixGraph.java | 353 +++--------
.../lib/graph/models/EdgeSaveStructure.java | 1 -
.../lib/graph/models/GraphSaveStructure.java | 124 +++-
.../lib/graph/models/MarkSaveStructure.java | 1 -
src/berack96/lib/graph/view/GraphInfo.java | 36 +-
.../lib/graph/view/GraphListener.java | 4 +-
src/berack96/lib/graph/view/GraphPanel.java | 99 +--
.../lib/graph/view/GraphPointsSave.java | 54 ++
src/berack96/lib/graph/view/GraphWindow.java | 22 +-
.../lib/graph/view/VisitListener.java | 6 +-
.../graph/view/vertex/VertexComponent.java | 6 +-
.../graph/view/vertex/VertexIntListener.java | 18 +-
.../lib/graph/view/vertex/VertexView.java | 6 +-
src/berack96/lib/graph/visit/impl/BFS.java | 8 +-
src/berack96/lib/graph/visit/impl/DFS.java | 8 +-
src/berack96/lib/graph/visit/impl/Depth.java | 53 ++
src/berack96/lib/graph/visit/impl/Tarjan.java | 10 +-
.../lib/graph/visit/impl/VisitInfo.java | 351 ++++++-----
test/berack96/test/lib/TestGraph.java | 523 ++++++++--------
test/resources/test.json | 2 +-
27 files changed, 1678 insertions(+), 1771 deletions(-)
create mode 100644 src/berack96/lib/graph/impl/AGraph.java
delete mode 100644 src/berack96/lib/graph/impl/AdjGraph.java
create mode 100644 src/berack96/lib/graph/impl/ListGraph.java
create mode 100644 src/berack96/lib/graph/view/GraphPointsSave.java
create mode 100644 src/berack96/lib/graph/visit/impl/Depth.java
diff --git a/build.gradle b/build.gradle
index bc2999e..58ef372 100644
--- a/build.gradle
+++ b/build.gradle
@@ -14,13 +14,9 @@ test {
useJUnitPlatform()
}
-sourceSets {
- main {
- java {
- srcDirs "src"
- srcDirs "test"
- }
- }
+sourceSets.main.java {
+ srcDirs "src"
+ srcDirs "test"
}
repositories {
@@ -28,8 +24,9 @@ repositories {
}
dependencies {
- compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
+ implementation 'org.junit.jupiter:junit-jupiter:5.5.2'
+ compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
/*compile group: 'commons-collections', name: 'commons-collections', version: '3.2'*/
- testCompile 'junit:junit:4.4'
+ testCompile 'junit:junit:5.5.2'
}
\ No newline at end of file
diff --git a/src/berack96/lib/graph/Graph.java b/src/berack96/lib/graph/Graph.java
index 65ee5b0..4a300e1 100644
--- a/src/berack96/lib/graph/Graph.java
+++ b/src/berack96/lib/graph/Graph.java
@@ -1,21 +1,13 @@
package berack96.lib.graph;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
+import berack96.lib.graph.visit.VisitStrategy;
+import berack96.lib.graph.visit.impl.VisitInfo;
+
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
-import com.google.gson.Gson;
-import com.google.gson.JsonSyntaxException;
-
-import berack96.lib.graph.models.GraphSaveStructure;
-import berack96.lib.graph.visit.VisitStrategy;
-import berack96.lib.graph.visit.impl.VisitInfo;
-
/**
* An interface for the graphs.
* This interface is used for the graphs with Directed edges.
@@ -27,11 +19,10 @@ import berack96.lib.graph.visit.impl.VisitInfo;
*/
public interface Graph extends Iterable {
- final String NOT_DAG = "The graph is not a DAG";
- final String NOT_CONNECTED = "The source vertex doesn't have a path that reach the destination";
- final String PARAM_NULL = "The parameter must not be null";
- final String VERTEX_NOT_CONTAINED = "The vertex must be contained in the graph";
- final Gson GSON = new Gson();
+ String NOT_DAG = "The graph is not a DAG";
+ String NOT_CONNECTED = "The source vertex doesn't have a path that reach the destination";
+ String PARAM_NULL = "The parameter must not be null";
+ String VERTEX_NOT_CONTAINED = "The vertex must be contained in the graph";
/**
* Tells if the graph has some cycle.
@@ -70,16 +61,16 @@ public interface Graph extends Iterable {
* @throws NullPointerException if the vertex is null
* @throws IllegalArgumentException if the vertex is not contained in the graph
*/
- Vertex getVertex(V vertex) throws NullPointerException, IllegalArgumentException;
+ Vertex get(V vertex) throws NullPointerException, IllegalArgumentException;
/**
- * Add the vertex to the graph. If it's already in the graph it will be replaced.
+ * Add the vertex to the graph. If it's already in the graph it will be replaced and all its edges will be resetted.
* Of course the vertex added will have no edge to any other vertex nor form any other vertex.
*
* @param vertex the vertex to add
* @throws NullPointerException if the vertex is null
*/
- void addVertex(V vertex) throws NullPointerException;
+ void add(V vertex) throws NullPointerException;
/**
* Add the specified vertex to the graph only if the graph doesn't contains it.
@@ -89,7 +80,7 @@ public interface Graph extends Iterable {
* @return true if the vertex is added, false if the graph contains the vertex and therefore the new one is not added
* @throws NullPointerException if the vertex is null
*/
- boolean addVertexIfAbsent(V vertex) throws NullPointerException;
+ boolean addIfAbsent(V vertex) throws NullPointerException;
/**
* Add all the vertices contained in the collection to the graph.
@@ -99,7 +90,7 @@ public interface Graph extends Iterable {
* @param vertices a collection of the vertices to add
* @throws NullPointerException if the set is null
*/
- void addAllVertices(Collection vertices) throws NullPointerException;
+ void addAll(Collection vertices) throws NullPointerException;
/**
* Remove the selected vertex from the graph.
@@ -109,13 +100,13 @@ public interface Graph extends Iterable {
* @throws NullPointerException if the vertex is null
* @throws IllegalArgumentException if the vertex is not contained
*/
- void removeVertex(V vertex) throws NullPointerException, IllegalArgumentException;
+ void remove(V vertex) throws NullPointerException, IllegalArgumentException;
/**
* Remove all the vertex contained in the graph.
* After this method's call the graph will be empty; no vertices nor edges.
*/
- void removeAllVertex();
+ void removeAll();
/**
* Get all the marks of this graph.
@@ -408,11 +399,11 @@ public interface Graph extends Iterable {
* @throws NullPointerException if the vertex is null
* @throws IllegalArgumentException if the vertex is not contained in the graph
*/
- Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException;
+ Collection getChildrens(V vertex) throws NullPointerException, IllegalArgumentException;
/**
* Get all the vertices that have the vertex passed as their child.
- * Basically is the opposite of {@link #getChildren(Object)}
+ * Basically is the opposite of {@link #getChildrens(Object)}
* Note: depending on the implementation, modifying the returned collection
* could affect the graph behavior and the changes could be reflected to the graph.
*
@@ -462,7 +453,7 @@ public interface Graph extends Iterable {
*
* @return the number of vertices
*/
- int numberOfVertices();
+ int size();
/**
* Tells how many edges are in the graph.
@@ -500,7 +491,7 @@ public interface Graph extends Iterable {
* A topological ordering of a graph is a linear ordering of its vertices such that for
* every directed edge (V1, V2) from vertex V1 to vertex V2, V2 comes before V1 in the ordering.
*
- * @return an array containing the topological order of the vertices
+ * @return a list containing the topological order of the vertices
* @throws UnsupportedOperationException if the graph is not a DAG (see {@link #isDAG()})
*/
List topologicalSort() throws UnsupportedOperationException;
@@ -521,7 +512,7 @@ public interface Graph extends Iterable {
* Of course the sub-graph will contain the edges that link the vertices, but only the one selected.
*
* @param source the source vertex
- * @param depth the maximum depth (must be a positive number, if >=0 a graph containing only the source is returned)
+ * @param depth the maximum depth (must be a positive number, if <=0 a graph containing only the source is returned)
* @return a sub-graph of the original
* @throws NullPointerException if the vertex is null
* @throws IllegalArgumentException if the vertex is not contained
@@ -562,91 +553,5 @@ public interface Graph extends Iterable {
*/
Map>> distance(V source) throws NullPointerException, IllegalArgumentException;
- /**
- * Save the Graph passed as input to a file inserted as parameter.
- * The resulting file is a Json string representing all the graph.
- * If the directory for getting through the file do not exist,
- * then it is created.
- * For now the marks are not included.
- *
- * @param graph the graph to save
- * @param file the name of the file
- * @throws IOException for various reason that appear in the message, but the most common is that the file is not found.
- */
- static void save(Graph, ?> graph, String file) throws IOException {
- save(graph, "", file);
- }
-
- /**
- * Save the Graph passed as input to a file inserted as parameter.
- * The resulting file is a Json string representing all the graph.
- * If the directory for getting through the file do not exist,
- * then it is created.
- * For now the marks are not included.
- * The additional parameter is used if you want to save other as well as the graph.
- *
- * @param graph the graph to save
- * @param other other things to save
- * @param file the name of the file
- * @throws IOException for various reason that appear in the message, but the most common is that the file is not found.
- */
- static void save(Graph, ?> graph, String other, String file) throws IOException {
- GraphSaveStructure save = new GraphSaveStructure(graph, other);
- int slash = file.lastIndexOf("\\");
- if(slash == -1)
- slash = file.lastIndexOf("/");
- if(slash != -1) {
- String dir = file.substring(0, slash);
- File fDir = new File(dir);
- fDir.mkdirs();
- }
-
- FileWriter writer = new FileWriter(file);
-
- GSON.toJson(save, writer);
- writer.close();
- }
-
- /**
- * Load an already saved graph in an instance of a graph.
- * Before loading the graph, it is emptied.
- *
- * @param the parameter needed for the vertex
- * @param the parameter needed for the weight
- * @param graph the graph to load with
- * @param file the file where the graph is saved
- * @param classV the class used for the Vertex
- * @param classW the class used for the Weight
- * @return the string saved in other, if any
- * @throws IOException for any possible reason, the most common: the file doesn't exist
- * @throws NullPointerException if the graph is null
- * @throws JsonSyntaxException if the file is malformed or corrupted
- */
- static String load(Graph graph, String file, Class classV, Class classW) throws IOException, NullPointerException, JsonSyntaxException {
- FileReader reader = new FileReader(file);
- StringBuilder fileContent = new StringBuilder();
- int c;
-
- while((c = reader.read()) != -1)
- fileContent.append((char)c);
- reader.close();
- GraphSaveStructure save = GSON.fromJson(fileContent.toString(), GraphSaveStructure.class);
-
- graph.removeAllVertex();
- for(String str : save.vertices)
- graph.addVertex(GSON.fromJson(str, classV));
-
- for(int i = 0; i V*
}
diff --git a/src/berack96/lib/graph/Vertex.java b/src/berack96/lib/graph/Vertex.java
index 79433ac..570abf0 100644
--- a/src/berack96/lib/graph/Vertex.java
+++ b/src/berack96/lib/graph/Vertex.java
@@ -1,12 +1,12 @@
package berack96.lib.graph;
+import berack96.lib.graph.visit.VisitStrategy;
+import berack96.lib.graph.visit.impl.VisitInfo;
+
import java.util.Collection;
import java.util.HashSet;
import java.util.function.Consumer;
-import berack96.lib.graph.visit.VisitStrategy;
-import berack96.lib.graph.visit.impl.VisitInfo;
-
/**
* Class used for represent a vertex of the graph.
* The vertex contained is linked with the graph, so if any changes are made to
@@ -105,7 +105,7 @@ public class Vertex {
*/
public Collection getChildren() throws UnsupportedOperationException {
throwIfNotContained();
- return graph.getChildren(vertex);
+ return graph.getChildrens(vertex);
}
/**
@@ -219,7 +219,7 @@ public class Vertex {
* Add the vertex to the graph only if it's not already in the graph.
*/
public void addIfAbsent() {
- graph.addVertexIfAbsent(vertex);
+ graph.addIfAbsent(vertex);
}
/**
@@ -228,7 +228,7 @@ public class Vertex {
*/
public void remove() {
if (graph.contains(vertex))
- graph.removeVertex(vertex);
+ graph.remove(vertex);
}
/**
@@ -240,7 +240,7 @@ public class Vertex {
* @throws NullPointerException if the strategy is null
* @throws UnsupportedOperationException if the vertex is not in the graph anymore
*/
- public VisitInfo visit(final VisitStrategy strategy, final Consumer visit) throws NullPointerException, UnsupportedOperationException {
+ public VisitInfo visit(final VisitStrategy strategy, final Consumer visit) throws NullPointerException, UnsupportedOperationException {
throwIfNotContained();
return graph.visit(vertex, (VisitStrategy) strategy, visit);
}
diff --git a/src/berack96/lib/graph/impl/AGraph.java b/src/berack96/lib/graph/impl/AGraph.java
new file mode 100644
index 0000000..52a0190
--- /dev/null
+++ b/src/berack96/lib/graph/impl/AGraph.java
@@ -0,0 +1,579 @@
+package berack96.lib.graph.impl;
+
+import berack96.lib.graph.Edge;
+import berack96.lib.graph.Graph;
+import berack96.lib.graph.Vertex;
+import berack96.lib.graph.visit.VisitStrategy;
+import berack96.lib.graph.visit.impl.Depth;
+import berack96.lib.graph.visit.impl.Dijkstra;
+import berack96.lib.graph.visit.impl.Tarjan;
+import berack96.lib.graph.visit.impl.VisitInfo;
+
+import java.util.*;
+import java.util.function.Consumer;
+
+/**
+ * An abstract class used for a basic implementation of a graph.
+ * It implements the visits, the markers and some other stupid to implement methods.
+ * It might not be super efficient but it works and you can always overwrite its methods for better performance
+ *
+ * @param the vertex
+ * @param the weight
+ * @author Berack96
+ */
+public abstract class AGraph implements Graph {
+
+ /**
+ * Map that contains the marker as key and a set of all the vertices that has it as the value.
+ * This map is build like this for performance in creating the marker for multiple vertices.
+ * If you flip the parameters (object and set) then has more performance over the single vertex.
+ */
+ private final Map> markers = new HashMap<>();
+
+ /**
+ * Need this variable for not calculating each time the SCC or the cyclic part if the graph doesn't change
+ */
+ private Tarjan tarjan = null;
+
+ /**
+ * Need this variable for not calculating each time the distance from a vertex to all his destinations if the graph doesn't change
+ */
+ final private Map> dijkstra = new HashMap<>();
+
+ /**
+ * Get a new instance of this Graph.
+ *
+ * @return A new instance of the graph
+ */
+ protected abstract Graph getNewInstance();
+
+ /**
+ * Add a vertex to the graph
+ *
+ * @param vertex the vertex to add
+ */
+ protected abstract void addVertex(V vertex);
+
+ /**
+ * Check if a vertex is in the graph
+ *
+ * @param vertex the vertex to check
+ * @return true if is contained, false otherwise
+ */
+ protected abstract boolean containsVertex(V vertex);
+
+ /**
+ * Remove a vertex from the graph
+ *
+ * @param vertex the vertex to remove
+ */
+ protected abstract void removeVertex(V vertex);
+
+ /**
+ * Remove all vertices from the graph
+ */
+ protected abstract void removeAllVertices();
+
+ /**
+ * Check if the edge is in the graph
+ * @param vertex1 the source vertex
+ * @param vertex2 the destination vertex
+ * @return true if the edge is in the graph, false otherwise
+ */
+ protected abstract boolean containsEdgeImpl(V vertex1, V vertex2);
+
+ /**
+ * Add a new edge to the graph.
+ * If the edge already exist then replace the weight and returns the old one.
+ *
+ * @param vertex1 the source vertex
+ * @param vertex2 the destination vertex
+ * @param weight the weight of the new edge
+ * @return the old weight, null otherwise
+ */
+ protected abstract W addEdgeImpl(V vertex1, V vertex2, W weight);
+
+ /**
+ * Get the weight of the edge
+ *
+ * @param vertex1 the source vertex
+ * @param vertex2 the destination vertex
+ * @return the weight of the edge
+ */
+ protected abstract W getWeightImpl(V vertex1, V vertex2);
+
+ /**
+ * Retrieves all the edges that goes out of a vertex.
+ * (where the vertex is the source)
+ *
+ * @param vertex the source vertex
+ * @return a collection of edges
+ */
+ protected abstract Collection> getEdgesOutImpl(V vertex);
+
+ /**
+ * Retrieves all the edges that goes in of a vertex.
+ * (where the vertex is the destination)
+ *
+ * @param vertex the destination vertex
+ * @return a collection of edges
+ */
+ protected abstract Collection> getEdgesInImpl(V vertex);
+
+ /**
+ * Remove the edge from the graph
+ * @param vertex1 the source vertex
+ * @param vertex2 the destination vertex
+ */
+ protected abstract void removeEdgeImpl(V vertex1, V vertex2);
+
+ /**
+ * Removes all the edges that goes out of a vertex.
+ * (where the vertex is the source)
+ * @param vertex the source vertex
+ */
+ protected abstract void removeAllOutEdgeImpl(V vertex);
+
+ /**
+ * Removes all the edges that goes in of a vertex.
+ * (where the vertex is the destination)
+ *
+ * @param vertex the destination vertex
+ */
+ protected abstract void removeAllInEdgeImpl(V vertex);
+
+ @Override
+ public boolean isCyclic() {
+ return stronglyConnectedComponents().size() != size();
+ }
+
+ @Override
+ public boolean isDAG() {
+ return !isCyclic();
+ }
+
+ @Override
+ public Vertex get(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ return new Vertex<>(this, vertex);
+ }
+
+ @Override
+ public boolean contains(V vertex) throws NullPointerException {
+ checkNull(vertex);
+ return containsVertex(vertex);
+ }
+
+ @Override
+ public void add(V vertex) throws NullPointerException {
+ checkNull(vertex);
+ if(containsVertex(vertex))
+ remove(vertex);
+ addVertex(vertex);
+ graphChanged();
+ }
+
+ @Override
+ public boolean addIfAbsent(V vertex) throws NullPointerException {
+ if(contains(vertex))
+ return false;
+ add(vertex);
+ return true;
+ }
+
+ @Override
+ public void addAll(Collection vertices) throws NullPointerException {
+ checkNull(vertices);
+ vertices.forEach(this::addIfAbsent);
+ }
+
+ @Override
+ public void remove(V vertex) throws NullPointerException, IllegalArgumentException {
+ unMark(vertex);
+ removeVertex(vertex);
+ graphChanged();
+ }
+
+ @Override
+ public void removeAll() {
+ unMarkAll();
+ removeAllVertices();
+ graphChanged();
+ }
+
+ @Override
+ public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException {
+ checkNull(vertex1);
+ checkNull(vertex2);
+ return containsEdgeImpl(vertex1, vertex2);
+ }
+
+ @Override
+ public W addEdge(V vertex1, V vertex2, W weight) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex1);
+ checkNullAndExist(vertex2);
+ graphChanged();
+ return addEdgeImpl(vertex1, vertex2, weight);
+ }
+
+ @Override
+ public W addEdge(Edge edge) throws NullPointerException, IllegalArgumentException {
+ checkNull(edge);
+ return addEdge(edge.getSource(), edge.getDestination(), edge.getWeight());
+ }
+
+ @Override
+ public W addEdgeAndVertices(V vertex1, V vertex2, W weight) throws NullPointerException {
+ addIfAbsent(vertex1);
+ addIfAbsent(vertex2);
+ return addEdge(vertex1, vertex2, weight);
+ }
+
+ @Override
+ public W addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException {
+ return addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight());
+ }
+
+ @Override
+ public void addAllEdges(Collection> edges) throws NullPointerException {
+ edges.forEach((edge) -> addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight()));
+ }
+
+ @Override
+ public W getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex1);
+ checkNullAndExist(vertex2);
+ return getWeightImpl(vertex1, vertex2);
+ }
+
+ @Override
+ public Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ return getEdgesOutImpl(vertex);
+ }
+
+ @Override
+ public Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ return getEdgesInImpl(vertex);
+ }
+
+ @Override
+ public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex1);
+ checkNullAndExist(vertex2);
+ removeEdgeImpl(vertex1, vertex2);
+ graphChanged();
+ }
+
+ @Override
+ public void removeAllOutEdge(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ removeAllOutEdgeImpl(vertex);
+ graphChanged();
+ }
+
+ @Override
+ public void removeAllInEdge(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ removeAllInEdgeImpl(vertex);
+ graphChanged();
+ }
+
+ @Override
+ public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ removeVertex(vertex);
+ addVertex(vertex);
+ }
+
+ @Override
+ public void removeAllEdge() {
+ Collection vert = vertices();
+ removeAllVertices();
+ addAll(vert);
+ graphChanged();
+ }
+
+ @Override
+ public Collection vertices() {
+ Set set = new HashSet<>();
+ this.forEach(set::add);
+ return set;
+ }
+
+ @Override
+ public Collection> edges() {
+ Set> set = new HashSet<>();
+ this.forEach( v -> set.addAll(this.getEdgesOut(v)));
+ return set;
+ }
+
+ @Override
+ public int size() {
+ return vertices().size();
+ }
+
+ @Override
+ public int numberOfEdges() {
+ return edges().size();
+ }
+
+ @Override
+ public int degree(V vertex) throws NullPointerException, IllegalArgumentException {
+ return degreeIn(vertex) + degreeOut(vertex);
+ }
+
+ @Override
+ public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
+ return getAncestors(vertex).size();
+ }
+
+ @Override
+ public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
+ return getChildrens(vertex).size();
+ }
+
+ @Override
+ public Collection marks() {
+ Collection ret = new HashSet<>();
+ markers.forEach((m, v) -> {
+ if(v.size() > 0)
+ ret.add(m);
+ });
+
+ return ret;
+ }
+
+ @Override
+ public void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ checkNull(mark);
+
+ Set set = markers.computeIfAbsent(mark, (v) -> new HashSet<>());
+ set.add(vertex);
+ }
+
+ @Override
+ public void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ checkNull(mark);
+ markers.get(mark).remove(vertex);
+ }
+
+ @Override
+ public void unMark(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+ markers.forEach( (mark, set) -> set.remove(vertex) );
+ }
+
+ @Override
+ public Collection getMarkedWith(Object mark) throws NullPointerException {
+ checkNull(mark);
+ return markers.computeIfAbsent(mark, (v) -> new HashSet<>());
+ }
+
+ @Override
+ public Collection getMarks(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ Collection marks = new HashSet<>();
+ markers.forEach( (mark, set) -> {
+ if (set.contains(vertex))
+ marks.add(mark);
+ });
+
+ return marks;
+ }
+
+ @Override
+ public void unMarkAll(Object mark) {
+ checkNull(mark);
+ markers.remove(mark);
+ }
+
+ @Override
+ public void unMarkAll() {
+ markers.clear();
+ }
+
+ @Override
+ public Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ Collection> coll = getEdgesIn(vertex);
+ coll.addAll(getEdgesOut(vertex));
+ return coll;
+ }
+
+ @Override
+ public Collection getChildrens(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ Set set = new HashSet<>();
+ getEdgesOut(vertex).forEach(e -> set.add(e.getDestination()));
+ return set;
+ }
+
+ @Override
+ public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(vertex);
+
+ Set set = new HashSet<>();
+ getEdgesIn(vertex).forEach(e -> set.add(e.getSource()));
+ return set;
+ }
+
+ @Override
+ public VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, IllegalArgumentException {
+ return strategy.visit(this, source, visit);
+ }
+
+ @Override
+ public Graph transpose() {
+ Graph graph = getNewInstance();
+ graph.addAll(vertices());
+ for(Edge edge : edges())
+ graph.addEdge(edge.getDestination(), edge.getSource(), edge.getWeight());
+
+ return graph;
+ }
+
+ @Override
+ public List topologicalSort() throws UnsupportedOperationException {
+ if (!isDAG())
+ throw new UnsupportedOperationException(NOT_DAG);
+ return getTarjan().getTopologicalSort();
+ }
+
+ @Override
+ public Collection> stronglyConnectedComponents() {
+ return getTarjan().getSCC();
+ }
+
+ @Override
+ public Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException {
+ Graph sub = getNewInstance();
+
+ Set vertices = new HashSet<>();
+ new Depth(Math.max(depth, 0)).visit(this, source, vertices::add);
+
+ sub.addAll(vertices);
+ for (V vertex : vertices)
+ getEdgesOut(vertex).forEach((edge) -> {
+ if(sub.contains(edge.getSource()) && sub.contains(edge.getDestination()))
+ sub.addEdge(edge);
+ });
+
+ return sub;
+ }
+
+ @Override
+ public Graph subGraph(final Object...marker) {
+ final Graph sub = getNewInstance();
+ final Set allVertices = new HashSet<>();
+ final Set allMarkers = new HashSet<>();
+ final boolean isEmpty = (marker == null || marker.length == 0);
+
+ if (!isEmpty)
+ Collections.addAll(allMarkers, marker);
+
+ markers.forEach( (mark, set) -> {
+ if (isEmpty || allMarkers.contains(mark))
+ allVertices.addAll(set);
+ });
+
+ if (isEmpty) {
+ Collection toAdd = vertices();
+ toAdd.removeAll(allVertices);
+ allVertices.clear();
+ allVertices.addAll(toAdd);
+ }
+
+ sub.addAll(allVertices);
+ for (V vertex : sub.vertices())
+ this.edgesOf(vertex).forEach( (edge) -> {
+ if(sub.contains(edge.getSource()) && sub.contains(edge.getDestination()))
+ sub.addEdge(edge);
+ });
+
+ return sub;
+ }
+
+ @Override
+ public List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
+ checkNullAndExist(source);
+ checkNullAndExist(destination);
+
+ Dijkstra dijkstra = getDijkstra(source); /* Cached */
+ List> path = dijkstra.getLastDistance().get(destination);
+ if (path == null)
+ throw new UnsupportedOperationException(NOT_CONNECTED);
+ return new ArrayList<>(path);
+ }
+
+ @Override
+ public Map>> distance(V source) throws NullPointerException, IllegalArgumentException {
+ checkNullAndExist(source);
+ return new HashMap<>(getDijkstra(source).getLastDistance()); /* Cached */
+ }
+
+ /**
+ * Simple function that reset all the caching variables if the graph changed
+ */
+ private void graphChanged() {
+ tarjan = null;
+ dijkstra.clear();
+ }
+
+ /**
+ * Test if the object passed is null.
+ * If it is throw an exception.
+ * @param object the object to test
+ */
+ private void checkNull(Object object) {
+ if (object == null)
+ throw new NullPointerException(PARAM_NULL);
+ }
+
+ /**
+ * Check if the vertex passed is null and if exist in the graph.
+ * If not then throws eventual exception
+ * @param vertex the vertex to test
+ */
+ private void checkNullAndExist(V vertex) {
+ checkNull(vertex);
+ if (!contains(vertex))
+ throw new IllegalArgumentException(VERTEX_NOT_CONTAINED);
+ }
+
+ /**
+ * Simple function that return the result of the Dijkstra visit, with the starting point as source.
+ * It also cache it, so multiple call will return always the same value unless the graph has changed.
+ * @param source the source of the visit
+ * @return the complete visit
+ */
+ private Dijkstra getDijkstra(V source) {
+ if (dijkstra.get(source) == null) {
+ Dijkstra newDijkstra = new Dijkstra<>();
+ newDijkstra.visit(this, source, null);
+ dijkstra.put(source, newDijkstra);
+ }
+
+ return dijkstra.get(source);
+ }
+
+ /**
+ * Simple function that return the result of the Tarjan visit.
+ * It also cache it, so multiple call will return always the same value unless the graph has changed.
+ * @return the tarjan visit
+ */
+ private Tarjan getTarjan() {
+ if (tarjan == null) {
+ tarjan = new Tarjan<>();
+ tarjan.visit(this, null, null);
+ }
+
+ return tarjan;
+ }
+}
diff --git a/src/berack96/lib/graph/impl/AdjGraph.java b/src/berack96/lib/graph/impl/AdjGraph.java
deleted file mode 100644
index de3d4fa..0000000
--- a/src/berack96/lib/graph/impl/AdjGraph.java
+++ /dev/null
@@ -1,319 +0,0 @@
-package berack96.lib.graph.impl;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-
-import berack96.lib.graph.Edge;
-import berack96.lib.graph.Graph;
-import berack96.lib.graph.Vertex;
-import berack96.lib.graph.visit.VisitStrategy;
-import berack96.lib.graph.visit.impl.VisitInfo;
-
-public class AdjGraph implements Graph {
-
- @Override
- public Iterator iterator() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public boolean isCyclic() {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean isDAG() {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public Vertex getVertex(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void addVertex(V vertex) throws NullPointerException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean addVertexIfAbsent(V vertex) throws NullPointerException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void addAllVertices(Collection vertices) throws NullPointerException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeVertex(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeAllVertex() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean contains(V vertex) throws NullPointerException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public Collection marks() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void unMark(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Collection getMarkedWith(Object mark) throws NullPointerException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection getMarks(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void unMarkAll(Object mark) throws NullPointerException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void unMarkAll() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public W addEdge(V vertex1, V vertex2, W weight) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public W addEdge(Edge edge) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public W addEdgeAndVertices(V vertex1, V vertex2, W weight) throws NullPointerException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public W addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void addAllEdges(Collection> edges) throws NullPointerException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public W getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeAllInEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeAllOutEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeAllEdge() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public Collection vertices() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection> edges() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public int degree(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public int numberOfVertices() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public int numberOfEdges() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public VisitInfo visit(V source, VisitStrategy strategy, Consumer visit)
- throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Graph transpose() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public List topologicalSort() throws UnsupportedOperationException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection> stronglyConnectedComponents() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Graph subGraph(Object... marker) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public List> distance(V source, V destination)
- throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Map>> distance(V source) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
-}
diff --git a/src/berack96/lib/graph/impl/ListGraph.java b/src/berack96/lib/graph/impl/ListGraph.java
new file mode 100644
index 0000000..948c680
--- /dev/null
+++ b/src/berack96/lib/graph/impl/ListGraph.java
@@ -0,0 +1,144 @@
+package berack96.lib.graph.impl;
+
+import berack96.lib.graph.Edge;
+import berack96.lib.graph.Graph;
+
+import java.util.*;
+
+/**
+ * An implementation of the graph using an adjacent list for representing the edges
+ *
+ * @param the vertex
+ * @param the weight
+ * @author Berack96
+ */
+public class ListGraph extends AGraph {
+
+ final private Map> adj = new HashMap<>();
+
+ @Override
+ public Iterator iterator() {
+ return adj.keySet().iterator();
+ }
+
+ @Override
+ protected Graph getNewInstance() {
+ return new ListGraph<>();
+ }
+
+ @Override
+ protected void addVertex(V vertex) {
+ adj.put(vertex, new LinkedList<>());
+ }
+
+ @Override
+ protected boolean containsVertex(V vertex) {
+ return adj.containsKey(vertex);
+ }
+
+ @Override
+ protected void removeVertex(V vertex) {
+ adj.remove(vertex);
+ adj.forEach((v, l) -> {
+ Set set = new HashSet<>();
+ l.forEach(adj -> {
+ if(adj.vertex.equals(vertex))
+ set.add(adj);
+ });
+ l.removeAll(set);
+ });
+ }
+
+ @Override
+ protected void removeAllVertices() {
+ adj.clear();
+ }
+
+ @Override
+ protected boolean containsEdgeImpl(V vertex1, V vertex2) {
+ if(!adj.containsKey(vertex1))
+ return false;
+
+ for(Adj a : adj.get(vertex1))
+ if(a.vertex.equals(vertex2))
+ return true;
+ return false;
+ }
+
+ @Override
+ protected W addEdgeImpl(V vertex1, V vertex2, W weight) {
+ W ret = null;
+ List l = adj.get(vertex1);
+ for(Adj a : l)
+ if(a.vertex.equals(vertex2)) {
+ ret = a.weight;
+ a.weight = weight;
+ }
+ if(ret == null)
+ l.add(new Adj(vertex2, weight));
+ return ret;
+ }
+
+ @Override
+ protected W getWeightImpl(V vertex1, V vertex2) {
+ W ret = null;
+ for(Adj a : adj.get(vertex1))
+ if(a.vertex.equals(vertex2))
+ ret = a.weight;
+ return ret;
+ }
+
+ @Override
+ protected Collection> getEdgesOutImpl(V vertex) {
+ Set> set = new HashSet<>();
+ adj.get(vertex).forEach(a -> set.add(new Edge<>(vertex, a.vertex, a.weight)));
+ return set;
+ }
+
+ @Override
+ protected Collection> getEdgesInImpl(V vertex) {
+ Set> set = new HashSet<>();
+ adj.forEach((v, l) -> l.forEach(a -> {
+ if(a.vertex.equals(vertex))
+ set.add(new Edge<>(v, a.vertex, a.weight));
+ }));
+ return set;
+ }
+
+ @Override
+ protected void removeEdgeImpl(V vertex1, V vertex2) {
+ Adj ret = null;
+ List l = adj.get(vertex1);
+ for(Adj a : l)
+ if(a.vertex.equals(vertex2))
+ ret = a;
+ l.remove(ret);
+ }
+
+ @Override
+ protected void removeAllOutEdgeImpl(V vertex) {
+ adj.compute(vertex,(v, l) -> new LinkedList<>());
+ }
+
+ @Override
+ protected void removeAllInEdgeImpl(V vertex) {
+ adj.forEach((v, l) -> {
+ Set set = new HashSet<>();
+ l.forEach(adj -> {
+ if(adj.vertex.equals(vertex))
+ set.add(adj);
+ });
+ l.removeAll(set);
+ });
+ }
+
+ private class Adj {
+ private final V vertex;
+ private W weight;
+
+ private Adj(V vertex, W weight) {
+ this.vertex = vertex;
+ this.weight = weight;
+ }
+ }
+}
diff --git a/src/berack96/lib/graph/impl/MapGraph.java b/src/berack96/lib/graph/impl/MapGraph.java
index 6718030..2584093 100644
--- a/src/berack96/lib/graph/impl/MapGraph.java
+++ b/src/berack96/lib/graph/impl/MapGraph.java
@@ -1,16 +1,10 @@
package berack96.lib.graph.impl;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
-
import berack96.lib.graph.Edge;
import berack96.lib.graph.Graph;
-import berack96.lib.graph.Vertex;
-import berack96.lib.graph.visit.VisitStrategy;
-import berack96.lib.graph.visit.impl.Dijkstra;
-import berack96.lib.graph.visit.impl.Tarjan;
-import berack96.lib.graph.visit.impl.VisitInfo;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Graph that uses HashMap for vertices and edges
@@ -23,7 +17,7 @@ import berack96.lib.graph.visit.impl.VisitInfo;
* @param the weight of the edges
* @author Berack96
*/
-public class MapGraph implements Graph {
+public class MapGraph extends AGraph {
/**
* Map that contains the edges from a vertex to another
@@ -31,321 +25,88 @@ public class MapGraph implements Graph {
* If an edge exist, then it's weight is returned
*/
private final Map> edges = new HashMap<>();
-
- /**
- * Map that contains the marker as key and a set of all the vertices that has it as the value.
- * This map is build like this for performance in creating the marker for multiple vertices.
- * If you flip the parameters (object and set) then has more performance over the single vertex.
- */
- private final Map> markers = new HashMap<>();
-
- /**
- * Need this variable for not calculating each time the SCC or the cyclic part if the graph doesn't change
- */
- private Tarjan tarjan = null;
-
- /**
- * Need this variable for not calculating each time the distance from a vertex to all his destinations if the graph doesn't change
- */
- private Map> dijkstra = new HashMap<>();
-
- @Override
- public boolean isCyclic() {
- return stronglyConnectedComponents().size() != numberOfVertices();
- }
-
- @Override
- public boolean isDAG() {
- return !isCyclic();
- }
-
- @Override
- public Vertex getVertex(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- return new Vertex<>(this, vertex);
- }
-
- @Override
- public void addVertex(V vertex) throws NullPointerException {
- checkNull(vertex);
- edges.put(vertex, new HashMap<>());
- graphChanged();
- }
-
- @Override
- public boolean addVertexIfAbsent(V vertex) throws NullPointerException {
- if (contains(vertex))
- return false;
- addVertex(vertex);
- return true;
- }
-
- @Override
- public void addAllVertices(Collection vertices) throws NullPointerException {
- checkNull(vertices);
- vertices.forEach(this::addVertexIfAbsent);
- }
-
- @Override
- public void removeVertex(V vertex) throws NullPointerException {
- if (contains(vertex)) {
- edges.remove(vertex);
- edges.forEach((v, map) -> map.remove(vertex));
- markers.forEach((mark, set) -> set.remove(vertex));
- graphChanged();
- }
- }
-
- @Override
- public void removeAllVertex() {
- edges.clear();
- markers.clear();
- graphChanged();
- }
-
- @Override
- public boolean contains(V vertex) throws NullPointerException {
- checkNull(vertex);
- return edges.containsKey(vertex);
- }
@Override
- public Collection marks() {
- Collection ret = new HashSet<>();
- markers.forEach((m, v) -> {
- if(v.size() > 0)
- ret.add(m);
- });
-
- return ret;
+ public Iterator iterator() {
+ return edges.keySet().iterator();
}
- @Override
- public void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- checkNull(mark);
-
- Set set = markers.computeIfAbsent(mark, (v) -> new HashSet<>());
- set.add(vertex);
- }
-
- @Override
- public void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- checkNull(mark);
- markers.get(mark).remove(vertex);
- }
-
- @Override
- public void unMark(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- markers.forEach( (mark, set) -> set.remove(vertex) );
- }
@Override
- public Collection getMarkedWith(Object mark) throws NullPointerException {
- checkNull(mark);
- return markers.computeIfAbsent(mark, (v) -> new HashSet<>());
+ protected Graph getNewInstance() {
+ return new MapGraph<>();
+ }
+
+ @Override
+ protected void addVertex(V vertex) {
+ edges.put(vertex, new HashMap<>());
+ }
+
+ @Override
+ protected boolean containsVertex(V vertex) {
+ return edges.containsKey(vertex);
+ }
+
+ @Override
+ protected void removeVertex(V vertex) {
+ edges.remove(vertex);
+ edges.forEach((v, map) -> map.remove(vertex));
+ }
+
+ @Override
+ protected void removeAllVertices() {
+ edges.clear();
+ }
+
+ @Override
+ protected boolean containsEdgeImpl(V vertex1, V vertex2) {
+ return contains(vertex1) && contains(vertex2) && edges.get(vertex1).containsKey(vertex2);
+ }
+
+ @Override
+ protected W addEdgeImpl(V vertex1, V vertex2, W weight) {
+ return edges.get(vertex1).put(vertex2, weight);
+ }
+
+ @Override
+ protected W getWeightImpl(V vertex1, V vertex2) {
+ return edges.get(vertex1).get(vertex2);
}
@Override
- public Collection getMarks(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- Collection marks = new HashSet<>();
- markers.forEach( (mark, set) -> {
- if (set.contains(vertex))
- marks.add(mark);
- });
-
- return marks;
- }
-
- @Override
- public void unMarkAll(Object mark) {
- checkNull(mark);
- markers.remove(mark);
- }
-
- @Override
- public void unMarkAll() {
- markers.clear();
- }
-
- @Override
- public W addEdge(V vertex1, V vertex2, W weight) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex1);
- checkNullAndExist(vertex2);
- checkNull(weight);
-
- W old = edges.get(vertex1).put(vertex2, weight);
- graphChanged();
- return old;
- }
-
- @Override
- public W addEdge(Edge edge) throws NullPointerException, IllegalArgumentException {
- return addEdge(edge.getSource(), edge.getDestination(), edge.getWeight());
- }
-
- @Override
- public W addEdgeAndVertices(V vertex1, V vertex2, W weight) throws NullPointerException {
- addVertexIfAbsent(vertex1);
- addVertexIfAbsent(vertex2);
- return addEdge(vertex1, vertex2, weight);
- }
-
- @Override
- public W addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException {
- return addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight());
- }
-
- @Override
- public void addAllEdges(Collection> edges) throws NullPointerException {
- edges.forEach((edge) -> addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight()));
- }
-
- @Override
- public W getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex1);
- checkNullAndExist(vertex2);
-
- return edges.get(vertex1).get(vertex2);
- }
-
- @Override
- public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex1);
- checkNullAndExist(vertex2);
-
- edges.get(vertex1).remove(vertex2);
- graphChanged();
- }
-
- @Override
- public void removeAllInEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- edges.forEach((v, map) -> map.remove(vertex));
- graphChanged();
- }
-
- @Override
- public void removeAllOutEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- edges.put(vertex, new HashMap<>());
- graphChanged();
- }
-
- @Override
- public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- removeVertex(vertex);
- addVertex(vertex);
- }
-
- @Override
- public void removeAllEdge() {
- edges.forEach((v, map) -> map.clear());
- graphChanged();
- }
-
- @Override
- public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException {
- return (contains(vertex1) && contains(vertex2)) && edges.get(vertex1).get(vertex2) != null;
- }
-
- @Override
- public Collection vertices() {
- return new HashSet<>(edges.keySet());
- }
-
- @Override
- public Collection> edges() {
- Set> allEdges = new HashSet<>();
- edges.forEach((source, map) -> map.forEach((destination, weight) -> allEdges.add(new Edge<>(source, destination, weight))));
- return allEdges;
- }
-
- @Override
- public Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- Set> set = new HashSet<>();
- edges.forEach((source, map) -> map.forEach((destination, weight) -> {
- if (destination.equals(vertex) || source.equals(vertex))
- set.add(new Edge<>(source, destination, weight));
- }));
- return set;
- }
-
- @Override
- public Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
+ protected Collection> getEdgesOutImpl(V vertex) {
Collection> collection = new HashSet<>();
+ edges.get(vertex).forEach((dest, weight) -> collection.add(new Edge<>(vertex, dest, weight)));
+ return collection;
+ }
+
+ @Override
+ protected Collection> getEdgesInImpl(V vertex) {
+ Collection> collection = new HashSet<>();
edges.forEach((source, edge) -> {
if (edge.get(vertex) != null)
collection.add(new Edge<>(source, vertex, edge.get(vertex)));
});
-
return collection;
- }
+ }
- @Override
- public Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
- Collection> collection = new HashSet<>();
- edges.get(vertex).forEach((dest, weight) -> collection.add(new Edge<>(vertex, dest, weight)));
+ @Override
+ protected void removeEdgeImpl(V vertex1, V vertex2) {
+ edges.get(vertex1).remove(vertex2);
+ }
- return collection;
- }
+ @Override
+ protected void removeAllOutEdgeImpl(V vertex) {
+ edges.put(vertex, new HashMap<>());
+ }
- @Override
- public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- return new HashSet<>(edges.get(vertex).keySet());
- }
-
- @Override
- public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- Set set = new HashSet<>();
- edges.forEach((v, map) -> {
- if (map.containsKey(vertex)) set.add(v);
- });
- return set;
- }
-
- @Override
- public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- AtomicInteger sum = new AtomicInteger();
- edges.forEach((v, map) -> {
- if (map.containsKey(vertex))
- sum.getAndIncrement();
- });
-
- return sum.get();
- }
-
- @Override
- public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(vertex);
-
- return edges.get(vertex).size();
- }
-
- @Override
- public int degree(V vertex) throws NullPointerException, IllegalArgumentException {
- return degreeIn(vertex) + degreeOut(vertex);
- }
-
- @Override
- public int numberOfVertices() {
+ @Override
+ protected void removeAllInEdgeImpl(V vertex) {
+ edges.forEach((v, map) -> map.remove(vertex));
+ }
+
+ @Override
+ public int size() {
return edges.size();
}
@@ -356,189 +117,4 @@ public class MapGraph implements Graph {
return sum.get();
}
-
- @Override
- public VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, IllegalArgumentException {
- return strategy.visit(this, source, visit);
- }
-
- @Override
- public Graph transpose() {
- Graph graph = new MapGraph<>();
- for (V vertex : edges.keySet())
- graph.addVertex(vertex);
-
- edges.forEach((source, map) -> map.forEach((destination, weight) -> graph.addEdge(destination, source, weight)));
-
- return graph;
- }
-
- @Override
- public List topologicalSort() throws UnsupportedOperationException {
- if (!isDAG())
- throw new UnsupportedOperationException(NOT_DAG);
- return getTarjan().getTopologicalSort();
- }
-
- @Override
- public Collection> stronglyConnectedComponents() {
- return getTarjan().getSCC();
- }
-
- @Override
- public Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException {
- Graph sub = new MapGraph<>();
- Set vertices = new HashSet<>();
-
- int finalDepth = depth > 0 ? depth : 0;
- VisitStrategy strategy = (graph, sourceVertex, visit) -> {
- int currentDepth = 0;
- final LinkedList> toVisitChildren = new LinkedList<>();
- toVisitChildren.add(new AbstractMap.SimpleEntry<>(sourceVertex, 0));
- vertices.add(source);
-
- while (!toVisitChildren.isEmpty() && currentDepth + 1 <= finalDepth) {
- final Map.Entry current = toVisitChildren.removeFirst();
- currentDepth = current.getValue() + 1;
- final int finalCurrentDepth = currentDepth;
-
- for (V child : graph.getChildren(current.getKey()))
- if (!vertices.contains(child)) {
- toVisitChildren.addLast(new AbstractMap.SimpleEntry<>(child, finalCurrentDepth));
- vertices.add(child);
- }
- }
- return null;
- };
-
- strategy.visit(this, source, null);
-
- sub.addAllVertices(vertices);
- for (V vertex : vertices)
- getEdgesOut(vertex).forEach((edge) -> {
- try {
- sub.addEdge(edge);
- } catch (Exception ignored) {
- }
- });
-
- return sub;
- }
-
- @Override
- public Graph subGraph(final Object...marker) {
- final Graph sub = new MapGraph<>();
- final Set allVertices = new HashSet<>();
- final Set allMarkers = new HashSet<>();
- final boolean isEmpty = (marker == null || marker.length == 0);
-
- if (!isEmpty)
- for (Object mark: marker)
- allMarkers.add(mark);
-
- markers.forEach( (mark, set) -> {
- if (isEmpty || allMarkers.contains(mark))
- allVertices.addAll(set);
- });
-
- if (isEmpty) {
- Collection toAdd = vertices();
- toAdd.removeAll(allVertices);
- allVertices.clear();
- allVertices.addAll(toAdd);
- }
-
- sub.addAllVertices(allVertices);
- for (V vertex : sub.vertices())
- edges.get(vertex).forEach( (dest, weight) -> {
- try {
- sub.addEdge(vertex, dest, weight);
- } catch (Exception ignored) {}
- });
-
- return sub;
- }
-
- @Override
- public List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException {
- checkNullAndExist(source);
- checkNullAndExist(destination);
-
- Dijkstra dijkstra = getDijkstra(source); /* Cached */
- List> path = dijkstra.getLastDistance().get(destination);
- if (path == null)
- throw new UnsupportedOperationException(NOT_CONNECTED);
- return new ArrayList<>(path);
- }
-
- @Override
- public Map>> distance(V source) throws NullPointerException, IllegalArgumentException {
- checkNullAndExist(source);
- return new HashMap<>(getDijkstra(source).getLastDistance()); /* Cached */
- }
-
- @Override
- public Iterator iterator() {
- return edges.keySet().iterator();
- }
-
-
- /**
- * Simple function that reset all the caching variables if the graph changed
- */
- private void graphChanged() {
- tarjan = null;
- dijkstra.clear();
- }
-
- /**
- * Simple function that return the result of the Dijkstra visit, with the starting point as source.
- * It also cache it, so multiple call will return always the same value unless the graph has changed.
- * @param source the source of the visit
- * @return the complete visit
- */
- private Dijkstra getDijkstra(V source) {
- if (dijkstra.get(source) == null) {
- Dijkstra newDijkstra = new Dijkstra<>();
- newDijkstra.visit(this, source, null);
- dijkstra.put(source, newDijkstra);
- }
-
- return dijkstra.get(source);
- }
-
- /**
- * Simple function that return the result of the Tarjan visit.
- * It also cache it, so multiple call will return always the same value unless the graph has changed.
- * @return the tarjan visit
- */
- private Tarjan getTarjan() {
- if (tarjan == null) {
- tarjan = new Tarjan<>();
- tarjan.visit(this, null, null);
- }
-
- return tarjan;
- }
-
- /**
- * Test if the object passed is null.
- * If it is throw an exception.
- * @param object the object to test
- */
- private void checkNull(Object object) {
- if (object == null)
- throw new NullPointerException(PARAM_NULL);
- }
-
- /**
- * Check if the vertex passed is null and if exist in the graph.
- * If not then throws eventual exception
- * @param vertex the vertex to test
- */
- private void checkNullAndExist(V vertex) {
- checkNull(vertex);
- if (!edges.containsKey(vertex))
- throw new IllegalArgumentException(VERTEX_NOT_CONTAINED);
- }
}
diff --git a/src/berack96/lib/graph/impl/MatrixGraph.java b/src/berack96/lib/graph/impl/MatrixGraph.java
index 896cf96..fd5d615 100644
--- a/src/berack96/lib/graph/impl/MatrixGraph.java
+++ b/src/berack96/lib/graph/impl/MatrixGraph.java
@@ -1,319 +1,132 @@
package berack96.lib.graph.impl;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-
import berack96.lib.graph.Edge;
import berack96.lib.graph.Graph;
-import berack96.lib.graph.Vertex;
-import berack96.lib.graph.visit.VisitStrategy;
-import berack96.lib.graph.visit.impl.VisitInfo;
-public class MatrixGraph implements Graph {
+import java.util.*;
+
+/**
+ * An implementation of the graph using a matrix for representing the edges
+ *
+ * @param the vertex
+ * @param the weight
+ * @author Berack96
+ */
+public class MatrixGraph extends AGraph {
+
+ final Map map = new HashMap<>();
+ final List> matrix = new ArrayList<>();
@Override
public Iterator iterator() {
- // TODO Auto-generated method stub
- return null;
+ return map.keySet().iterator();
}
@Override
- public boolean isCyclic() {
- // TODO Auto-generated method stub
- return false;
+ protected Graph getNewInstance() {
+ return new MatrixGraph<>();
}
@Override
- public boolean isDAG() {
- // TODO Auto-generated method stub
- return false;
+ protected void addVertex(V vertex) {
+ map.put(vertex, map.size());
+
+ List newVert = new ArrayList<>(map.size());
+ for (int i=0; i list.add(null));
+ matrix.add(newVert);
}
@Override
- public Vertex getVertex(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
+ protected boolean containsVertex(V vertex) {
+ return map.containsKey(vertex);
}
@Override
- public void addVertex(V vertex) throws NullPointerException {
- // TODO Auto-generated method stub
-
+ protected void removeVertex(V vertex) {
+ int x = map.remove(vertex);
+ map.replaceAll((vert, index) -> index>x? index-1:index);
+
+ matrix.remove(x);
+ matrix.forEach(list -> {
+ int i;
+ for(i=x; i0)
+ list.remove(i);
+ });
}
@Override
- public boolean addVertexIfAbsent(V vertex) throws NullPointerException {
- // TODO Auto-generated method stub
- return false;
+ protected void removeAllVertices() {
+ map.clear();
+ matrix.clear();
}
@Override
- public void addAllVertices(Collection vertices) throws NullPointerException {
- // TODO Auto-generated method stub
-
+ protected boolean containsEdgeImpl(V vertex1, V vertex2) {
+ try {
+ return matrix.get(map.get(vertex1)).get(map.get(vertex2)) != null;
+ } catch (Exception ignore) {
+ return false;
+ }
}
@Override
- public void removeVertex(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
+ protected W addEdgeImpl(V vertex1, V vertex2, W weight) {
+ return matrix.get(map.get(vertex1)).set(map.get(vertex2), weight);
}
@Override
- public void removeAllVertex() {
- // TODO Auto-generated method stub
-
+ protected W getWeightImpl(V vertex1, V vertex2) {
+ return matrix.get(map.get(vertex1)).get(map.get(vertex2));
}
@Override
- public boolean contains(V vertex) throws NullPointerException {
- // TODO Auto-generated method stub
- return false;
+ protected Collection> getEdgesOutImpl(V vertex) {
+ Set> set = new HashSet<>();
+ Map inverted = new HashMap<>();
+ map.keySet().forEach(v -> inverted.put(map.get(v), v));
+
+ List list = matrix.get(map.get(vertex));
+ for(int i=0; i(vertex, inverted.get(i), weight));
+ }
+ return set;
}
@Override
- public Collection marks() {
- // TODO Auto-generated method stub
- return null;
+ protected Collection> getEdgesInImpl(V vertex) {
+ Set> set = new HashSet<>();
+ Map inverted = new HashMap<>();
+ map.keySet().forEach(v -> inverted.put(map.get(v), v));
+
+ int x = map.get(vertex);
+ for(int i=0; i(inverted.get(i), vertex, weight));
+ }
+ return set;
}
@Override
- public void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
+ protected void removeEdgeImpl(V vertex1, V vertex2) {
+ matrix.get(map.get(vertex1)).set(map.get(vertex2), null);
}
@Override
- public void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
+ protected void removeAllOutEdgeImpl(V vertex) {
+ matrix.get(map.get(vertex)).replaceAll(var -> null);
}
@Override
- public void unMark(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
+ protected void removeAllInEdgeImpl(V vertex) {
+ int x = map.get(vertex);
+ matrix.forEach(list -> list.set(x, null));
}
-
- @Override
- public Collection getMarkedWith(Object mark) throws NullPointerException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection getMarks(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void unMarkAll(Object mark) throws NullPointerException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void unMarkAll() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public W addEdge(V vertex1, V vertex2, W weight) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public W addEdge(Edge edge) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public W addEdgeAndVertices(V vertex1, V vertex2, W weight) throws NullPointerException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public W addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void addAllEdges(Collection> edges) throws NullPointerException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public W getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeAllInEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeAllOutEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeAllEdge() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public Collection vertices() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection> edges() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public int degree(V vertex) throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public int numberOfVertices() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public int numberOfEdges() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public VisitInfo visit(V source, VisitStrategy strategy, Consumer visit)
- throws NullPointerException, IllegalArgumentException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Graph