From 07305b82f84cf4388d290f8957c8fa19fb73d796 Mon Sep 17 00:00:00 2001 From: Berack96 Date: Tue, 30 Aug 2022 11:12:50 +0200 Subject: [PATCH] Refactoring - changed to maven - modified hashMap and HashSet to Tree - modified files path --- .gitignore | 5 +- build.gradle | 32 - pom.xml | 80 + .../java}/berack96/lib/graph/Edge.java | 0 .../java}/berack96/lib/graph/Graph.java | 1307 +++++++++-------- .../berack96/lib/graph/GraphDirected.java | 40 +- .../berack96/lib/graph/GraphUndirected.java | 15 +- .../berack96/lib/graph/ObjectsComparator.java | 18 + .../java}/berack96/lib/graph/Vertex.java | 0 .../berack96/lib/graph/impl/ListGraph.java | 321 ++-- .../berack96/lib/graph/impl/MapGraph.java | 231 +-- .../berack96/lib/graph/impl/MatrixGraph.java | 392 ++--- .../lib/graph/impl/MatrixUndGraph.java | 31 +- .../lib/graph/models/EdgeSaveStructure.java | 34 +- .../lib/graph/models/GraphSaveStructure.java | 208 +-- .../lib/graph/models/MarkSaveStructure.java | 34 +- .../berack96/lib/graph/struct/QuickFind.java | 15 +- .../berack96/lib/graph/struct/UnionFind.java | 0 .../berack96/lib/graph/view/GraphInfo.java | 9 +- .../lib/graph/view/GraphListener.java | 0 .../berack96/lib/graph/view/GraphPanel.java | 0 .../lib/graph/view/GraphPointsSave.java | 0 .../berack96/lib/graph/view/GraphWindow.java | 0 .../lib/graph/view/GraphicalView.java | 0 .../java}/berack96/lib/graph/view/Main.java | 46 +- .../lib/graph/view/VisitListener.java | 0 .../lib/graph/view/edge/EdgeComponent.java | 0 .../lib/graph/view/edge/EdgeIntListener.java | 0 .../lib/graph/view/edge/EdgeListener.java | 0 .../lib/graph/view/edge/EdgeView.java | 0 .../berack96/lib/graph/view/stuff/Arrow.java | 0 .../graph/view/vertex/VertexComponent.java | 0 .../graph/view/vertex/VertexIntListener.java | 0 .../lib/graph/view/vertex/VertexListener.java | 0 .../lib/graph/view/vertex/VertexView.java | 0 .../lib/graph/visit/VisitDistSourceDest.java | 0 .../lib/graph/visit/VisitDistance.java | 0 .../berack96/lib/graph/visit/VisitMST.java | 7 +- .../berack96/lib/graph/visit/VisitSCC.java | 4 +- .../lib/graph/visit/VisitStrategy.java | 88 +- .../lib/graph/visit/VisitTopological.java | 0 .../berack96/lib/graph/visit/impl/BFS.java | 0 .../berack96/lib/graph/visit/impl/DFS.java | 0 .../lib/graph/visit/impl/Dijkstra.java | 6 +- .../lib/graph/visit/impl/Kruskal.java | 6 +- .../berack96/lib/graph/visit/impl/Prim.java | 11 +- .../berack96/lib/graph/visit/impl/Tarjan.java | 12 +- .../lib/graph/visit/impl/VisitInfo.java | 0 .../java}/berack96/test/lib/TestGraph.java | 26 +- src/test/java/resources/test.json | 1 + .../test/java}/resources/test.json.fail | 0 test/resources/test.json | 54 - 52 files changed, 1547 insertions(+), 1486 deletions(-) delete mode 100644 build.gradle create mode 100644 pom.xml rename src/{ => main/java}/berack96/lib/graph/Edge.java (100%) rename src/{ => main/java}/berack96/lib/graph/Graph.java (86%) rename src/{ => main/java}/berack96/lib/graph/GraphDirected.java (86%) rename src/{ => main/java}/berack96/lib/graph/GraphUndirected.java (70%) create mode 100644 src/main/java/berack96/lib/graph/ObjectsComparator.java rename src/{ => main/java}/berack96/lib/graph/Vertex.java (100%) rename src/{ => main/java}/berack96/lib/graph/impl/ListGraph.java (86%) rename src/{ => main/java}/berack96/lib/graph/impl/MapGraph.java (79%) rename src/{ => main/java}/berack96/lib/graph/impl/MatrixGraph.java (87%) rename src/{ => main/java}/berack96/lib/graph/impl/MatrixUndGraph.java (83%) rename src/{ => main/java}/berack96/lib/graph/models/EdgeSaveStructure.java (95%) rename src/{ => main/java}/berack96/lib/graph/models/GraphSaveStructure.java (92%) rename src/{ => main/java}/berack96/lib/graph/models/MarkSaveStructure.java (94%) rename src/{ => main/java}/berack96/lib/graph/struct/QuickFind.java (85%) rename src/{ => main/java}/berack96/lib/graph/struct/UnionFind.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/GraphInfo.java (98%) rename src/{ => main/java}/berack96/lib/graph/view/GraphListener.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/GraphPanel.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/GraphPointsSave.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/GraphWindow.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/GraphicalView.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/Main.java (97%) rename src/{ => main/java}/berack96/lib/graph/view/VisitListener.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/edge/EdgeComponent.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/edge/EdgeIntListener.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/edge/EdgeListener.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/edge/EdgeView.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/stuff/Arrow.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/vertex/VertexComponent.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/vertex/VertexIntListener.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/vertex/VertexListener.java (100%) rename src/{ => main/java}/berack96/lib/graph/view/vertex/VertexView.java (100%) rename src/{ => main/java}/berack96/lib/graph/visit/VisitDistSourceDest.java (100%) rename src/{ => main/java}/berack96/lib/graph/visit/VisitDistance.java (100%) rename src/{ => main/java}/berack96/lib/graph/visit/VisitMST.java (64%) rename src/{ => main/java}/berack96/lib/graph/visit/VisitSCC.java (86%) rename src/{ => main/java}/berack96/lib/graph/visit/VisitStrategy.java (97%) rename src/{ => main/java}/berack96/lib/graph/visit/VisitTopological.java (100%) rename src/{ => main/java}/berack96/lib/graph/visit/impl/BFS.java (100%) rename src/{ => main/java}/berack96/lib/graph/visit/impl/DFS.java (100%) rename src/{ => main/java}/berack96/lib/graph/visit/impl/Dijkstra.java (95%) rename src/{ => main/java}/berack96/lib/graph/visit/impl/Kruskal.java (90%) rename src/{ => main/java}/berack96/lib/graph/visit/impl/Prim.java (88%) rename src/{ => main/java}/berack96/lib/graph/visit/impl/Tarjan.java (93%) rename src/{ => main/java}/berack96/lib/graph/visit/impl/VisitInfo.java (100%) rename {test => src/test/java}/berack96/test/lib/TestGraph.java (98%) create mode 100644 src/test/java/resources/test.json rename {test => src/test/java}/resources/test.json.fail (100%) delete mode 100644 test/resources/test.json diff --git a/.gitignore b/.gitignore index 786237e..689f042 100644 --- a/.gitignore +++ b/.gitignore @@ -125,8 +125,9 @@ local.properties # mine +target/ .idea/* .project *.iml -.classpath -/.gradle/ +.classpath +/.gradle/ diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 58ef372..0000000 --- a/build.gradle +++ /dev/null @@ -1,32 +0,0 @@ -apply plugin: 'java' -apply plugin: 'eclipse' - -version='1.0-SNAPSHOT' - -jar { - manifest { - attributes 'Main-Class': 'berack96.lib.graph.view.Main' - } - from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } -} - -test { - useJUnitPlatform() -} - -sourceSets.main.java { - srcDirs "src" - srcDirs "test" -} - -repositories { - mavenCentral() -} - -dependencies { - 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:5.5.2' -} \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5cfc0ad --- /dev/null +++ b/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + berack96 + Graph + 1.0-SNAPSHOT + + + org.junit.jupiter + junit-jupiter-api + 5.9.0 + test + + + org.junit.jupiter + junit-jupiter-params + 5.9.0 + test + + + com.google.code.gson + gson + 2.9.1 + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.2 + + + org.apache.maven.plugins + maven-assembly-plugin + 2.2 + + + jar-with-dependencies + + + + berack96.lib.graph.view.Main + + + + + + package + + single + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + prepare-package + + jar + + + + + + + + 17 + 17 + + + \ No newline at end of file diff --git a/src/berack96/lib/graph/Edge.java b/src/main/java/berack96/lib/graph/Edge.java similarity index 100% rename from src/berack96/lib/graph/Edge.java rename to src/main/java/berack96/lib/graph/Edge.java diff --git a/src/berack96/lib/graph/Graph.java b/src/main/java/berack96/lib/graph/Graph.java similarity index 86% rename from src/berack96/lib/graph/Graph.java rename to src/main/java/berack96/lib/graph/Graph.java index 7d58ece..a6c93e5 100644 --- a/src/berack96/lib/graph/Graph.java +++ b/src/main/java/berack96/lib/graph/Graph.java @@ -1,638 +1,669 @@ -package berack96.lib.graph; - -import berack96.lib.graph.visit.VisitStrategy; -import berack96.lib.graph.visit.impl.BFS; -import berack96.lib.graph.visit.impl.Dijkstra; -import berack96.lib.graph.visit.impl.VisitInfo; - -import java.util.*; -import java.util.function.Consumer; - -/** - * An abstract class for the graphs.
- * This class is used for the graphs in general.
- * There are more specific {@link GraphDirected} and {@link GraphUndirected} edges graph interfaces.
- * - * @param The Object that represent a vertex - * @author Berack96 - */ -public abstract class Graph implements Iterable { - - public static final int NO_EDGE = 0; - public final static String NOT_CONNECTED = "The source vertex doesn't have a path that reach the destination"; - public final static String PARAM_NULL = "The parameter must not be null"; - public final static String VERTEX_NOT_CONTAINED = "The vertex must be contained in the graph"; - - /** - * Map that contains the vertex as key and a set of all the marker associated with it. - */ - private final Map> markers = new HashMap<>(); - - /** - * Get a new instance of this Graph. - * - * @return A new instance of the graph - */ - protected abstract Graph getNewInstance(); - - /** - * Check if the vertex passed is contained in the graph or not.
- * The vertex V1 is contained in the graph G, if and only if:
- * exist V2 in G such that V2 == V1 - * - * @param vertex the vertex to check - * @return true if the vertex is contained, false otherwise - */ - public abstract boolean contains(V vertex) throws NullPointerException; - - /** - * Get an instance of the vertex linked with this graph.
- * For more info see {@link Vertex} - * - * @param vertex the vertex - * @return a vertex - * @throws IllegalArgumentException if the vertex is not contained in the graph - */ - public final Vertex get(V vertex) throws IllegalArgumentException { - checkVert(vertex); - return new Vertex<>(this, vertex); - } - - /** - * Add the vertex to the graph. If it's already in the graph it will be replaced and all its edges will be reset.
- * Of course the vertex added will have no marks nor edge to any other vertex nor form any other vertex. - * - * @param vertex the vertex to add - * @throws NullPointerException if the vertex is null - */ - public abstract void add(V vertex) throws NullPointerException; - - /** - * Add the specified vertex to the graph only if the graph doesn't contains it.
- * The graph contains a vertex only if the method {@link #contains(Object)} returns true. - * - * @param vertex the vertex to add - * @return true if it adds a vertex, false if it was already in the graph - * @throws NullPointerException if the vertex is null - */ - public final boolean addIfAbsent(V vertex) throws NullPointerException { - if (contains(vertex)) - return false; - add(vertex); - return true; - } - - /** - * Add all the vertices contained in the collection to the graph.
- * If a vertex is contained in the collection and in the graph is ignored and it will not be replaced.
- * Null vertices will be ignored and they will not be added to the graph. - * - * @param vertices a collection of the vertices to add - * @throws NullPointerException if the set is null - */ - public void addAll(@SuppressWarnings("ConstantConditions") Collection vertices) throws NullPointerException { - check(vertices); - for (V vertex : vertices) - addIfAbsent(vertex); - } - - /** - * Remove the selected vertex from the graph.
- * After this method's call the vertex will be no longer present in the graph, and nether all his edges and marks. - * - * @param vertex the vertex to remove - * @throws NullPointerException if the vertex is null - * @throws IllegalArgumentException if the vertex is not contained - */ - public abstract 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. - */ - public void removeAll() { - unMarkAll(); - for (V vertex : vertices()) - remove(vertex); - } - - /** - * Check if the edge between the two vertex passed is contained in the graph or not.
- * 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 - */ - public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException { - try { - return getWeight(vertex1, vertex2) != NO_EDGE; - } catch (IllegalArgumentException ignore) { - return false; - } - } - - /** - * Get the weight of the selected edge.
- * If the edge doesn't exist, then 0 is returned - * - * @param vertex1 a vertex of the graph - * @param vertex2 a vertex of the graph - * @return the weight previously set, or 0 if the edge doesn't exist - * @throws NullPointerException if one of the parameters is null - * @throws IllegalArgumentException if one of the vertex is not contained in the graph - */ - public abstract int getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException; - - /** - * Add an edge between the two vertex.
- * This method will overwrite any existing edge between the two vertex.
- * If there was a previous edge then it is returned - * - * @param edge the edge to add - * @return 0 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 - */ - public final int addEdge(Edge edge) throws NullPointerException, IllegalArgumentException { - return addEdge(edge.getSource(), edge.getDestination(), edge.getWeight()); - } - - /** - * Add an edge between the two vertex.
- * This method will overwrite any existing edge between the two vertices.
- * By default using this method will set the edge to the value 1. - * - * @param vertex1 a vertex of the graph - * @param vertex2 a vertex of the graph - * @throws NullPointerException if one of the parameter is null - * @throws IllegalArgumentException if one of the vertex is not contained in the graph - */ - public final void addEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException { - addEdge(vertex1, vertex2, 1); - } - - /** - * Add an edge between the two vertex.
- * This method will overwrite any existing edge between the two vertex.
- * If there was a previous edge then it's value is returned.
- * If the weight passed is equals to 0 or {@link Graph#NO_EDGE}, then - * the edge will be removed. - * - * @param vertex1 a vertex of the graph - * @param vertex2 a vertex of the graph - * @param weight the weight of the edge - * @return 0 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 - */ - public abstract int addEdge(V vertex1, V vertex2, int weight) throws NullPointerException, IllegalArgumentException; - - /** - * This particular function add an edge to the graph.
- * If one of the two, or both vertices of the edge aren't contained in the graph, then the vertices will be added.
- * This method will overwrite any existing edge between the two vertices.
- * If there was a previous edge then it is returned - * - * @param edge the edge to add - * @return 0 or the previous weight of the edge if there was already one - * @throws NullPointerException if one of the parameter is null - */ - public final int addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException { - return addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight()); - } - - /** - * This particular function add an edge to the graph.
- * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
- * This method will overwrite any existing edge between the two vertices.
- * By default using this method will set the edge to the value 1. - * - * @param vertex1 a vertex of the graph - * @param vertex2 a vertex of the graph - * @throws NullPointerException if one of the parameter is null - */ - public final int addEdgeAndVertices(V vertex1, V vertex2) throws NullPointerException { - return addEdgeAndVertices(vertex1, vertex2, 1); - } - - /** - * This particular function add an edge to the graph.
- * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
- * This method will overwrite any existing edge between the two vertices.
- * If there was a previous edge then it is returned - * - * @param vertex1 a vertex of the graph - * @param vertex2 a vertex of the graph - * @param weight the weight of the edge - * @return 0 or the previous weight of the edge if there was already one - * @throws NullPointerException if one of the parameter is null - */ - public final int addEdgeAndVertices(V vertex1, V vertex2, int weight) throws NullPointerException { - addIfAbsent(vertex1); - addIfAbsent(vertex2); - return addEdge(vertex1, vertex2, weight); - } - - /** - * Add all the edges of the collection to the graph.
- * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
- * Any null edges will be ignored.
- * This method will overwrite any existing edge between the two vertices. - * - * @param edges the edges to add - * @throws NullPointerException if the set is null - */ - public void addAllEdges(Collection> edges) throws NullPointerException { - edges.forEach(edge -> addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight())); - } - - /** - * Remove the edge between the two vertex by setting it's value to 0.
- * If the edge doesn't exist, then this call does nothing.
- * This method is equivalent to calling {@link Graph#addEdge(Object, Object, int)} )} - * with the weight set to {@link Graph#NO_EDGE} - * - * @param vertex1 a vertex of the graph - * @param vertex2 a vertex of the graph - * @throws NullPointerException if one of the parameters is null - * @throws IllegalArgumentException if one of the vertex is not contained in the graph - */ - public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException { - addEdge(vertex1, vertex2, NO_EDGE); - } - - /** - * Remove all edges form a particular vertex of the graph.
- * After this method's call the selected vertex will have 0 edges.
- * It will be no longer possible to reach this vertex from any other vertex, and vice versa. - * - * @param vertex a vertex of the graph - * @throws NullPointerException if the vertex is null - * @throws IllegalArgumentException if one of the vertex is not contained in the graph - */ - public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException { - unMark(vertex); - remove(vertex); - add(vertex); - } - - /** - * Remove all the edges of the graph.
- * After this method's call the graph will have only vertices, and no edge. - */ - public void removeAllEdge() { - Collection vertices = vertices(); - removeAll(); - addAll(vertices); - } - - /** - * Retrieve all the edges of a particular vertex.
- * - * @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 - */ - public abstract Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException; - - /** - * Get all the vertices that are children of the vertex passed as parameter.
- * The vertices V(0-N) that are 'children' of a vertex V1, are all the vertices that have an edge - * where V1 is the source of that edge. - * - * @param vertex the source vertex - * @return an array of vertices - * @throws NullPointerException if the vertex is null - * @throws IllegalArgumentException if the vertex is not contained in the graph - */ - public abstract Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException; - - /** - * Get all the vertices that have the vertex passed as their child.
- * Basically is the opposite of {@link #getChildren(Object)} - * - * @param vertex a vertex of the graph - * @return an array of ancestors of the vertex - * @throws NullPointerException if one of the parameters is null - * @throws IllegalArgumentException if one of the vertex is not contained in the graph - */ - public abstract Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException; - - /** - * Get all the marks of this graph.
- * Specifically it will return a collection of marks where every mark
- * as associated at least one vertex of the graph.
- * If the graph doesn't have vertex marked then it is returned an empty collection. - * - * @return a collection of marks - */ - public final Collection marks() { - Collection ret = new HashSet<>(); - markers.forEach((v, set) -> ret.addAll(set)); - return ret; - } - - /** - * Add to the specified vertex the mark passed.
- * A vertex can have multiple marker.
- * The null marker cannot be used. - * - * @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 - */ - public final void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException { - check(mark); - checkVert(vertex); - Set marks = markers.computeIfAbsent(vertex, v -> new HashSet<>()); - marks.add(mark); - } - - /** - * Remove the selected mark from the vertex.
- * - * @param vertex the vertex where remove the mark - * @param mark the mark to remove - * @throws NullPointerException if a param is null - * @throws IllegalArgumentException if the vertex is not contained in the graph - */ - public final void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException { - check(mark); - checkVert(vertex); - markers.computeIfPresent(vertex, (v, set) -> { - set.remove(mark); - if (set.size() > 0) - return set; - return null; - }); - } - - /** - * Unmark the vertex selected.
- * After this call the vertex will not have any marked object to himself. - * - * @param vertex the vertex - * @throws NullPointerException if the vertex is null - * @throws IllegalArgumentException if the vertex is not contained in the graph - */ - public final void unMark(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - try { - markers.remove(vertex).clear(); - } catch (Exception ignore) { - } - } - - /** - * Get all the vertices that are marked with the specific mark passed.
- * If there aren't vertices with that mark then it is returned an empty set.
- * - * @param mark the mark - * @return all the vertices that are marked with that specific mark - * @throws NullPointerException if the mark is null - */ - public final Collection getMarkedWith(Object mark) throws NullPointerException { - check(mark); - Collection vertices = new ArrayList<>(markers.size()); - markers.forEach((v, set) -> { - if (set.contains(mark)) - vertices.add(v); - }); - return vertices; - } - - /** - * Get all the marker of this vertex.
- * If the vertex doesn't have any mark, then it will return an empty set.
- * Note: modifying the returned collection affect the marker of the vertex. - * - * @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 - */ - public final Collection getMarks(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - return markers.getOrDefault(vertex, new HashSet<>()); - } - - /** - * Remove the selected mark from all the vertices - * - * @param mark the mark to remove - * @throws NullPointerException if the mark is null - */ - public final void unMarkAll(Object mark) throws NullPointerException { - check(mark); - Collection toRemove = new ArrayList<>(markers.size()); - markers.forEach((v, set) -> { - set.remove(mark); - if (set.size() == 0) - toRemove.add(v); - }); - markers.keySet().removeAll(toRemove); - } - - /** - * Remove all the marker to all the vertex.
- * After this call the {@link #getMarks(Object)} applied to any vertex will return an empty set - */ - public final void unMarkAll() { - markers.values().forEach(Set::clear); - markers.clear(); - } - - /** - * Get all the vertices in the graph.
- * If the graph doesn't contains vertices, it'll return an empty collection.
- * - * @return an array that include all the vertices - */ - public Collection vertices() { - Collection collection = new ArrayList<>(); - forEach(collection::add); - return collection; - } - - /** - * Get all the edges in the graph.
- * If the graph doesn't contains edges, it'll return an empty collection.
- * - * @return a collection that include all the edges - */ - public abstract Collection> edges(); - - /** - * Tells the degree of a vertex.
- * The degree of a vertex is the quantity of edges that have.
- * Basically, it'll count how many edge it have. - * - * @param vertex a vertex of the graph - * @return the degree of the vertex - * @throws NullPointerException if the vertex is null - * @throws IllegalArgumentException if the vertex is not contained in the graph - */ - public abstract int degree(V vertex) throws NullPointerException, IllegalArgumentException; - - /** - * Tells how many vertices are in the graph. - * - * @return the number of vertices - */ - public abstract int size(); - - /** - * Tells how many edges are in the graph. - * - * @return the number of edges - */ - public abstract int numberOfEdges(); - - /** - * Visit the graph accordingly to the strategy that is passed.
- * Some strategy can accept a source vertex null, because they visit all the graph anyway. - * - * @param source the starting vertex for the visit - * @param strategy the algorithm for visiting the graph - * @param visit the function to apply at each vertex visited - * @return an info of the visit if provided by the strategy - * @throws NullPointerException if one of the parameter is null (except the consumer) - * @throws UnsupportedOperationException in the case the visit cannot be applied to the graph - */ - public final VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, UnsupportedOperationException { - return strategy.visit(this, source, visit); - } - - /** - * Get a sub-graph of the current one based on the maximum depth that is given.
- * If the depth is 1 then only the source and it's children will be in the sub-graph.
- * If the depth is 2 then only the source, it's children and it's children of it's children will be in the sub-graph.
- * And so on.
- * Of course the sub-graph will contain the edges that link the vertices, but only the one selected. - * - * @param source the source vertex - * @param depth the maximum depth (must be a positive number, if <=0 a graph containing only the source is returned) - * @return a sub-graph of the original - * @throws NullPointerException if the vertex is null - * @throws IllegalArgumentException if the vertex is not contained - */ - public final Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException { - checkVert(source); - Graph sub = getNewInstance(); - Set vertices = new HashSet<>(this.size() + 1, 1); - new BFS().setMaxDepth(Math.max(depth, 0)).visit(this, source, vertices::add); - - sub.addAll(vertices); - for (V src : vertices) - for (V dest : getChildren(src)) - if (sub.contains(dest)) - sub.addEdge(new Edge<>(src, dest, this.getWeight(src, dest))); - return sub; - } - - /** - * Get a sub-graph of the current one with only the vertex marked with the selected markers.
- * Each vertex will have all his markers and his edges, but only the ones with the destination marked with the same marker.
- * If the marker is not specified or is null then the returning graph will have all the vertices that are not marked by any marker.
- * If the graph doesn't contain any vertex with that marker then an empty graph is returned. - * - * @param marker one or more markers - * @return a sub-graph of the current graph - */ - public final Graph subGraph(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((v, set) -> { - if (!Collections.disjoint(allMarkers, set)) - allVertices.add(v); - }); - } else { - Collection toAdd = vertices(); - toAdd.removeAll(markers.keySet()); - allVertices.addAll(toAdd); - } - - sub.addAll(allVertices); - for (V src : sub.vertices()) { - for (Object mark : getMarks(src)) - sub.mark(src, mark); - for (V dest : getChildren(src)) - if (sub.contains(dest)) - sub.addEdge(src, dest, getWeight(src, dest)); - } - return sub; - } - - /** - * Get the minimum path from the source vertex to the destination vertex.
- * If the source vertex can't reach the destination, then an exception is thrown. - * - * @param source the vertex where to start - * @param destination the destination chosen - * @return an ordered list of edges from source to destination that represent the minimum path between the two vertices - * @throws NullPointerException if one of the parameter is null (except the consumer) - * @throws IllegalArgumentException if the vertex is not in the graph - * @throws UnsupportedOperationException if from the source it's not possible to reach the destination - */ - public final List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException { - checkVert(source, destination); - List> path = distance(source).get(destination); - if (path == null) - throw new UnsupportedOperationException(NOT_CONNECTED); - return path; - } - - /** - * Get the minimum path from the source vertex to all the possible reachable vertices. - * - * @param source the vertex where to start - * @return a map containing all the possible reachable vertices from the source and the minimum path to reach them - * @throws NullPointerException if one of the parameter is null (except the consumer) - * @throws IllegalArgumentException if the vertex is not in the graph - */ - public final Map>> distance(V source) throws NullPointerException, IllegalArgumentException { - checkVert(source); - Dijkstra dijkstra = new Dijkstra<>(); - dijkstra.visit(this, source, null); - return dijkstra.getLastDistance(); - } - - - /** - * Check if the object passed is not null. - * If it's null then throws eventual exception - * - * @param objects the objects to test - */ - protected final void check(Object... objects) { - for (Object obj : objects) - if (obj == null) - throw new NullPointerException(PARAM_NULL); - } - - /** - * Check if the vertex passed is not null and if exist in the graph. - * If not then throws eventual exception - * - * @param vertices the vertices to test - */ - @SafeVarargs - protected final void checkVert(V... vertices) { - check((Object[]) vertices); - for (V vert : vertices) - try { - if (!contains(vert)) - throw new IllegalArgumentException(VERTEX_NOT_CONTAINED); - } catch (ClassCastException ignore) { - } - } -} +package berack96.lib.graph; + +import berack96.lib.graph.visit.VisitStrategy; +import berack96.lib.graph.visit.impl.BFS; +import berack96.lib.graph.visit.impl.Dijkstra; +import berack96.lib.graph.visit.impl.VisitInfo; + +import java.util.*; +import java.util.function.Consumer; + +/** + * An abstract class for the graphs.
+ * This class is used for the graphs in general.
+ * There are more specific {@link GraphDirected} and {@link GraphUndirected} edges graph interfaces.
+ * + * @param The Object that represent a vertex + * @author Berack96 + */ +public abstract class Graph implements Iterable { + + //------------------- STAIC ----------------- + + public static final int NO_EDGE = 0; + public final static String NOT_CONNECTED = "The source vertex doesn't have a path that reach the destination"; + public final static String PARAM_NULL = "The parameter must not be null"; + public final static String VERTEX_NOT_CONTAINED = "The vertex must be contained in the graph"; + + /** + * Create the default map. All operations are O(log(n))
+ * It returns a TreeMap with a ObjectComparator as comparator.
+ * This way all the graphs will use the same maps.
+ * It is not required to use this method, but it is highly recommended.
+ * + * @return A newly created TreeMap instance with ObjectsComparator as comparator + */ + public final static Map getDefaultMap() { + return new TreeMap(ObjectsComparator.instance); + } + + /** + * Create the default set. All operations are O(log(n))
+ * It returns a TreeSet with a ObjectComparator as comparator.
+ * This way all the graphs will use the same sets.
+ * It is not required to use this method, but it is highly recommended.
+ * + * @return A newly created TreeSet instance with ObjectsComparator as comparator + */ + public final static Set getDefaultSet() { + return new TreeSet(ObjectsComparator.instance); + } + + //------------------- INSTANCE ----------------- + + /** + * Map that contains the vertex as key and a set of all the marker associated with it. + */ + private final Map> markers = getDefaultMap(); + + /** + * Get a new instance of this graph. + * + * @return A new instance of the graph + */ + protected abstract Graph getNewInstance(); + + /** + * Check if the vertex passed is contained in the graph or not.
+ * The vertex V1 is contained in the graph G, if and only if:
+ * exist V2 in G such that V2 == V1 + * + * @param vertex the vertex to check + * @return true if the vertex is contained, false otherwise + */ + public abstract boolean contains(V vertex) throws NullPointerException; + + /** + * Get an instance of the vertex linked with this graph.
+ * For more info see {@link Vertex} + * + * @param vertex the vertex + * @return a vertex + * @throws IllegalArgumentException if the vertex is not contained in the graph + */ + public final Vertex get(V vertex) throws IllegalArgumentException { + checkVert(vertex); + return new Vertex<>(this, vertex); + } + + /** + * Add the vertex to the graph. If it's already in the graph it will be replaced and all its edges will be reset.
+ * Of course the vertex added will have no marks nor edge to any other vertex nor form any other vertex. + * + * @param vertex the vertex to add + * @throws NullPointerException if the vertex is null + */ + public abstract void add(V vertex) throws NullPointerException; + + /** + * Add the specified vertex to the graph only if the graph doesn't contains it.
+ * The graph contains a vertex only if the method {@link #contains(Object)} returns true. + * + * @param vertex the vertex to add + * @return true if it adds a vertex, false if it was already in the graph + * @throws NullPointerException if the vertex is null + */ + public final boolean addIfAbsent(V vertex) throws NullPointerException { + if (contains(vertex)) + return false; + add(vertex); + return true; + } + + /** + * Add all the vertices contained in the collection to the graph.
+ * If a vertex is contained in the collection and in the graph is ignored and it will not be replaced.
+ * Null vertices will be ignored and they will not be added to the graph. + * + * @param vertices a collection of the vertices to add + * @throws NullPointerException if the set is null + */ + public void addAll(Collection vertices) throws NullPointerException { + check(vertices); + for (V vertex : vertices) + addIfAbsent(vertex); + } + + /** + * Remove the selected vertex from the graph.
+ * After this method's call the vertex will be no longer present in the graph, and nether all his edges and marks. + * + * @param vertex the vertex to remove + * @throws NullPointerException if the vertex is null + * @throws IllegalArgumentException if the vertex is not contained + */ + public abstract 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. + */ + public void removeAll() { + unMarkAll(); + for (V vertex : vertices()) + remove(vertex); + } + + /** + * Check if the edge between the two vertex passed is contained in the graph or not.
+ * 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 + */ + public boolean containsEdge(V vertex1, V vertex2) throws NullPointerException { + try { + return getWeight(vertex1, vertex2) != NO_EDGE; + } catch (IllegalArgumentException ignore) { + return false; + } + } + + /** + * Get the weight of the selected edge.
+ * If the edge doesn't exist, then 0 is returned + * + * @param vertex1 a vertex of the graph + * @param vertex2 a vertex of the graph + * @return the weight previously set, or 0 if the edge doesn't exist + * @throws NullPointerException if one of the parameters is null + * @throws IllegalArgumentException if one of the vertex is not contained in the graph + */ + public abstract int getWeight(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException; + + /** + * Add an edge between the two vertex.
+ * This method will overwrite any existing edge between the two vertex.
+ * If there was a previous edge then it is returned + * + * @param edge the edge to add + * @return 0 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 + */ + public final int addEdge(Edge edge) throws NullPointerException, IllegalArgumentException { + return addEdge(edge.getSource(), edge.getDestination(), edge.getWeight()); + } + + /** + * Add an edge between the two vertex.
+ * This method will overwrite any existing edge between the two vertices.
+ * By default using this method will set the edge to the value 1. + * + * @param vertex1 a vertex of the graph + * @param vertex2 a vertex of the graph + * @throws NullPointerException if one of the parameter is null + * @throws IllegalArgumentException if one of the vertex is not contained in the graph + */ + public final void addEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException { + addEdge(vertex1, vertex2, 1); + } + + /** + * Add an edge between the two vertex.
+ * This method will overwrite any existing edge between the two vertex.
+ * If there was a previous edge then it's value is returned.
+ * If the weight passed is equals to 0 or {@link Graph#NO_EDGE}, then + * the edge will be removed. + * + * @param vertex1 a vertex of the graph + * @param vertex2 a vertex of the graph + * @param weight the weight of the edge + * @return 0 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 + */ + public abstract int addEdge(V vertex1, V vertex2, int weight) throws NullPointerException, IllegalArgumentException; + + /** + * This particular function add an edge to the graph.
+ * If one of the two, or both vertices of the edge aren't contained in the graph, then the vertices will be added.
+ * This method will overwrite any existing edge between the two vertices.
+ * If there was a previous edge then it is returned + * + * @param edge the edge to add + * @return 0 or the previous weight of the edge if there was already one + * @throws NullPointerException if one of the parameter is null + */ + public final int addEdgeAndVertices(Edge edge) throws NullPointerException, IllegalArgumentException { + return addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight()); + } + + /** + * This particular function add an edge to the graph.
+ * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
+ * This method will overwrite any existing edge between the two vertices.
+ * By default using this method will set the edge to the value 1. + * + * @param vertex1 a vertex of the graph + * @param vertex2 a vertex of the graph + * @throws NullPointerException if one of the parameter is null + */ + public final int addEdgeAndVertices(V vertex1, V vertex2) throws NullPointerException { + return addEdgeAndVertices(vertex1, vertex2, 1); + } + + /** + * This particular function add an edge to the graph.
+ * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
+ * This method will overwrite any existing edge between the two vertices.
+ * If there was a previous edge then it is returned + * + * @param vertex1 a vertex of the graph + * @param vertex2 a vertex of the graph + * @param weight the weight of the edge + * @return 0 or the previous weight of the edge if there was already one + * @throws NullPointerException if one of the parameter is null + */ + public final int addEdgeAndVertices(V vertex1, V vertex2, int weight) throws NullPointerException { + addIfAbsent(vertex1); + addIfAbsent(vertex2); + return addEdge(vertex1, vertex2, weight); + } + + /** + * Add all the edges of the collection to the graph.
+ * If one of the two, or both vertices aren't contained in the graph, then the vertices will be added.
+ * Any null edges will be ignored.
+ * This method will overwrite any existing edge between the two vertices. + * + * @param edges the edges to add + * @throws NullPointerException if the set is null + */ + public void addAllEdges(Collection> edges) throws NullPointerException { + edges.forEach(edge -> addEdgeAndVertices(edge.getSource(), edge.getDestination(), edge.getWeight())); + } + + /** + * Remove the edge between the two vertex by setting it's value to 0.
+ * If the edge doesn't exist, then this call does nothing.
+ * This method is equivalent to calling {@link Graph#addEdge(Object, Object, int)} )} + * with the weight set to {@link Graph#NO_EDGE} + * + * @param vertex1 a vertex of the graph + * @param vertex2 a vertex of the graph + * @throws NullPointerException if one of the parameters is null + * @throws IllegalArgumentException if one of the vertex is not contained in the graph + */ + public void removeEdge(V vertex1, V vertex2) throws NullPointerException, IllegalArgumentException { + addEdge(vertex1, vertex2, NO_EDGE); + } + + /** + * Remove all edges form a particular vertex of the graph.
+ * After this method's call the selected vertex will have 0 edges.
+ * It will be no longer possible to reach this vertex from any other vertex, and vice versa. + * + * @param vertex a vertex of the graph + * @throws NullPointerException if the vertex is null + * @throws IllegalArgumentException if one of the vertex is not contained in the graph + */ + public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException { + unMark(vertex); + remove(vertex); + add(vertex); + } + + /** + * Remove all the edges of the graph.
+ * After this method's call the graph will have only vertices, and no edge. + */ + public void removeAllEdge() { + Set vertices = vertices(); + removeAll(); + addAll(vertices); + } + + /** + * Retrieve all the edges of a particular vertex.
+ * + * @param vertex a vertex of the graph + * @return a set of edges + * @throws NullPointerException if the vertex is null + * @throws IllegalArgumentException if the vertex is not contained in the graph + */ + public abstract Set> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException; + + /** + * Get all the vertices that are children of the vertex passed as parameter.
+ * The vertices V(0-N) that are 'children' of a vertex V1, are all the vertices that have an edge + * where V1 is the source of that edge. + * + * @param vertex the source vertex + * @return a set of vertices + * @throws NullPointerException if the vertex is null + * @throws IllegalArgumentException if the vertex is not contained in the graph + */ + public abstract Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException; + + /** + * Get all the vertices that have the vertex passed as their child.
+ * Basically is the opposite of {@link #getChildren(Object)} + * + * @param vertex a vertex of the graph + * @return a set 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 + */ + public abstract Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException; + + /** + * Get all the marks of this graph.
+ * Specifically it will return a Set of marks where every mark
+ * as associated at least one vertex of the graph.
+ * If the graph doesn't have vertex marked then it is returned an empty Set. + * + * @return a set of marks + */ + public final Set marks() { + Set ret = getDefaultSet(); + markers.forEach((v, set) -> ret.addAll(set)); + return ret; + } + + /** + * Add to the specified vertex the mark passed.
+ * A vertex can have multiple marker.
+ * The null marker cannot be used. + * + * @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 + */ + public final void mark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException { + check(mark); + checkVert(vertex); + Set marks = markers.computeIfAbsent(vertex, v -> getDefaultSet()); + marks.add(mark); + } + + /** + * Remove the selected mark from the vertex.
+ * + * @param vertex the vertex where remove the mark + * @param mark the mark to remove + * @throws NullPointerException if a param is null + * @throws IllegalArgumentException if the vertex is not contained in the graph + */ + public final void unMark(V vertex, Object mark) throws NullPointerException, IllegalArgumentException { + check(mark); + checkVert(vertex); + markers.computeIfPresent(vertex, (v, set) -> { + set.remove(mark); + if (set.size() > 0) + return set; + return null; + }); + } + + /** + * Unmark the vertex selected.
+ * After this call the vertex will not have any marked object to himself. + * + * @param vertex the vertex + * @throws NullPointerException if the vertex is null + * @throws IllegalArgumentException if the vertex is not contained in the graph + */ + public final void unMark(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + try { + markers.remove(vertex).clear(); + } catch (Exception ignore) { + } + } + + /** + * Get all the vertices that are marked with the specific mark passed.
+ * If there aren't vertices with that mark then it is returned an empty set.
+ * + * @param mark the mark + * @return a set of all the vertices that are marked with that specific mark + * @throws NullPointerException if the mark is null + */ + public final Set getMarkedWith(Object mark) throws NullPointerException { + check(mark); + Set vertices = getDefaultSet(); + markers.forEach((v, set) -> { + if (set.contains(mark)) + vertices.add(v); + }); + return vertices; + } + + /** + * Get all the marker of this vertex.
+ * If the vertex doesn't have any mark, then it will return an empty set.
+ * Note: modifying the returned Set affect the marker of the vertex. + * + * @param vertex the vertex + * @return a set of all the mark to the vertex or an empty Set if none + * @throws NullPointerException if the vertex is null + * @throws IllegalArgumentException if the vertex is not contained in the graph + */ + public final Set getMarks(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + return markers.getOrDefault(vertex, getDefaultSet()); + } + + /** + * Remove the selected mark from all the vertices + * + * @param mark the mark to remove + * @throws NullPointerException if the mark is null + */ + public final void unMarkAll(Object mark) throws NullPointerException { + check(mark); + Set toRemove = getDefaultSet(); + markers.forEach((v, set) -> { + set.remove(mark); + if (set.size() == 0) + toRemove.add(v); + }); + markers.keySet().removeAll(toRemove); + } + + /** + * Remove all the marker to all the vertex.
+ * After this call the {@link #getMarks(Object)} applied to any vertex will return an empty set + */ + public final void unMarkAll() { + markers.values().forEach(Set::clear); + markers.clear(); + } + + /** + * Get all the vertices in the graph.
+ * If the graph doesn't contains vertices, it'll return an empty Set.
+ * + * @return a set that include all the vertices + */ + public Set vertices() { + Set vertices = getDefaultSet(); + forEach(vertices::add); + return vertices; + } + + /** + * Get all the edges in the graph.
+ * If the graph doesn't contains edges, it'll return an empty Set.
+ * + * @return a Set that include all the edges + */ + public abstract Set> edges(); + + /** + * Tells the degree of a vertex.
+ * The degree of a vertex is the quantity of edges that have.
+ * Basically, it'll count how many edge it have. + * + * @param vertex a vertex of the graph + * @return the degree of the vertex + * @throws NullPointerException if the vertex is null + * @throws IllegalArgumentException if the vertex is not contained in the graph + */ + public abstract int degree(V vertex) throws NullPointerException, IllegalArgumentException; + + /** + * Tells how many vertices are in the graph. + * + * @return the number of vertices + */ + public abstract int size(); + + /** + * Tells how many edges are in the graph. + * + * @return the number of edges + */ + public abstract int numberOfEdges(); + + /** + * Visit the graph accordingly to the strategy that is passed.
+ * Some strategy can accept a source vertex null, because they visit all the graph anyway. + * + * @param source the starting vertex for the visit + * @param strategy the algorithm for visiting the graph + * @param visit the function to apply at each vertex visited + * @return an info of the visit if provided by the strategy + * @throws NullPointerException if one of the parameter is null (except the consumer) + * @throws UnsupportedOperationException in the case the visit cannot be applied to the graph + */ + public final VisitInfo visit(V source, VisitStrategy strategy, Consumer visit) throws NullPointerException, UnsupportedOperationException { + return strategy.visit(this, source, visit); + } + + /** + * Get a sub-graph of the current one based on the maximum depth that is given.
+ * If the depth is 1 then only the source and it's children will be in the sub-graph.
+ * If the depth is 2 then only the source, it's children and it's children of it's children will be in the sub-graph.
+ * And so on.
+ * Of course the sub-graph will contain the edges that link the vertices, but only the one selected. + * + * @param source the source vertex + * @param depth the maximum depth (must be a positive number, if <=0 a graph containing only the source is returned) + * @return a sub-graph of the original + * @throws NullPointerException if the vertex is null + * @throws IllegalArgumentException if the vertex is not contained + */ + public final Graph subGraph(V source, int depth) throws NullPointerException, IllegalArgumentException { + checkVert(source); + Graph sub = getNewInstance(); + Set vertices = getDefaultSet(); + new BFS().setMaxDepth(Math.max(depth, 0)).visit(this, source, vertices::add); + + sub.addAll(vertices); + for (V src : vertices) + for (V dest : getChildren(src)) + if (sub.contains(dest)) + sub.addEdge(src, dest, this.getWeight(src, dest)); + return sub; + } + + /** + * Get a sub-graph of the current one with only the vertex marked with the selected markers. (OR set operation)
+ * Each vertex will have all his markers and his edges, but only the ones with the destination marked with the same marker.
+ * If the marker is not specified or is null then the returning graph will have all the vertices that are not marked by any marker.
+ * If in the list of markers there is a null marker it will be skipped.
+ * If the graph doesn't contain any vertex with any marker passed then an empty graph is returned. + * + * @param marker one or more markers + * @return a sub-graph of the current graph + */ + public final Graph subGraph(Object... marker) { + final Graph sub = getNewInstance(); + final Set allVertices = getDefaultSet(); + final Set allMarkers = getDefaultSet(); + + if (marker != null && marker.length > 0) + for(int i=0; i 0) + markers.forEach((v, set) -> { + if (!Collections.disjoint(allMarkers, set)) + allVertices.add(v); + }); + else { + Set toAdd = vertices(); + toAdd.removeAll(markers.keySet()); + allVertices.addAll(toAdd); + } + + sub.addAll(allVertices); + for (V src : sub.vertices()) { + for (Object mark : getMarks(src)) + sub.mark(src, mark); + for (V dest : getChildren(src)) + if (sub.contains(dest)) + sub.addEdge(src, dest, getWeight(src, dest)); + } + return sub; + } + + /** + * Get the minimum path from the source vertex to the destination vertex.
+ * If the source vertex can't reach the destination, then an exception is thrown. + * + * @param source the vertex where to start + * @param destination the destination chosen + * @return an ordered list of edges from source to destination that represent the minimum path between the two vertices + * @throws NullPointerException if one of the parameter is null (except the consumer) + * @throws IllegalArgumentException if the vertex is not in the graph + * @throws UnsupportedOperationException if from the source it's not possible to reach the destination + */ + public final List> distance(V source, V destination) throws NullPointerException, IllegalArgumentException, UnsupportedOperationException { + checkVert(source, destination); + List> path = distance(source).get(destination); + if (path == null) + throw new UnsupportedOperationException(NOT_CONNECTED); + return path; + } + + /** + * Get the minimum path from the source vertex to all the possible reachable vertices. + * + * @param source the vertex where to start + * @return a map containing all the possible reachable vertices from the source and the minimum path to reach them + * @throws NullPointerException if one of the parameter is null (except the consumer) + * @throws IllegalArgumentException if the vertex is not in the graph + */ + public final Map>> distance(V source) throws NullPointerException, IllegalArgumentException { + checkVert(source); + Dijkstra dijkstra = new Dijkstra<>(); + dijkstra.visit(this, source, null); + return dijkstra.getLastDistance(); + } + + /** + * Check if the object passed is not null. + * If it's null then throws eventual exception + * + * @param objects the objects to test + */ + protected final void check(Object... objects) { + for (Object obj : objects) + if (obj == null) + throw new NullPointerException(PARAM_NULL); + } + + /** + * Check if the vertex passed is not null and if exist in the graph. + * If not then throws eventual exception + * + * @param vertices the vertices to test + */ + @SafeVarargs + protected final void checkVert(V... vertices) { + check((Object[]) vertices); + for (V vert : vertices) + try { + if (!contains(vert)) + throw new IllegalArgumentException(VERTEX_NOT_CONTAINED); + } catch (ClassCastException ignore) { + } + } +} diff --git a/src/berack96/lib/graph/GraphDirected.java b/src/main/java/berack96/lib/graph/GraphDirected.java similarity index 86% rename from src/berack96/lib/graph/GraphDirected.java rename to src/main/java/berack96/lib/graph/GraphDirected.java index bd2abe5..9bbce28 100644 --- a/src/berack96/lib/graph/GraphDirected.java +++ b/src/main/java/berack96/lib/graph/GraphDirected.java @@ -4,10 +4,8 @@ import berack96.lib.graph.visit.VisitSCC; import berack96.lib.graph.visit.VisitTopological; import berack96.lib.graph.visit.impl.Tarjan; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; import java.util.List; +import java.util.Set; /** * This is a more specific interface for an implementation of a Undirected Graph.
@@ -70,17 +68,17 @@ public abstract class GraphDirected extends Graph { /** * Retrieve all the edges of a particular vertex.
* Note: the edges that are returned are the one that have this vertex as destination and another as source.
- * Note2: depending on the implementation, modifying the returned collection
+ * Note2: depending on the implementation, modifying the returned Set
* could affect the graph behavior and the changes could be reflected to the graph. * * @param vertex a vertex of the graph - * @return a collection of edges + * @return a Set of edges * @throws NullPointerException if the vertex is null * @throws IllegalArgumentException if the vertex is not contained in the graph */ - public Collection> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException { - Collection ancestors = getAncestors(vertex); - Collection> edgesIn = new HashSet<>(ancestors.size()); + public Set> getEdgesIn(V vertex) throws NullPointerException, IllegalArgumentException { + Set ancestors = getAncestors(vertex); + Set> edgesIn = getDefaultSet(); for (V ancestor : ancestors) { int weight = getWeight(ancestor, vertex); @@ -93,17 +91,17 @@ public abstract class GraphDirected extends Graph { /** * Retrieve all the edges that goes OUT of a particular vertex.
* Note: the edges that are returned are the one that have this vertex as source and another one as destination.
- * Note2: depending on the implementation, modifying the returned collection
+ * Note2: depending on the implementation, modifying the returned Set
* could affect the graph behavior and the changes could be reflected to the graph. * * @param vertex a vertex of the graph - * @return a collection of edges + * @return a Set of edges * @throws NullPointerException if the vertex is null * @throws IllegalArgumentException if the vertex is not contained in the graph */ - public Collection> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException { - Collection children = getChildren(vertex); - Collection> edgesOut = new HashSet<>(children.size()); + public Set> getEdgesOut(V vertex) throws NullPointerException, IllegalArgumentException { + Set children = getChildren(vertex); + Set> edgesOut = getDefaultSet(); for (V child : children) { int weight = getWeight(vertex, child); @@ -178,26 +176,26 @@ public abstract class GraphDirected extends Graph { * The strongly connected components or disconnected components of an arbitrary directed graph * form a partition into subgraphs that are themselves strongly connected. * - * @return a collection containing the strongly connected components + * @return a Set containing the strongly connected components */ - public final Collection> stronglyConnectedComponents() { + public final Set> stronglyConnectedComponents() { VisitSCC visit = new Tarjan<>(); visit.visit(this, null, null); return visit.getSCC(); } @Override - public Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException { - Collection> edges = getEdgesIn(vertex); + public Set> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException { + Set> edges = getEdgesIn(vertex); edges.addAll(getEdgesOut(vertex)); return edges; } @Override - public Collection> edges() { - Collection> collection = new ArrayList<>(); - forEach(v -> collection.addAll(getEdgesIn(v))); - return collection; + public Set> edges() { + Set> set = getDefaultSet(); + forEach(v -> set.addAll(getEdgesIn(v))); + return set; } @Override diff --git a/src/berack96/lib/graph/GraphUndirected.java b/src/main/java/berack96/lib/graph/GraphUndirected.java similarity index 70% rename from src/berack96/lib/graph/GraphUndirected.java rename to src/main/java/berack96/lib/graph/GraphUndirected.java index e07fb47..96bcb37 100644 --- a/src/berack96/lib/graph/GraphUndirected.java +++ b/src/main/java/berack96/lib/graph/GraphUndirected.java @@ -3,8 +3,7 @@ package berack96.lib.graph; import berack96.lib.graph.visit.VisitMST; import berack96.lib.graph.visit.impl.Prim; -import java.util.Collection; -import java.util.LinkedList; +import java.util.Set; /** * This is a more specific interface for an implementation of a Directed Graph.
@@ -19,27 +18,27 @@ public abstract class GraphUndirected extends Graph { /** * The connected components of an arbitrary undirected graph form a partition into subgraphs that are themselves connected. * - * @return a collection containing the strongly connected components + * @return a Set containing the strongly connected components */ - public Collection> connectedComponents() { + public Set> connectedComponents() { return null; } /** * minimum spanning forest or minimum spamming tree of the graph * - * @return A collection of edges representing the M.S.F. + * @return A Set of edges representing the M.S.F. */ - public Collection> minimumSpanningForest() { + public Set> minimumSpanningForest() { VisitMST visit = new Prim<>(); visit.visit(this, iterator().next(), null); return visit.getMST(); } @Override - public Collection> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException { + public Set> edgesOf(V vertex) throws NullPointerException, IllegalArgumentException { checkVert(vertex); - Collection> edges = new LinkedList<>(); + Set> edges = getDefaultSet(); getChildren(vertex).forEach(v -> edges.add(new Edge<>(vertex, v, getWeight(vertex, v)))); return edges; } diff --git a/src/main/java/berack96/lib/graph/ObjectsComparator.java b/src/main/java/berack96/lib/graph/ObjectsComparator.java new file mode 100644 index 0000000..e3668dd --- /dev/null +++ b/src/main/java/berack96/lib/graph/ObjectsComparator.java @@ -0,0 +1,18 @@ +package berack96.lib.graph; +import java.util.Comparator; + +/** + * Compare two arbitrary objects.
+ * It uses the method hashCode that every object has to compare two objects.
+ * This is a simple use + */ +public class ObjectsComparator implements Comparator { + static public final ObjectsComparator instance = new ObjectsComparator(); + + private ObjectsComparator(){}; + + @Override + public int compare(Object o1, Object o2) { + return o1.hashCode() - o2.hashCode(); + } +} diff --git a/src/berack96/lib/graph/Vertex.java b/src/main/java/berack96/lib/graph/Vertex.java similarity index 100% rename from src/berack96/lib/graph/Vertex.java rename to src/main/java/berack96/lib/graph/Vertex.java diff --git a/src/berack96/lib/graph/impl/ListGraph.java b/src/main/java/berack96/lib/graph/impl/ListGraph.java similarity index 86% rename from src/berack96/lib/graph/impl/ListGraph.java rename to src/main/java/berack96/lib/graph/impl/ListGraph.java index fb29b81..88acea1 100644 --- a/src/berack96/lib/graph/impl/ListGraph.java +++ b/src/main/java/berack96/lib/graph/impl/ListGraph.java @@ -1,160 +1,161 @@ -package berack96.lib.graph.impl; - -import berack96.lib.graph.Graph; -import berack96.lib.graph.GraphDirected; - -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * An implementation of the graph using an adjacent list for representing the edges - * - * @param the vertex - * @author Berack96 - */ -public class ListGraph extends GraphDirected { - - final private Map> adj = new Hashtable<>(); - - @Override - public Iterator iterator() { - return adj.keySet().iterator(); - } - - @Override - protected Graph getNewInstance() { - return new ListGraph<>(); - } - - @Override - public void add(V vertex) { - check(vertex); - if (adj.containsKey(vertex)) - removeAllEdge(vertex); - else - adj.put(vertex, new LinkedList<>()); - } - - @Override - public boolean contains(V vertex) { - check(vertex); - return adj.containsKey(vertex); - } - - @Override - public void remove(V vertex) { - checkVert(vertex); - adj.remove(vertex); - adj.forEach((v, list) -> list.remove(getAdj(list, vertex))); - } - - @Override - public int addEdge(V vertex1, V vertex2, int weight) { - checkVert(vertex1, vertex2); - - List list = adj.get(vertex1); - Adj a = getAdj(list, vertex2); - int old = a == null ? NO_EDGE : a.weight; - - if (weight == NO_EDGE) - list.remove(a); - else if (old == NO_EDGE) - list.add(new Adj(vertex2, weight)); - else - a.weight = weight; - return old; - } - - @Override - public int getWeight(V vertex1, V vertex2) { - checkVert(vertex1, vertex2); - Adj a = getAdj(adj.get(vertex1), vertex2); - return a == null ? NO_EDGE : a.weight; - } - - @Override - public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - Collection children = new HashSet<>(); - for (Adj adj : adj.get(vertex)) - children.add(adj.vertex); - return children; - } - - @Override - public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - Collection ancestors = new HashSet<>(); - adj.forEach((v, list) -> { - if (getAdj(list, vertex) != null) - ancestors.add(v); - }); - - return ancestors; - } - - - /** - * From here on there are some optimization for the methods of the generic DirectedGraph - **/ - - @Override - public int size() { - return adj.size(); - } - - @Override - public int numberOfEdges() { - AtomicInteger size = new AtomicInteger(0); - adj.values().forEach(list -> size.addAndGet(list.size())); - return size.get(); - } - - @Override - public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - AtomicInteger degree = new AtomicInteger(0); - adj.values().forEach(list -> degree.addAndGet(getAdj(list, vertex) != null ? 1 : 0)); - return degree.get(); - } - - @Override - public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - return adj.get(vertex).size(); - } - - @Override - public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - adj.get(vertex).clear(); - adj.forEach((v, list) -> list.remove(getAdj(list, vertex))); - } - - @Override - public void removeAllEdge() { - adj.forEach((v, list) -> list.clear()); - } - - @Override - public void removeAll() { - adj.clear(); - } - - private Adj getAdj(List list, V vertex) { - for (Adj adj : list) - if (Objects.equals(adj.vertex, vertex)) - return adj; - return null; - } - - private class Adj { - private final V vertex; - private int weight; - - private Adj(V vertex, int weight) { - this.vertex = vertex; - this.weight = weight; - } - } -} +package berack96.lib.graph.impl; + +import berack96.lib.graph.Graph; +import berack96.lib.graph.GraphDirected; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * An implementation of the graph using an adjacent list for representing the edges + * + * @param the vertex + * @author Berack96 + */ +public class ListGraph extends GraphDirected { + + // in case of thread safety use -> Collections.synchronizedSortedMap(TreeMap) + final private Map> adj = getDefaultMap(); + + @Override + public Iterator iterator() { + return adj.keySet().iterator(); + } + + @Override + protected Graph getNewInstance() { + return new ListGraph<>(); + } + + @Override + public void add(V vertex) { + check(vertex); + if (adj.containsKey(vertex)) + removeAllEdge(vertex); + else + adj.put(vertex, new LinkedList<>()); + } + + @Override + public boolean contains(V vertex) { + check(vertex); + return adj.containsKey(vertex); + } + + @Override + public void remove(V vertex) { + checkVert(vertex); + adj.remove(vertex); + adj.forEach((v, list) -> list.remove(getAdj(list, vertex))); + } + + @Override + public int addEdge(V vertex1, V vertex2, int weight) { + checkVert(vertex1, vertex2); + + List list = adj.get(vertex1); + Adj a = getAdj(list, vertex2); + int old = a == null ? NO_EDGE : a.weight; + + if (weight == NO_EDGE) + list.remove(a); + else if (old == NO_EDGE) + list.add(new Adj(vertex2, weight)); + else + a.weight = weight; + return old; + } + + @Override + public int getWeight(V vertex1, V vertex2) { + checkVert(vertex1, vertex2); + Adj a = getAdj(adj.get(vertex1), vertex2); + return a == null ? NO_EDGE : a.weight; + } + + @Override + public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + Set children = getDefaultSet(); + for (Adj adj : adj.get(vertex)) + children.add(adj.vertex); + return children; + } + + @Override + public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + Set ancestors = getDefaultSet(); + adj.forEach((v, list) -> { + if (getAdj(list, vertex) != null) + ancestors.add(v); + }); + + return ancestors; + } + + + /** + * From here on there are some optimization for the methods of the generic DirectedGraph + **/ + + @Override + public int size() { + return adj.size(); + } + + @Override + public int numberOfEdges() { + AtomicInteger size = new AtomicInteger(0); + adj.values().forEach(list -> size.addAndGet(list.size())); + return size.get(); + } + + @Override + public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + AtomicInteger degree = new AtomicInteger(0); + adj.values().forEach(list -> degree.addAndGet(getAdj(list, vertex) != null ? 1 : 0)); + return degree.get(); + } + + @Override + public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + return adj.get(vertex).size(); + } + + @Override + public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + adj.get(vertex).clear(); + adj.forEach((v, list) -> list.remove(getAdj(list, vertex))); + } + + @Override + public void removeAllEdge() { + adj.forEach((v, list) -> list.clear()); + } + + @Override + public void removeAll() { + adj.clear(); + } + + private Adj getAdj(List list, V vertex) { + for (Adj adj : list) + if (Objects.equals(adj.vertex, vertex)) + return adj; + return null; + } + + private class Adj { + private final V vertex; + private int weight; + + private Adj(V vertex, int weight) { + this.vertex = vertex; + this.weight = weight; + } + } +} diff --git a/src/berack96/lib/graph/impl/MapGraph.java b/src/main/java/berack96/lib/graph/impl/MapGraph.java similarity index 79% rename from src/berack96/lib/graph/impl/MapGraph.java rename to src/main/java/berack96/lib/graph/impl/MapGraph.java index a477fa2..600de5c 100644 --- a/src/berack96/lib/graph/impl/MapGraph.java +++ b/src/main/java/berack96/lib/graph/impl/MapGraph.java @@ -1,115 +1,116 @@ -package berack96.lib.graph.impl; - -import berack96.lib.graph.Graph; -import berack96.lib.graph.GraphDirected; - -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Graph that uses HashMap for vertices and edges
- * More specifically it utilizes a Map containing all the vertices mapped to all their edges
- * Technically this version of the graph combine the fast adding/removing of the edges of the Matrix implementation, - * with the low memory and fast adding/removing of vertices of the Linked List implementation.
- * This happen if the HashMap is not reallocated. So in the end each operation of adding or removing has O(n) - * - * @param the vertices - * @author Berack96 - */ -public class MapGraph extends GraphDirected { - - /** - * Map that contains the edges from a vertex to another
- * The first vertex is the vertex where start the edge, the second one is where the edge goes
- * If an edge exist, then it's weight is returned - */ - private final Map> edges = new HashMap<>(); - - @Override - public Iterator iterator() { - return edges.keySet().iterator(); - } - - - @Override - protected Graph getNewInstance() { - return new MapGraph<>(); - } - - @Override - public void add(V vertex) { - check(vertex); - edges.computeIfAbsent(vertex, v -> new HashMap<>()); - edges.forEach((v, adj) -> adj.remove(vertex)); - edges.get(vertex).clear(); - } - - @Override - public boolean contains(V vertex) { - check(vertex); - return edges.containsKey(vertex); - } - - @Override - public void remove(V vertex) { - checkVert(vertex); - edges.remove(vertex); - edges.forEach((v, map) -> map.remove(vertex)); - } - - @Override - public int addEdge(V vertex1, V vertex2, int weight) { - checkVert(vertex1, vertex2); - Map edge = edges.get(vertex1); - Integer old = edge.get(vertex2); - old = old == null ? NO_EDGE : old; - - if (weight == NO_EDGE) - edge.remove(vertex2); - else - edge.put(vertex2, weight); - return old; - } - - @Override - public int getWeight(V vertex1, V vertex2) { - checkVert(vertex1, vertex2); - Integer weight = edges.get(vertex1).get(vertex2); - return weight == null ? NO_EDGE : weight; - } - - @Override - public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - return new HashSet<>(edges.get(vertex).keySet()); - } - - @Override - public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - Collection ancestors = new HashSet<>(); - edges.forEach((v, adj) -> { - if (adj.containsKey(vertex)) - ancestors.add(v); - }); - return ancestors; - } - - @Override - public void removeAll() { - edges.clear(); - } - - @Override - public int size() { - return edges.size(); - } - - @Override - public int numberOfEdges() { - AtomicInteger sum = new AtomicInteger(0); - edges.forEach((v, map) -> sum.getAndAdd(map.size())); - - return sum.get(); - } -} +package berack96.lib.graph.impl; + +import berack96.lib.graph.Graph; +import berack96.lib.graph.GraphDirected; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Graph that uses TreeMap for vertices and edges
+ * More specifically it utilizes a Map containing all the vertices mapped to all their edges
+ * Technically this version of the graph combine the fast adding/removing of the edges of the Matrix implementation, + * with the low memory and fast adding/removing of vertices of the Linked List implementation.
+ * "Fast" in this case means O(log(n)) since it is a tree, so not tecnically as fast as O(1), + * but better than O(n).
+ * + * @param the vertices + * @author Berack96 + */ +public class MapGraph extends GraphDirected { + + /** + * Map that contains the edges from a vertex to another
+ * The first vertex is the vertex where start the edge, the second one is where the edge goes
+ * If an edge exist, then it's weight is returned + */ + private final Map> edges = getDefaultMap(); + + @Override + public Iterator iterator() { + return edges.keySet().iterator(); + } + + + @Override + protected Graph getNewInstance() { + return new MapGraph<>(); + } + + @Override + public void add(V vertex) { + check(vertex); + edges.computeIfAbsent(vertex, v -> new TreeMap<>()); + edges.forEach((v, adj) -> adj.remove(vertex)); + edges.get(vertex).clear(); + } + + @Override + public boolean contains(V vertex) { + check(vertex); + return edges.containsKey(vertex); + } + + @Override + public void remove(V vertex) { + checkVert(vertex); + edges.remove(vertex); + edges.forEach((v, map) -> map.remove(vertex)); + } + + @Override + public int addEdge(V vertex1, V vertex2, int weight) { + checkVert(vertex1, vertex2); + Map edge = edges.get(vertex1); + Integer old = edge.get(vertex2); + old = old == null ? NO_EDGE : old; + + if (weight == NO_EDGE) + edge.remove(vertex2); + else + edge.put(vertex2, weight); + return old; + } + + @Override + public int getWeight(V vertex1, V vertex2) { + checkVert(vertex1, vertex2); + Integer weight = edges.get(vertex1).get(vertex2); + return weight == null ? NO_EDGE : weight; + } + + @Override + public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + return new HashSet<>(edges.get(vertex).keySet()); + } + + @Override + public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + Set ancestors = getDefaultSet(); + edges.forEach((v, adj) -> { + if (adj.containsKey(vertex)) + ancestors.add(v); + }); + return ancestors; + } + + @Override + public void removeAll() { + edges.clear(); + } + + @Override + public int size() { + return edges.size(); + } + + @Override + public int numberOfEdges() { + AtomicInteger sum = new AtomicInteger(0); + edges.forEach((v, map) -> sum.getAndAdd(map.size())); + + return sum.get(); + } +} diff --git a/src/berack96/lib/graph/impl/MatrixGraph.java b/src/main/java/berack96/lib/graph/impl/MatrixGraph.java similarity index 87% rename from src/berack96/lib/graph/impl/MatrixGraph.java rename to src/main/java/berack96/lib/graph/impl/MatrixGraph.java index 6023d32..b0debc1 100644 --- a/src/berack96/lib/graph/impl/MatrixGraph.java +++ b/src/main/java/berack96/lib/graph/impl/MatrixGraph.java @@ -1,196 +1,196 @@ -package berack96.lib.graph.impl; - -import berack96.lib.graph.Graph; -import berack96.lib.graph.GraphDirected; - -import java.util.*; - -/** - * An implementation of the graph using a matrix for representing the edges - * - * @param the vertex - * @author Berack96 - */ -public class MatrixGraph extends GraphDirected { - - private final Map map = new HashMap<>(); - private int[][] matrix = new int[0][0]; - - @Override - public Iterator iterator() { - return map.keySet().iterator(); - } - - @Override - protected Graph getNewInstance() { - return new MatrixGraph<>(); - } - - @Override - public void add(V vertex) { - check(vertex); - if (map.containsKey(vertex)) - removeAllEdge(vertex); - else { - map.put(vertex, map.size()); - matrix = modifyMatrix(map.size()); - } - } - - @Override - public boolean contains(V vertex) { - check(vertex); - return map.containsKey(vertex); - } - - @Override - public void remove(V vertex) { - checkVert(vertex); - int x = map.remove(vertex); - int newSize = map.size(); - - int[][] newMatrix = new int[newSize][newSize]; - for (int i = 0; i < newSize; i++) - for (int j = 0; j < newSize; j++) { - int indexI = i + (i < x ? 0 : 1); - int indexJ = j + (j < x ? 0 : 1); - - newMatrix[i][j] = matrix[indexI][indexJ]; - } - - matrix = newMatrix; - map.replaceAll((vert, index) -> index > x ? index - 1 : index); - } - - @Override - public int addEdge(V vertex1, V vertex2, int weight) { - checkVert(vertex1, vertex2); - int i = map.get(vertex1); - int j = map.get(vertex2); - - int old = matrix[i][j]; - matrix[i][j] = weight; - return old; - } - - @Override - public int getWeight(V vertex1, V vertex2) { - checkVert(vertex1, vertex2); - return matrix[map.get(vertex1)][map.get(vertex2)]; - } - - @Override - public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - int x = map.get(vertex); - Collection children = new HashSet<>(); - Map invert = getInverted(); - - for (int i = 0; i < matrix.length; i++) - if (matrix[x][i] != NO_EDGE) - children.add(invert.get(i)); - return children; - } - - @Override - public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - int x = map.get(vertex); - Collection ancestors = new HashSet<>(); - Map invert = getInverted(); - - for (int i = 0; i < matrix.length; i++) - if (matrix[i][x] != NO_EDGE) - ancestors.add(invert.get(i)); - return ancestors; - } - - /** - * From here on there are some optimization for the methods of the generic DirectedGraph - **/ - - @Override - public int size() { - return map.size(); - } - - @Override - public int numberOfEdges() { - int sum = 0; - for (int[] adj : matrix) - for (int edge : adj) - if (edge != NO_EDGE) - sum++; - return sum; - } - - @Override - public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - int degree = 0, x = map.get(vertex); - for (int[] ints : matrix) degree += ints[x] == NO_EDGE ? 0 : 1; - return degree; - } - - @Override - public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - int degree = 0, x = map.get(vertex); - for (int ints : matrix[x]) degree += ints == NO_EDGE ? 0 : 1; - return degree; - } - - @Override - public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException { - checkVert(vertex); - int x = map.get(vertex); - Arrays.fill(matrix[x], NO_EDGE); - for (int[] ints : matrix) ints[x] = NO_EDGE; - } - - @Override - public void removeAllEdge() { - for (int[] ints : matrix) - Arrays.fill(ints, NO_EDGE); - } - - @Override - public void removeAll() { - map.clear(); - matrix = new int[0][0]; - } - - @Override - public void addAll(Collection vertices) throws NullPointerException { - check(vertices); - for (V vert : vertices) - if (vert != null) - map.compute(vert, (v, i) -> { - if (i == null) - return map.size(); - removeAllEdge(vert); - return i; - }); - matrix = modifyMatrix(map.size()); - } - - private int[][] modifyMatrix(int newSize) { - int oldSize = matrix.length; - if (newSize <= oldSize) - return matrix; - - int[][] newMatrix = new int[newSize][newSize]; - for (int[] ints : newMatrix) - Arrays.fill(ints, NO_EDGE); - for (int i = 0; i < oldSize; i++) - System.arraycopy(matrix[i], 0, newMatrix[i], 0, oldSize); - - return newMatrix; - } - - private Map getInverted() { - Map invert = new HashMap<>(map.size() + 1, 1); - map.forEach((v, i) -> invert.put(i, v)); - return invert; - } -} +package berack96.lib.graph.impl; + +import berack96.lib.graph.Graph; +import berack96.lib.graph.GraphDirected; + +import java.util.*; + +/** + * An implementation of the graph using a matrix for representing the edges + * + * @param the vertex + * @author Berack96 + */ +public class MatrixGraph extends GraphDirected { + + private final Map map = getDefaultMap(); + private int[][] matrix = new int[0][0]; + + @Override + public Iterator iterator() { + return map.keySet().iterator(); + } + + @Override + protected Graph getNewInstance() { + return new MatrixGraph<>(); + } + + @Override + public void add(V vertex) { + check(vertex); + if (map.containsKey(vertex)) + removeAllEdge(vertex); + else { + map.put(vertex, map.size()); + matrix = modifyMatrix(map.size()); + } + } + + @Override + public boolean contains(V vertex) { + check(vertex); + return map.containsKey(vertex); + } + + @Override + public void remove(V vertex) { + checkVert(vertex); + int x = map.remove(vertex); + int newSize = map.size(); + + int[][] newMatrix = new int[newSize][newSize]; + for (int i = 0; i < newSize; i++) + for (int j = 0; j < newSize; j++) { + int indexI = i + (i < x ? 0 : 1); + int indexJ = j + (j < x ? 0 : 1); + + newMatrix[i][j] = matrix[indexI][indexJ]; + } + + matrix = newMatrix; + map.replaceAll((vert, index) -> index > x ? index - 1 : index); + } + + @Override + public int addEdge(V vertex1, V vertex2, int weight) { + checkVert(vertex1, vertex2); + int i = map.get(vertex1); + int j = map.get(vertex2); + + int old = matrix[i][j]; + matrix[i][j] = weight; + return old; + } + + @Override + public int getWeight(V vertex1, V vertex2) { + checkVert(vertex1, vertex2); + return matrix[map.get(vertex1)][map.get(vertex2)]; + } + + @Override + public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + int x = map.get(vertex); + Set children = getDefaultSet(); + Map invert = getInverted(); + + for (int i = 0; i < matrix.length; i++) + if (matrix[x][i] != NO_EDGE) + children.add(invert.get(i)); + return children; + } + + @Override + public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + int x = map.get(vertex); + Set ancestors = getDefaultSet(); + Map invert = getInverted(); + + for (int i = 0; i < matrix.length; i++) + if (matrix[i][x] != NO_EDGE) + ancestors.add(invert.get(i)); + return ancestors; + } + + /** + * From here on there are some optimization for the methods of the generic DirectedGraph + **/ + + @Override + public int size() { + return map.size(); + } + + @Override + public int numberOfEdges() { + int sum = 0; + for (int[] adj : matrix) + for (int edge : adj) + if (edge != NO_EDGE) + sum++; + return sum; + } + + @Override + public int degreeIn(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + int degree = 0, x = map.get(vertex); + for (int[] ints : matrix) degree += ints[x] == NO_EDGE ? 0 : 1; + return degree; + } + + @Override + public int degreeOut(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + int degree = 0, x = map.get(vertex); + for (int ints : matrix[x]) degree += ints == NO_EDGE ? 0 : 1; + return degree; + } + + @Override + public void removeAllEdge(V vertex) throws NullPointerException, IllegalArgumentException { + checkVert(vertex); + int x = map.get(vertex); + Arrays.fill(matrix[x], NO_EDGE); + for (int[] ints : matrix) ints[x] = NO_EDGE; + } + + @Override + public void removeAllEdge() { + for (int[] ints : matrix) + Arrays.fill(ints, NO_EDGE); + } + + @Override + public void removeAll() { + map.clear(); + matrix = new int[0][0]; + } + + @Override + public void addAll(Collection vertices) throws NullPointerException { + check(vertices); + for (V vert : vertices) + if (vert != null) + map.compute(vert, (v, i) -> { + if (i == null) + return map.size(); + removeAllEdge(vert); + return i; + }); + matrix = modifyMatrix(map.size()); + } + + private int[][] modifyMatrix(int newSize) { + int oldSize = matrix.length; + if (newSize <= oldSize) + return matrix; + + int[][] newMatrix = new int[newSize][newSize]; + for (int[] ints : newMatrix) + Arrays.fill(ints, NO_EDGE); + for (int i = 0; i < oldSize; i++) + System.arraycopy(matrix[i], 0, newMatrix[i], 0, oldSize); + + return newMatrix; + } + + private Map getInverted() { + Map invert = getDefaultMap(); + map.forEach((v, i) -> invert.put(i, v)); + return invert; + } +} diff --git a/src/berack96/lib/graph/impl/MatrixUndGraph.java b/src/main/java/berack96/lib/graph/impl/MatrixUndGraph.java similarity index 83% rename from src/berack96/lib/graph/impl/MatrixUndGraph.java rename to src/main/java/berack96/lib/graph/impl/MatrixUndGraph.java index 327af48..459a871 100644 --- a/src/berack96/lib/graph/impl/MatrixUndGraph.java +++ b/src/main/java/berack96/lib/graph/impl/MatrixUndGraph.java @@ -8,7 +8,7 @@ import java.util.*; public class MatrixUndGraph extends GraphUndirected { - Map map = new HashMap<>(); + Map map = getDefaultMap(); private int[][] matrix = new int[0][0]; @Override @@ -73,33 +73,33 @@ public class MatrixUndGraph extends GraphUndirected { } @Override - public Collection getChildren(V vertex) throws NullPointerException, IllegalArgumentException { + public Set getChildren(V vertex) throws NullPointerException, IllegalArgumentException { checkVert(vertex); - Collection collection = new HashSet<>(); - Map inverted = getInverted(); + V[] inverted = getInverted(); + Set set = getDefaultSet(); int x = map.get(vertex); for (int i = 0; i < matrix.length; i++) if (i < x && matrix[x][i] != 0) - collection.add(inverted.get(i)); + set.add(inverted[i]); else if (i > x && matrix[i][x] != 0) - collection.add(inverted.get(i)); - return collection; + set.add(inverted[i]); + return set; } @Override - public Collection getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { + public Set getAncestors(V vertex) throws NullPointerException, IllegalArgumentException { return getChildren(vertex); } @Override - public Collection> edges() { - Map inverted = getInverted(); - Collection> edges = new LinkedList<>(); + public Set> edges() { + V[] inverted = getInverted(); + Set> edges = getDefaultSet(); for (int i = 0; i < matrix.length; i++) for (int j = 0; j < matrix[i].length; j++) if (matrix[i][j] != NO_EDGE) - edges.add(new Edge<>(inverted.get(i), inverted.get(j), matrix[i][j])); + edges.add(new Edge<>(inverted[i], inverted[j], matrix[i][j])); return edges; } @@ -168,9 +168,10 @@ public class MatrixUndGraph extends GraphUndirected { return newMatrix; } - private Map getInverted() { - Map invert = new HashMap<>(map.size() + 1, 1); - map.forEach((v, i) -> invert.put(i, v)); + @SuppressWarnings("unchecked") + private V[] getInverted() { + V[] invert = (V[]) new Object[map.size()]; + map.forEach((v, i) -> invert[i] = v); return invert; } } diff --git a/src/berack96/lib/graph/models/EdgeSaveStructure.java b/src/main/java/berack96/lib/graph/models/EdgeSaveStructure.java similarity index 95% rename from src/berack96/lib/graph/models/EdgeSaveStructure.java rename to src/main/java/berack96/lib/graph/models/EdgeSaveStructure.java index e8b161d..b775ab2 100644 --- a/src/berack96/lib/graph/models/EdgeSaveStructure.java +++ b/src/main/java/berack96/lib/graph/models/EdgeSaveStructure.java @@ -1,18 +1,18 @@ -package berack96.lib.graph.models; - -/** - * Support class used for saving a Graph in a file. - * - * @author Berack96 - */ -public class EdgeSaveStructure { - protected EdgeSaveStructure(String s, String d, int w) { - this.src = s; - this.dest = d; - this.weight = w; - } - - public String src; - public String dest; - public int weight; +package berack96.lib.graph.models; + +/** + * Support class used for saving a Graph in a file. + * + * @author Berack96 + */ +public class EdgeSaveStructure { + protected EdgeSaveStructure(String s, String d, int w) { + this.src = s; + this.dest = d; + this.weight = w; + } + + public String src; + public String dest; + public int weight; } \ No newline at end of file diff --git a/src/berack96/lib/graph/models/GraphSaveStructure.java b/src/main/java/berack96/lib/graph/models/GraphSaveStructure.java similarity index 92% rename from src/berack96/lib/graph/models/GraphSaveStructure.java rename to src/main/java/berack96/lib/graph/models/GraphSaveStructure.java index 4d2cc4f..526e9ef 100644 --- a/src/berack96/lib/graph/models/GraphSaveStructure.java +++ b/src/main/java/berack96/lib/graph/models/GraphSaveStructure.java @@ -1,105 +1,105 @@ -package berack96.lib.graph.models; - -import berack96.lib.graph.Edge; -import berack96.lib.graph.Graph; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.InstanceCreator; -import com.google.gson.JsonSyntaxException; -import com.google.gson.stream.JsonReader; - -import java.io.*; - -/** - * Support class used for saving a Graph in a file. - * - * @author Berack96 - */ -public class GraphSaveStructure { - final static public Gson gson = new Gson(); - public String[] vertices; - public EdgeSaveStructure[] edges; - //public MarkSaveStructure[] marks; - - /** - * Load the graph saved in this class in an instance of a graph passed. - * Before loading the graph, it is emptied. - * - * @param graph the graph where insert the data - * @param fileName the file path and name - * @param classV the class of the vertices - * @throws FileNotFoundException in the case the file is not found - * @throws NullPointerException in the case the graph is null - */ - public final void load(@SuppressWarnings("ConstantConditions") Graph graph, String fileName, Class classV) throws FileNotFoundException, NullPointerException { - //this way i use this class for the load - InstanceCreator> creator = type -> this; - Gson gson = new GsonBuilder().registerTypeAdapter(this.getClass(), creator).create(); - JsonReader reader = new JsonReader(new FileReader(fileName)); - gson.fromJson(reader, GraphSaveStructure.class); - loadGraph(graph, classV); - } - - /** - * This method can be used by sub-classes for saving other stuff from the graph - * - * @param graph the graph to load with - * @param classV the class used for the Vertex - * @throws NullPointerException if the graph is null - * @throws JsonSyntaxException if the file is malformed or corrupted - */ - protected void loadGraph(Graph graph, Class classV) throws NullPointerException, JsonSyntaxException { - graph.removeAll(); - for (String str : vertices) - graph.add(gson.fromJson(str, classV)); - - for (EdgeSaveStructure edge : edges) - graph.addEdge(gson.fromJson(edge.src, classV), gson.fromJson(edge.dest, classV), edge.weight); - } - - /** - * 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.
- * 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 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. - */ - public final void save(Graph graph, String file) throws IOException { - saveGraph(graph); - int slash = file.lastIndexOf("\\"); - if (slash == -1) - slash = file.lastIndexOf("/"); - if (slash != -1) { - String dir = file.substring(0, slash); - File fDir = new File(dir); - //noinspection ResultOfMethodCallIgnored - fDir.mkdirs(); - } - - FileWriter writer = new FileWriter(file); - gson.toJson(this, writer); - writer.close(); - } - - /** - * This method can be used by sub-classes for saving other stuff from the graph - * - * @param graph the graph to save - */ - protected void saveGraph(Graph graph) { - this.vertices = new String[graph.size()]; - int i = 0; - for (Object o : graph.vertices()) - this.vertices[i++] = gson.toJson(o); - - this.edges = new EdgeSaveStructure[graph.numberOfEdges()]; - i = 0; - for (Edge edge : graph.edges()) - this.edges[i++] = new EdgeSaveStructure(gson.toJson(edge.getSource()), gson.toJson(edge.getDestination()), edge.getWeight()); - } +package berack96.lib.graph.models; + +import berack96.lib.graph.Edge; +import berack96.lib.graph.Graph; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.InstanceCreator; +import com.google.gson.JsonSyntaxException; +import com.google.gson.stream.JsonReader; + +import java.io.*; + +/** + * Support class used for saving a Graph in a file. + * + * @author Berack96 + */ +public class GraphSaveStructure { + final static public Gson gson = new Gson(); + public String[] vertices; + public EdgeSaveStructure[] edges; + //public MarkSaveStructure[] marks; + + /** + * Load the graph saved in this class in an instance of a graph passed. + * Before loading the graph, it is emptied. + * + * @param graph the graph where insert the data + * @param fileName the file path and name + * @param classV the class of the vertices + * @throws FileNotFoundException in the case the file is not found + * @throws NullPointerException in the case the graph is null + */ + public final void load(Graph graph, String fileName, Class classV) throws FileNotFoundException, NullPointerException { + //this way i use this class for the load + InstanceCreator> creator = type -> this; + Gson gson = new GsonBuilder().registerTypeAdapter(this.getClass(), creator).create(); + JsonReader reader = new JsonReader(new FileReader(fileName)); + gson.fromJson(reader, GraphSaveStructure.class); + loadGraph(graph, classV); + } + + /** + * This method can be used by sub-classes for saving other stuff from the graph + * + * @param graph the graph to load with + * @param classV the class used for the Vertex + * @throws NullPointerException if the graph is null + * @throws JsonSyntaxException if the file is malformed or corrupted + */ + protected void loadGraph(Graph graph, Class classV) throws NullPointerException, JsonSyntaxException { + graph.removeAll(); + for (String str : vertices) + graph.add(gson.fromJson(str, classV)); + + for (EdgeSaveStructure edge : edges) + graph.addEdge(gson.fromJson(edge.src, classV), gson.fromJson(edge.dest, classV), edge.weight); + } + + /** + * 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.
+ * 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 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. + */ + public final void save(Graph graph, String file) throws IOException { + saveGraph(graph); + int slash = file.lastIndexOf("\\"); + if (slash == -1) + slash = file.lastIndexOf("/"); + if (slash != -1) { + String dir = file.substring(0, slash); + File fDir = new File(dir); + //noinspection ResultOfMethodCallIgnored + fDir.mkdirs(); + } + + FileWriter writer = new FileWriter(file); + gson.toJson(this, writer); + writer.close(); + } + + /** + * This method can be used by sub-classes for saving other stuff from the graph + * + * @param graph the graph to save + */ + protected void saveGraph(Graph graph) { + this.vertices = new String[graph.size()]; + int i = 0; + for (Object o : graph.vertices()) + this.vertices[i++] = gson.toJson(o); + + this.edges = new EdgeSaveStructure[graph.numberOfEdges()]; + i = 0; + for (Edge edge : graph.edges()) + this.edges[i++] = new EdgeSaveStructure(gson.toJson(edge.getSource()), gson.toJson(edge.getDestination()), edge.getWeight()); + } } \ No newline at end of file diff --git a/src/berack96/lib/graph/models/MarkSaveStructure.java b/src/main/java/berack96/lib/graph/models/MarkSaveStructure.java similarity index 94% rename from src/berack96/lib/graph/models/MarkSaveStructure.java rename to src/main/java/berack96/lib/graph/models/MarkSaveStructure.java index 3b3c125..3e4ba2b 100644 --- a/src/berack96/lib/graph/models/MarkSaveStructure.java +++ b/src/main/java/berack96/lib/graph/models/MarkSaveStructure.java @@ -1,17 +1,17 @@ -package berack96.lib.graph.models; - -/** - * Support class used for saving a Graph in a file. - * - * @author Berack96 - * - */ -public class MarkSaveStructure { - protected MarkSaveStructure(String v, Object m) { - this.vert = v; - this.mark = m; - } - - public String vert; - public Object mark; -} +package berack96.lib.graph.models; + +/** + * Support class used for saving a Graph in a file. + * + * @author Berack96 + * + */ +public class MarkSaveStructure { + protected MarkSaveStructure(String v, Object m) { + this.vert = v; + this.mark = m; + } + + public String vert; + public Object mark; +} diff --git a/src/berack96/lib/graph/struct/QuickFind.java b/src/main/java/berack96/lib/graph/struct/QuickFind.java similarity index 85% rename from src/berack96/lib/graph/struct/QuickFind.java rename to src/main/java/berack96/lib/graph/struct/QuickFind.java index 51cc7de..a2345b7 100644 --- a/src/berack96/lib/graph/struct/QuickFind.java +++ b/src/main/java/berack96/lib/graph/struct/QuickFind.java @@ -1,19 +1,20 @@ package berack96.lib.graph.struct; import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; +import berack96.lib.graph.Graph; + /** * Simple implementation of the {@link UnionFind} interface with priority to the find function. * * @param the elements to search and merge */ public class QuickFind implements UnionFind { - Map> struct = new HashMap<>(); + Map> struct = Graph.getDefaultMap(); @Override public int size() { @@ -22,7 +23,7 @@ public class QuickFind implements UnionFind { @Override public void makeSetAll(Collection elements) throws NullPointerException { - Map> temp = new HashMap<>(elements.size() + 1, 1); + Map> temp = Graph.getDefaultMap(); for (X elem : elements) temp.computeIfAbsent(elem, new AddElement()); struct.putAll(temp); @@ -65,10 +66,10 @@ public class QuickFind implements UnionFind { /** * Stupid class for implementing the adding of a new element */ - private class AddElement implements Function> { + private class AddElement implements Function> { @Override - public Collection apply(X x) { - Collection coll = new HashSet<>(); + public Set apply(X x) { + Set coll = Graph.getDefaultSet(); coll.add(x); return coll; } diff --git a/src/berack96/lib/graph/struct/UnionFind.java b/src/main/java/berack96/lib/graph/struct/UnionFind.java similarity index 100% rename from src/berack96/lib/graph/struct/UnionFind.java rename to src/main/java/berack96/lib/graph/struct/UnionFind.java diff --git a/src/berack96/lib/graph/view/GraphInfo.java b/src/main/java/berack96/lib/graph/view/GraphInfo.java similarity index 98% rename from src/berack96/lib/graph/view/GraphInfo.java rename to src/main/java/berack96/lib/graph/view/GraphInfo.java index 40ee762..2eec442 100644 --- a/src/berack96/lib/graph/view/GraphInfo.java +++ b/src/main/java/berack96/lib/graph/view/GraphInfo.java @@ -74,13 +74,13 @@ public class GraphInfo extends JPanel { components.add(vNumber); components.add(new JLabel("Edge Number: ")); components.add(eNumber); - components.add(new JLabel("Is Cyclic: ")); + //components.add(new JLabel("Is Cyclic: ")); //components.add(gCyclic); JPanel panelInfo = new JPanel(); panelInfo.setOpaque(false); panelInfo.setBorder(BorderFactory.createLineBorder(Color.RED)); - panelInfo.setLayout(new GridLayout(components.size()/2, 2, 2*2, 2*2)); + panelInfo.setLayout(new GridLayout(components.size()/2, 2)); components.forEach(panelInfo::add); components.clear(); @@ -123,7 +123,7 @@ public class GraphInfo extends JPanel { JPanel panelVertex = new JPanel(); panelVertex.setOpaque(false); - panelVertex.setLayout(new GridLayout(components.size()/2, 2, 2*2, 2*2)); + panelVertex.setLayout(new GridLayout(components.size()/2, 2)); components.forEach(panelVertex::add); components.clear(); @@ -163,7 +163,7 @@ public class GraphInfo extends JPanel { JPanel panelSave = new JPanel(); panelSave.setOpaque(false); panelSave.setBorder(BorderFactory.createLineBorder(Color.RED)); - panelSave.setLayout(new GridLayout(components.size()/2, 2, 2*2, 2*2)); + panelSave.setLayout(new GridLayout(components.size()/2, 2)); components.forEach(panelSave::add); components.clear(); @@ -177,7 +177,6 @@ public class GraphInfo extends JPanel { this.add(panelVertex); this.add(panelErrors); this.add(panelSave); - /*this.add(panelSave);*/ modVertex.doClick(); diff --git a/src/berack96/lib/graph/view/GraphListener.java b/src/main/java/berack96/lib/graph/view/GraphListener.java similarity index 100% rename from src/berack96/lib/graph/view/GraphListener.java rename to src/main/java/berack96/lib/graph/view/GraphListener.java diff --git a/src/berack96/lib/graph/view/GraphPanel.java b/src/main/java/berack96/lib/graph/view/GraphPanel.java similarity index 100% rename from src/berack96/lib/graph/view/GraphPanel.java rename to src/main/java/berack96/lib/graph/view/GraphPanel.java diff --git a/src/berack96/lib/graph/view/GraphPointsSave.java b/src/main/java/berack96/lib/graph/view/GraphPointsSave.java similarity index 100% rename from src/berack96/lib/graph/view/GraphPointsSave.java rename to src/main/java/berack96/lib/graph/view/GraphPointsSave.java diff --git a/src/berack96/lib/graph/view/GraphWindow.java b/src/main/java/berack96/lib/graph/view/GraphWindow.java similarity index 100% rename from src/berack96/lib/graph/view/GraphWindow.java rename to src/main/java/berack96/lib/graph/view/GraphWindow.java diff --git a/src/berack96/lib/graph/view/GraphicalView.java b/src/main/java/berack96/lib/graph/view/GraphicalView.java similarity index 100% rename from src/berack96/lib/graph/view/GraphicalView.java rename to src/main/java/berack96/lib/graph/view/GraphicalView.java diff --git a/src/berack96/lib/graph/view/Main.java b/src/main/java/berack96/lib/graph/view/Main.java similarity index 97% rename from src/berack96/lib/graph/view/Main.java rename to src/main/java/berack96/lib/graph/view/Main.java index 254462f..776f29f 100644 --- a/src/berack96/lib/graph/view/Main.java +++ b/src/main/java/berack96/lib/graph/view/Main.java @@ -1,23 +1,23 @@ -package berack96.lib.graph.view; - -import berack96.lib.graph.view.edge.EdgeIntListener; -import berack96.lib.graph.view.edge.EdgeView; -import berack96.lib.graph.view.vertex.VertexIntListener; -import berack96.lib.graph.view.vertex.VertexView; - -import java.awt.*; - -public class Main { - - public static void main(String[] args) { - GraphPanel panel = new GraphPanel<>(new VertexView<>(), new EdgeView<>(), Integer.class); - GraphWindow win = new GraphWindow<>(panel, new VertexIntListener(panel), new EdgeIntListener<>(panel)); - Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // full screen - dim.setSize(dim.width / 2, dim.height / 2); - win.setSize(dim); - win.setLocationRelativeTo(null); //centered - win.visitRefresh(500); - - win.setVisible(true); - } -} +package berack96.lib.graph.view; + +import berack96.lib.graph.view.edge.EdgeIntListener; +import berack96.lib.graph.view.edge.EdgeView; +import berack96.lib.graph.view.vertex.VertexIntListener; +import berack96.lib.graph.view.vertex.VertexView; + +import java.awt.*; + +public class Main { + + public static void main(String[] args) { + GraphPanel panel = new GraphPanel<>(new VertexView<>(), new EdgeView<>(), Integer.class); + GraphWindow win = new GraphWindow<>(panel, new VertexIntListener(panel), new EdgeIntListener<>(panel)); + Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // full screen + dim.setSize(dim.width / 2, dim.height / 2); + win.setSize(dim); + win.setLocationRelativeTo(null); //centered + win.visitRefresh(500); + + win.setVisible(true); + } +} diff --git a/src/berack96/lib/graph/view/VisitListener.java b/src/main/java/berack96/lib/graph/view/VisitListener.java similarity index 100% rename from src/berack96/lib/graph/view/VisitListener.java rename to src/main/java/berack96/lib/graph/view/VisitListener.java diff --git a/src/berack96/lib/graph/view/edge/EdgeComponent.java b/src/main/java/berack96/lib/graph/view/edge/EdgeComponent.java similarity index 100% rename from src/berack96/lib/graph/view/edge/EdgeComponent.java rename to src/main/java/berack96/lib/graph/view/edge/EdgeComponent.java diff --git a/src/berack96/lib/graph/view/edge/EdgeIntListener.java b/src/main/java/berack96/lib/graph/view/edge/EdgeIntListener.java similarity index 100% rename from src/berack96/lib/graph/view/edge/EdgeIntListener.java rename to src/main/java/berack96/lib/graph/view/edge/EdgeIntListener.java diff --git a/src/berack96/lib/graph/view/edge/EdgeListener.java b/src/main/java/berack96/lib/graph/view/edge/EdgeListener.java similarity index 100% rename from src/berack96/lib/graph/view/edge/EdgeListener.java rename to src/main/java/berack96/lib/graph/view/edge/EdgeListener.java diff --git a/src/berack96/lib/graph/view/edge/EdgeView.java b/src/main/java/berack96/lib/graph/view/edge/EdgeView.java similarity index 100% rename from src/berack96/lib/graph/view/edge/EdgeView.java rename to src/main/java/berack96/lib/graph/view/edge/EdgeView.java diff --git a/src/berack96/lib/graph/view/stuff/Arrow.java b/src/main/java/berack96/lib/graph/view/stuff/Arrow.java similarity index 100% rename from src/berack96/lib/graph/view/stuff/Arrow.java rename to src/main/java/berack96/lib/graph/view/stuff/Arrow.java diff --git a/src/berack96/lib/graph/view/vertex/VertexComponent.java b/src/main/java/berack96/lib/graph/view/vertex/VertexComponent.java similarity index 100% rename from src/berack96/lib/graph/view/vertex/VertexComponent.java rename to src/main/java/berack96/lib/graph/view/vertex/VertexComponent.java diff --git a/src/berack96/lib/graph/view/vertex/VertexIntListener.java b/src/main/java/berack96/lib/graph/view/vertex/VertexIntListener.java similarity index 100% rename from src/berack96/lib/graph/view/vertex/VertexIntListener.java rename to src/main/java/berack96/lib/graph/view/vertex/VertexIntListener.java diff --git a/src/berack96/lib/graph/view/vertex/VertexListener.java b/src/main/java/berack96/lib/graph/view/vertex/VertexListener.java similarity index 100% rename from src/berack96/lib/graph/view/vertex/VertexListener.java rename to src/main/java/berack96/lib/graph/view/vertex/VertexListener.java diff --git a/src/berack96/lib/graph/view/vertex/VertexView.java b/src/main/java/berack96/lib/graph/view/vertex/VertexView.java similarity index 100% rename from src/berack96/lib/graph/view/vertex/VertexView.java rename to src/main/java/berack96/lib/graph/view/vertex/VertexView.java diff --git a/src/berack96/lib/graph/visit/VisitDistSourceDest.java b/src/main/java/berack96/lib/graph/visit/VisitDistSourceDest.java similarity index 100% rename from src/berack96/lib/graph/visit/VisitDistSourceDest.java rename to src/main/java/berack96/lib/graph/visit/VisitDistSourceDest.java diff --git a/src/berack96/lib/graph/visit/VisitDistance.java b/src/main/java/berack96/lib/graph/visit/VisitDistance.java similarity index 100% rename from src/berack96/lib/graph/visit/VisitDistance.java rename to src/main/java/berack96/lib/graph/visit/VisitDistance.java diff --git a/src/berack96/lib/graph/visit/VisitMST.java b/src/main/java/berack96/lib/graph/visit/VisitMST.java similarity index 64% rename from src/berack96/lib/graph/visit/VisitMST.java rename to src/main/java/berack96/lib/graph/visit/VisitMST.java index 1f28ab0..7d051d8 100644 --- a/src/berack96/lib/graph/visit/VisitMST.java +++ b/src/main/java/berack96/lib/graph/visit/VisitMST.java @@ -2,7 +2,7 @@ package berack96.lib.graph.visit; import berack96.lib.graph.Edge; -import java.util.Collection; +import java.util.Set; /** * @param @@ -10,10 +10,11 @@ import java.util.Collection; public interface VisitMST extends VisitStrategy { /** - * Return the latest calculated MST. + * Return the latest calculated MST.
+ * https://en.wikipedia.org/wiki/Minimum_spanning_tree * * @return the latest MST * @throws NullPointerException if there is no last calculated MST */ - Collection> getMST(); + Set> getMST(); } diff --git a/src/berack96/lib/graph/visit/VisitSCC.java b/src/main/java/berack96/lib/graph/visit/VisitSCC.java similarity index 86% rename from src/berack96/lib/graph/visit/VisitSCC.java rename to src/main/java/berack96/lib/graph/visit/VisitSCC.java index 95a22b0..494e559 100644 --- a/src/berack96/lib/graph/visit/VisitSCC.java +++ b/src/main/java/berack96/lib/graph/visit/VisitSCC.java @@ -1,6 +1,6 @@ package berack96.lib.graph.visit; -import java.util.Collection; +import java.util.Set; /** * Interface that is helpful for implements visit that needs to retrieve the SCC @@ -16,5 +16,5 @@ public interface VisitSCC extends VisitStrategy { * @return the latest SCC * @throws NullPointerException if there is no last calculated SCC */ - Collection> getSCC(); + Set> getSCC(); } diff --git a/src/berack96/lib/graph/visit/VisitStrategy.java b/src/main/java/berack96/lib/graph/visit/VisitStrategy.java similarity index 97% rename from src/berack96/lib/graph/visit/VisitStrategy.java rename to src/main/java/berack96/lib/graph/visit/VisitStrategy.java index fda52e8..db7f68d 100644 --- a/src/berack96/lib/graph/visit/VisitStrategy.java +++ b/src/main/java/berack96/lib/graph/visit/VisitStrategy.java @@ -1,44 +1,44 @@ -package berack96.lib.graph.visit; - -import berack96.lib.graph.Graph; -import berack96.lib.graph.GraphDirected; -import berack96.lib.graph.visit.impl.VisitInfo; - -import java.util.function.Consumer; - -/** - * This class is used for define some strategy for the visit of a graph. - * - * @param The Object that represent a vertex - * @author Berack96 - */ -public interface VisitStrategy { - - /** - * With this the graph will be visited accordingly to the strategy of the visit.
- * Some strategy can accept a source vertex null, because they visit all the graph anyway.
- * If you want to stop the visit of the graph, you just have to throw any exception in the visit function, but be sure to catch it - * - * @param graph the graph to visit - * @param source the vertex where the visit starts - * @param visit the function to apply at each vertex when they are visited - * @return an info of the view - * @throws NullPointerException if the graph is null - * @throws UnsupportedOperationException in the case that the visit algorithm cannot be applied to the graph - */ - VisitInfo visit(Graph graph, V source, Consumer visit) throws NullPointerException, UnsupportedOperationException; - - /** - * Method used for checking if the graph is Directed.
- * It's useful when the algorithm can only be applied to Directed graph. - * - * @param graph the instance of the graph to check - * @return the instance of the graph casted to a {@link GraphDirected} - * @throws UnsupportedOperationException in the case it's not a directed graph - */ - default GraphDirected checkDirected(Graph graph) { - if (graph instanceof GraphDirected) - return (GraphDirected) graph; - throw new UnsupportedOperationException(); - } -} +package berack96.lib.graph.visit; + +import berack96.lib.graph.Graph; +import berack96.lib.graph.GraphDirected; +import berack96.lib.graph.visit.impl.VisitInfo; + +import java.util.function.Consumer; + +/** + * This class is used for define some strategy for the visit of a graph. + * + * @param The Object that represent a vertex + * @author Berack96 + */ +public interface VisitStrategy { + + /** + * With this the graph will be visited accordingly to the strategy of the visit.
+ * Some strategy can accept a source vertex null, because they visit all the graph anyway.
+ * If you want to stop the visit of the graph, you just have to throw any exception in the visit function, but be sure to catch it + * + * @param graph the graph to visit + * @param source the vertex where the visit starts + * @param visit the function to apply at each vertex when they are visited + * @return an info of the view + * @throws NullPointerException if the graph is null + * @throws UnsupportedOperationException in the case that the visit algorithm cannot be applied to the graph + */ + VisitInfo visit(Graph graph, V source, Consumer visit) throws NullPointerException, UnsupportedOperationException; + + /** + * Method used for checking if the graph is Directed.
+ * It's useful when the algorithm can only be applied to Directed graph. + * + * @param graph the instance of the graph to check + * @return the instance of the graph casted to a {@link GraphDirected} + * @throws UnsupportedOperationException in the case it's not a directed graph + */ + default GraphDirected checkDirected(Graph graph) { + if (graph instanceof GraphDirected) + return (GraphDirected) graph; + throw new UnsupportedOperationException(); + } +} diff --git a/src/berack96/lib/graph/visit/VisitTopological.java b/src/main/java/berack96/lib/graph/visit/VisitTopological.java similarity index 100% rename from src/berack96/lib/graph/visit/VisitTopological.java rename to src/main/java/berack96/lib/graph/visit/VisitTopological.java diff --git a/src/berack96/lib/graph/visit/impl/BFS.java b/src/main/java/berack96/lib/graph/visit/impl/BFS.java similarity index 100% rename from src/berack96/lib/graph/visit/impl/BFS.java rename to src/main/java/berack96/lib/graph/visit/impl/BFS.java diff --git a/src/berack96/lib/graph/visit/impl/DFS.java b/src/main/java/berack96/lib/graph/visit/impl/DFS.java similarity index 100% rename from src/berack96/lib/graph/visit/impl/DFS.java rename to src/main/java/berack96/lib/graph/visit/impl/DFS.java diff --git a/src/berack96/lib/graph/visit/impl/Dijkstra.java b/src/main/java/berack96/lib/graph/visit/impl/Dijkstra.java similarity index 95% rename from src/berack96/lib/graph/visit/impl/Dijkstra.java rename to src/main/java/berack96/lib/graph/visit/impl/Dijkstra.java index 45665f9..189fe85 100644 --- a/src/berack96/lib/graph/visit/impl/Dijkstra.java +++ b/src/main/java/berack96/lib/graph/visit/impl/Dijkstra.java @@ -32,8 +32,8 @@ public class Dijkstra implements VisitDistance { public VisitInfo visit(Graph graph, V source, Consumer visit) throws NullPointerException, IllegalArgumentException { VisitInfo info = new VisitInfo<>(source); Queue queue = new PriorityQueue<>(); - Map dist = new HashMap<>(); - Map prev = new HashMap<>(); + Map dist = Graph.getDefaultMap(); + Map prev = Graph.getDefaultMap(); this.source = source; dist.put(source, 0); // Initialization @@ -63,7 +63,7 @@ public class Dijkstra implements VisitDistance { } /* Cleaning up the results */ - distance = new HashMap<>(); + distance = Graph.getDefaultMap(); for (V vertex : prev.keySet()) { List> path = new LinkedList<>(); V child = vertex; diff --git a/src/berack96/lib/graph/visit/impl/Kruskal.java b/src/main/java/berack96/lib/graph/visit/impl/Kruskal.java similarity index 90% rename from src/berack96/lib/graph/visit/impl/Kruskal.java rename to src/main/java/berack96/lib/graph/visit/impl/Kruskal.java index e744935..e8c5ff3 100644 --- a/src/berack96/lib/graph/visit/impl/Kruskal.java +++ b/src/main/java/berack96/lib/graph/visit/impl/Kruskal.java @@ -17,10 +17,10 @@ import java.util.function.Consumer; * @param The vertex of the graph */ public class Kruskal implements VisitMST { - private Collection> mst; + private Set> mst; @Override - public Collection> getMST() { + public Set> getMST() { return mst; } @@ -32,7 +32,7 @@ public class Kruskal implements VisitMST { List> edges = new ArrayList<>(graph.edges()); Collections.sort(edges); - mst = new HashSet<>(graph.size(), 1); + mst = Graph.getDefaultSet(); Iterator> iter = edges.iterator(); while (iter.hasNext() && sets.size() > 1) { Edge edge = iter.next(); diff --git a/src/berack96/lib/graph/visit/impl/Prim.java b/src/main/java/berack96/lib/graph/visit/impl/Prim.java similarity index 88% rename from src/berack96/lib/graph/visit/impl/Prim.java rename to src/main/java/berack96/lib/graph/visit/impl/Prim.java index 0ce648e..27ed407 100644 --- a/src/berack96/lib/graph/visit/impl/Prim.java +++ b/src/main/java/berack96/lib/graph/visit/impl/Prim.java @@ -5,8 +5,7 @@ import berack96.lib.graph.Graph; import berack96.lib.graph.GraphUndirected; import berack96.lib.graph.visit.VisitMST; -import java.util.Collection; -import java.util.LinkedList; +import java.util.Set; import java.util.function.Consumer; /** @@ -17,17 +16,17 @@ import java.util.function.Consumer; */ public class Prim implements VisitMST { - private Collection> mst; + private Set> mst; @Override - public Collection> getMST() { + public Set> getMST() { return mst; } @Override public VisitInfo visit(Graph graph, V source, Consumer visit) throws NullPointerException, UnsupportedOperationException { - mst = new LinkedList<>(); - Collection vertices = graph.vertices(); + mst = Graph.getDefaultSet(); + Set vertices = graph.vertices(); if (source == null) source = vertices.iterator().next(); diff --git a/src/berack96/lib/graph/visit/impl/Tarjan.java b/src/main/java/berack96/lib/graph/visit/impl/Tarjan.java similarity index 93% rename from src/berack96/lib/graph/visit/impl/Tarjan.java rename to src/main/java/berack96/lib/graph/visit/impl/Tarjan.java index ff9b29d..15ab7af 100644 --- a/src/berack96/lib/graph/visit/impl/Tarjan.java +++ b/src/main/java/berack96/lib/graph/visit/impl/Tarjan.java @@ -15,7 +15,7 @@ import java.util.function.Consumer; */ public class Tarjan implements VisitSCC, VisitTopological { - private Collection> SCC = null; + private Set> SCC = null; private List topologicalSort = null; private Map indices = null; @@ -24,7 +24,7 @@ public class Tarjan implements VisitSCC, VisitTopological { private VisitInfo info = null; @Override - public Collection> getSCC() { + public Set> getSCC() { return SCC; } @@ -44,12 +44,12 @@ public class Tarjan implements VisitSCC, VisitTopological { */ @Override public VisitInfo visit(Graph graph, V source, Consumer visit) throws NullPointerException, IllegalArgumentException { - SCC = new HashSet<>(); + SCC = Graph.getDefaultSet(); topologicalSort = new ArrayList<>(graph.size()); info = null; - indices = new HashMap<>(); - lowLink = new HashMap<>(); + indices = Graph.getDefaultMap(); + lowLink = Graph.getDefaultMap(); stack = new Stack<>(); int index = 0; @@ -89,7 +89,7 @@ public class Tarjan implements VisitSCC, VisitTopological { // If v is a root node, pop the stack and generate an SCC if (lowLink.get(vertex).equals(indices.get(vertex))) { - Set newComponent = new HashSet<>(); + Set newComponent = Graph.getDefaultSet(); V temp; do { temp = stack.pop(); diff --git a/src/berack96/lib/graph/visit/impl/VisitInfo.java b/src/main/java/berack96/lib/graph/visit/impl/VisitInfo.java similarity index 100% rename from src/berack96/lib/graph/visit/impl/VisitInfo.java rename to src/main/java/berack96/lib/graph/visit/impl/VisitInfo.java diff --git a/test/berack96/test/lib/TestGraph.java b/src/test/java/berack96/test/lib/TestGraph.java similarity index 98% rename from test/berack96/test/lib/TestGraph.java rename to src/test/java/berack96/test/lib/TestGraph.java index a6492fb..f2e5046 100644 --- a/test/berack96/test/lib/TestGraph.java +++ b/src/test/java/berack96/test/lib/TestGraph.java @@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; @@ -1531,7 +1532,7 @@ public class TestGraph { shouldContain(sub.edges(), new Edge<>("4", "6", 6), new Edge<>("6", "2", 2)); - + sub = graph.subGraph("blue", "circle"); shouldContain(sub.vertices(), "1", "2", "3", "4", "5", "6"); shouldContain(sub.edges(), @@ -1543,11 +1544,27 @@ public class TestGraph { new Edge<>("5", "4", 5), new Edge<>("6", "2", 2)); + sub = graph.subGraph("even", "even"); + shouldContain(sub.vertices(), "2", "4", "6"); + shouldContain(sub.edges(), + new Edge<>("4", "6", 6), + new Edge<>("6", "2", 2)); + + sub = graph.subGraph("even", null, "even"); + shouldContain(sub.vertices(), "2", "4", "6"); + shouldContain(sub.edges(), + new Edge<>("4", "6", 6), + new Edge<>("6", "2", 2)); + + sub = graph.subGraph((Object) null); + shouldContain(sub.vertices(), "7", "8"); + shouldContain(sub.edges(), new Edge<>("8", "7", 9)); + sub = graph.subGraph(); shouldContain(sub.vertices(), "7", "8"); shouldContain(sub.edges(), new Edge<>("8", "7", 9)); - sub = graph.subGraph(null); + sub = graph.subGraph((Object[]) null); shouldContain(sub.vertices(), "7", "8"); shouldContain(sub.edges(), new Edge<>("8", "7", 9)); } @@ -1672,7 +1689,7 @@ public class TestGraph { //TODO tests for GraphUndirected save/load @ParameterizedTest @MethodSource("getGraphsDir") - public void saveLoadDir(final GraphDirected graph) { + public void saveLoadDir(final GraphDirected graph) throws URISyntaxException { /* * This graph should be like this * @@ -1682,8 +1699,7 @@ public class TestGraph { * v v * 3 <- 5 -> 4 8 */ - - String fileName = "test/resources/test.json"; + String fileName = ClassLoader.getSystemResource("").getPath() + "resources/test.json"; Set vertices = Set.of("1", "2", "3", "4", "5", "6", "7", "8"); Set> edges = new HashSet<>(); Map> marks = new HashMap<>(); diff --git a/src/test/java/resources/test.json b/src/test/java/resources/test.json new file mode 100644 index 0000000..02c57b6 --- /dev/null +++ b/src/test/java/resources/test.json @@ -0,0 +1 @@ +{"vertices":["\"6\"","\"5\"","\"4\"","\"3\"","\"2\"","\"1\"","\"8\"","\"7\""],"edges":[{"src":"\"4\"","dest":"\"6\"","weight":6},{"src":"\"2\"","dest":"\"5\"","weight":4},{"src":"\"5\"","dest":"\"4\"","weight":5},{"src":"\"5\"","dest":"\"3\"","weight":2},{"src":"\"1\"","dest":"\"3\"","weight":1},{"src":"\"6\"","dest":"\"2\"","weight":2},{"src":"\"1\"","dest":"\"2\"","weight":1},{"src":"\"8\"","dest":"\"7\"","weight":9}]} \ No newline at end of file diff --git a/test/resources/test.json.fail b/src/test/java/resources/test.json.fail similarity index 100% rename from test/resources/test.json.fail rename to src/test/java/resources/test.json.fail diff --git a/test/resources/test.json b/test/resources/test.json deleted file mode 100644 index 624e195..0000000 --- a/test/resources/test.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "vertices": [ - "\"6\"", - "\"5\"", - "\"4\"", - "\"3\"", - "\"2\"", - "\"1\"", - "\"8\"", - "\"7\"" - ], - "edges": [ - { - "src": "\"4\"", - "dest": "\"6\"", - "weight": 6 - }, - { - "src": "\"2\"", - "dest": "\"5\"", - "weight": 4 - }, - { - "src": "\"5\"", - "dest": "\"4\"", - "weight": 5 - }, - { - "src": "\"5\"", - "dest": "\"3\"", - "weight": 2 - }, - { - "src": "\"1\"", - "dest": "\"3\"", - "weight": 1 - }, - { - "src": "\"6\"", - "dest": "\"2\"", - "weight": 2 - }, - { - "src": "\"1\"", - "dest": "\"2\"", - "weight": 1 - }, - { - "src": "\"8\"", - "dest": "\"7\"", - "weight": 9 - } - ] -} \ No newline at end of file