From 8c94b79d2679252e8e75e3a31deea5dd2af90a59 Mon Sep 17 00:00:00 2001 From: Javier Marrero Date: Wed, 9 Nov 2022 15:45:16 -0500 Subject: [PATCH 1/2] Merge origin/main into development-the_surgeon Conflicts: src/cu/edu/cujae/graphy/algorithms/AbstractAlgorithm.java src/cu/edu/cujae/graphy/algorithms/Algorithm.java src/cu/edu/cujae/graphy/algorithms/CycleDetection.java src/cu/edu/cujae/graphy/algorithms/DijkstraShortestPath.java src/cu/edu/cujae/graphy/algorithms/HamiltonianCycleDetection.java src/cu/edu/cujae/graphy/core/Edge.java src/cu/edu/cujae/graphy/core/EdgeFactory.java src/cu/edu/cujae/graphy/core/Graph.java src/cu/edu/cujae/graphy/core/GraphBuilder.java src/cu/edu/cujae/graphy/core/Node.java src/cu/edu/cujae/graphy/core/Tree.java src/cu/edu/cujae/graphy/core/Weight.java src/cu/edu/cujae/graphy/core/WeightedGraph.java src/cu/edu/cujae/graphy/core/abstractions/AbstractEdge.java src/cu/edu/cujae/graphy/core/abstractions/AbstractGraph.java src/cu/edu/cujae/graphy/core/abstractions/AdjacencyListGraph.java src/cu/edu/cujae/graphy/core/defaults/DefaultGraphBuilder.java src/cu/edu/cujae/graphy/core/defaults/DefaultNode.java src/cu/edu/cujae/graphy/core/defaults/DefaultSimpleGraph.java src/cu/edu/cujae/graphy/core/defaults/DefaultWeightedGraphBuilder.java src/cu/edu/cujae/graphy/core/exceptions/InvalidOperationException.java src/cu/edu/cujae/graphy/core/iterators/AbstractGraphIterator.java src/cu/edu/cujae/graphy/core/iterators/GraphIterator.java src/cu/edu/cujae/graphy/core/trees/DefaultGeneralTreeNode.java src/cu/edu/cujae/graphy/core/utility/GraphBuilders.java src/cu/edu/cujae/graphy/core/utility/Weights.java src/cu/edu/cujae/graphy/utils/Pair.java test/cu/edu/cujae/graphy/tests/algorithms/CyclesTest.java --- nbproject/project.properties | 196 +++++----- .../algorithms/DijkstraShortestPath.java | 370 +++++++++--------- src/cu/edu/cujae/graphy/core/Tree.java | 146 +++---- .../core/defaults/DefaultGraphBuilder.java | 128 +++--- .../cujae/graphy/tests/WeightedGraphTest.java | 2 + .../graphy/tests/algorithms/CyclesTest.java | 144 +++---- .../tests/algorithms/TreeDetectionTest.java | 190 ++++----- 7 files changed, 590 insertions(+), 586 deletions(-) diff --git a/nbproject/project.properties b/nbproject/project.properties index dd349ad..916a5a5 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -1,98 +1,98 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=true -annotation.processing.processors.list= -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -application.title=jlibgraph -application.vendor=Javier Marrero -auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml -build.classes.dir=${build.dir}/classes -build.classes.excludes=**/*.java,**/*.form -# This directory is removed when the project is cleaned: -build.dir=build -build.generated.dir=${build.dir}/generated -build.generated.sources.dir=${build.dir}/generated-sources -# Only compile against the classpath explicitly listed here: -build.sysclasspath=ignore -build.test.classes.dir=${build.dir}/test/classes -build.test.results.dir=${build.dir}/test/results -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.modulepath=\ - ${run.modulepath} -debug.test.classpath=\ - ${run.test.classpath} -debug.test.modulepath=\ - ${run.test.modulepath} -# Files in build.classes.dir which should be excluded from distribution jar -dist.archive.excludes= -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=${dist.dir}/jlibgraph.jar -dist.javadoc.dir=${dist.dir}/javadoc -dist.jlink.dir=${dist.dir}/jlink -dist.jlink.output=${dist.jlink.dir}/jlibgraph -endorsed.classpath= -excludes= -includes=** -jar.compress=false -javac.classpath= -# Space-separated list of extra javac options -javac.compilerargs= -javac.deprecation=true -javac.external.vm=true -javac.modulepath= -javac.processormodulepath= -javac.processorpath=\ - ${javac.classpath} -javac.source=11 -javac.target=11 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir}:\ - ${libs.junit_5.classpath} -javac.test.modulepath=\ - ${javac.modulepath} -javac.test.processorpath=\ - ${javac.test.classpath} -javadoc.additionalparam= -javadoc.author=true -javadoc.encoding=${source.encoding} -javadoc.html5=false -javadoc.noindex=false -javadoc.nonavbar=false -javadoc.notree=false -javadoc.private=false -javadoc.splitindex=true -javadoc.use=true -javadoc.version=true -javadoc.windowtitle=JLibGraph API Reference -# The jlink additional root modules to resolve -jlink.additionalmodules= -# The jlink additional command line parameters -jlink.additionalparam= -jlink.launcher=true -jlink.launcher.name=jlibgraph -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=true -platform.active=default_platform -project.license=lgpl21 -run.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -# Space-separated list of JVM arguments used when running the project. -# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. -# To set system properties for unit tests define test-sys-prop.name=value: -run.jvmargs= -run.modulepath=\ - ${javac.modulepath} -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -run.test.modulepath=\ - ${javac.test.modulepath} -source.encoding=UTF-8 -src.dir=src -test.src.dir=test +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=true +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=jlibgraph +application.vendor=Javier Marrero +auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.modulepath=\ + ${run.modulepath} +debug.test.classpath=\ + ${run.test.classpath} +debug.test.modulepath=\ + ${run.test.modulepath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/jlibgraph.jar +dist.javadoc.dir=${dist.dir}/javadoc +dist.jlink.dir=${dist.dir}/jlink +dist.jlink.output=${dist.jlink.dir}/jlibgraph +endorsed.classpath= +excludes= +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=true +javac.external.vm=true +javac.modulepath= +javac.processormodulepath= +javac.processorpath=\ + ${javac.classpath} +javac.source=12 +javac.target=12 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit_5.classpath} +javac.test.modulepath=\ + ${javac.modulepath} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=true +javadoc.encoding=${source.encoding} +javadoc.html5=false +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=true +javadoc.windowtitle=JLibGraph API Reference +# The jlink additional root modules to resolve +jlink.additionalmodules= +# The jlink additional command line parameters +jlink.additionalparam= +jlink.launcher=true +jlink.launcher.name=jlibgraph +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=true +platform.active=default_platform +project.license=lgpl21 +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.modulepath=\ + ${javac.modulepath} +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +run.test.modulepath=\ + ${javac.test.modulepath} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/src/cu/edu/cujae/graphy/algorithms/DijkstraShortestPath.java b/src/cu/edu/cujae/graphy/algorithms/DijkstraShortestPath.java index 85e9c7e..4e101b9 100644 --- a/src/cu/edu/cujae/graphy/algorithms/DijkstraShortestPath.java +++ b/src/cu/edu/cujae/graphy/algorithms/DijkstraShortestPath.java @@ -1,185 +1,185 @@ -/* - * Copyright (C) 2022 CUJAE. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ -package cu.edu.cujae.graphy.algorithms; - -import cu.edu.cujae.graphy.core.Edge; -import cu.edu.cujae.graphy.core.WeightedGraph; -import cu.edu.cujae.graphy.core.iterators.GraphIterator; -import cu.edu.cujae.graphy.utils.Pair; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.TreeMap; - -/** - * Given a graph and a source vertex in the graph, find the shortest paths from the source to all vertices in the given - * graph. - *

- * The name of the algorithm refers to the Dutch computation scientist Edsger Dijkstra, who described it in 1959. - * The algorithm solves the single-source shortest path problem for a weighted graph. This algorithm is greedy - * and keeps track of the weights of the edges for finding the path that minimizes the total distance. - *

- * The time complexity of this algorithm is at most O(n2) but on the average case it may - * achieve O(V + E log(V)). Dijkstra has several advantages such as its time complexity, that it is useful - * in finding the shortest distance quite fast. However it is unable to handle negative weights and, as every greedy - * algorithm it may not be optimal for certain conditions. - *

- * Dijkstra's algorithm fails on negative weights because since Dijkstra follows a greedy approach, once a node is - * marked as visited it cannot be reconsidered even if there is another path with less cost or distance. This issue - * arises only if there exists a negative weight or edge in the graph. If negative weights are needed, see the - * Bellman-Ford algorithm. In this implementation, whenever a graph with negative weights is encountered it may throw - * a {@link InvalidOperationException}. - * - * @author Javier Marrero - * @param The type of the graph - */ -public class DijkstraShortestPath extends AbstractAlgorithm>>> -{ - - private final Map distances; - private final WeightedGraph G; - private final GraphIterator it; - private final Map previous; - private final int s; - private final PriorityQueue Q; - private final int V; - - public DijkstraShortestPath(WeightedGraph graph, GraphIterator iter) - { - super(new HashMap<>(graph.size())); - if (!graph.isWeighted()) - { - throw new IllegalArgumentException( - "Attempted to apply Dijkstra Shortest Path algorithm to an unweighted graph."); - } - - // Initialize the fields of the classes - this.distances = new HashMap<>(graph.size(), 0.25f); - this.G = graph; - this.it = iter; - this.previous = new TreeMap<>(); - this.s = iter.getLabel(); - this.Q = new PriorityQueue<>(graph.size(), (Integer u, Integer v) -> - { - int du = distances.get(u); - int dv = distances.get(v); - - return du - dv; - }); - this.V = graph.size(); - - // Get a set of all the integer vertices - int[] vertices = new int[V]; - int k = 0; - - GraphIterator depthFirstSearchIterator = (GraphIterator) graph.depthFirstSearchIterator(false); - while (depthFirstSearchIterator.hasNext()) - { - depthFirstSearchIterator.next(); - vertices[k++] = depthFirstSearchIterator.getLabel(); - } - - // Initialize the distances - for (int v : vertices) - { - if (G.isVertexAdjacent(s, v)) - { - distances.put(v, (Integer) iter.getAdjacentEdge(v).getWeight().getValue()); - previous.put(v, iter.getLabel()); - } - else - { - distances.put(v, Integer.MAX_VALUE); - previous.put(v, null); - } - - Q.add(v); - } - - // System.err.println(Q); - // Initialize the initial distances - distances.put(iter.getLabel(), 0); - } - - @Override - public Algorithm>>> apply() - { - // Code - while (!Q.isEmpty()) - { - // System.err.println(Q); - - int u = Q.poll(); - it.next(u); - - for (Edge edge : it.getAllAdjacentEdges()) - { - int v; - if (it.getEdgesDepartingSelf().contains(edge)) - { - v = edge.getFinalNode().getLabel(); - } - else - { - v = edge.getStartNode().getLabel(); - } - - if (Q.contains(v)) - { - int alt = distances.get(u) + (int) edge.getWeight().getValue(); - if (alt <= distances.get(v)) - { - distances.put(v, alt); - previous.put(v, u); - } - } - } - } - - // Create the shortest path sequence - // Create the final result - Map>> result = getResult(); - for (int k : distances.keySet()) - { - result.put(k, new Pair<>(distances.get(k), makeShortestPathSequence(s, k))); - } - - // Mandated by the specification - return this; - } - - private List makeShortestPathSequence(int source, int target) - { - LinkedList S = new LinkedList<>(); - int u = target; - - if (previous.get(u) != null) - { - while (previous.get(u) != null) - { - S.push(u); - u = previous.get(u); - } - } - S.push(source); - return S; - } -} +/* + * Copyright (C) 2022 CUJAE. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package cu.edu.cujae.graphy.algorithms; + +import cu.edu.cujae.graphy.core.Edge; +import cu.edu.cujae.graphy.core.WeightedGraph; +import cu.edu.cujae.graphy.core.iterators.GraphIterator; +import cu.edu.cujae.graphy.utils.Pair; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.TreeMap; + +/** + * Given a graph and a source vertex in the graph, find the shortest paths from the source to all vertices in the given + * graph. + *

+ * The name of the algorithm refers to the Dutch computation scientist Edsger Dijkstra, who described it in 1959. + * The algorithm solves the single-source shortest path problem for a weighted graph. This algorithm is greedy + * and keeps track of the weights of the edges for finding the path that minimizes the total distance. + *

+ * The time complexity of this algorithm is at most O(n2) but on the average case it may + * achieve O(V + E log(V)). Dijkstra has several advantages such as its time complexity, that it is useful + * in finding the shortest distance quite fast. However it is unable to handle negative weights and, as every greedy + * algorithm it may not be optimal for certain conditions. + *

+ * Dijkstra's algorithm fails on negative weights because since Dijkstra follows a greedy approach, once a node is + * marked as visited it cannot be reconsidered even if there is another path with less cost or distance. This issue + * arises only if there exists a negative weight or edge in the graph. If negative weights are needed, see the + * Bellman-Ford algorithm. In this implementation, whenever a graph with negative weights is encountered it may throw + * a {@link InvalidOperationException}. + * + * @author Javier Marrero + * @param The type of the graph + */ +public class DijkstraShortestPath extends AbstractAlgorithm>>> +{ + + private final Map distances; + private final WeightedGraph G; + private final GraphIterator it; + private final Map previous; + private final int s; + private final PriorityQueue Q; + private final int V; + + public DijkstraShortestPath(WeightedGraph graph, GraphIterator iter) + { + super(new HashMap<>(graph.size())); + if (!graph.isWeighted()) + { + throw new IllegalArgumentException( + "Attempted to apply Dijkstra Shortest Path algorithm to an unweighted graph."); + } + + // Initialize the fields of the classes + this.distances = new HashMap<>(graph.size(), 0.25f); + this.G = graph; + this.it = iter; + this.previous = new TreeMap<>(); + this.s = iter.getLabel(); + this.Q = new PriorityQueue<>(graph.size(), (Integer u, Integer v) -> + { + int du = distances.get(u); + int dv = distances.get(v); + + return du - dv; + }); + this.V = graph.size(); + + // Get a set of all the integer vertices + int[] vertices = new int[V]; + int k = 0; + + GraphIterator depthFirstSearchIterator = (GraphIterator) graph.depthFirstSearchIterator(false); + while (depthFirstSearchIterator.hasNext()) + { + depthFirstSearchIterator.next(); + vertices[k++] = depthFirstSearchIterator.getLabel(); + } + + // Initialize the distances + for (int v : vertices) + { + if (G.isVertexAdjacent(s, v)) + { + distances.put(v, (Integer) iter.getAdjacentEdge(v).getWeight().getValue()); + previous.put(v, iter.getLabel()); + } + else + { + distances.put(v, Integer.MAX_VALUE); + previous.put(v, null); + } + + Q.add(v); + } + + // System.err.println(Q); + // Initialize the initial distances + distances.put(iter.getLabel(), 0); + } + + @Override + public Algorithm>>> apply() + { + // Code + while (!Q.isEmpty()) + { + // System.err.println(Q); + + int u = Q.poll(); + it.next(u); + + for (Edge edge : it.getAllAdjacentEdges()) + { + int v; + if (it.getEdgesDepartingSelf().contains(edge)) + { + v = edge.getFinalNode().getLabel(); + } + else + { + v = edge.getStartNode().getLabel(); + } + + if (Q.contains(v)) + { + int alt = distances.get(u) + (int) edge.getWeight().getValue(); + if (alt <= distances.get(v)) + { + distances.put(v, alt); + previous.put(v, u); + } + } + } + } + + // Create the shortest path sequence + // Create the final result + Map>> result = getResult(); + for (int k : distances.keySet()) + { + result.put(k, new Pair<>(distances.get(k), makeShortestPathSequence(s, k))); + } + + // Mandated by the specification + return this; + } + + private List makeShortestPathSequence(int source, int target) + { + LinkedList S = new LinkedList<>(); + int u = target; + + if (previous.get(u) != null) + { + while (previous.get(u) != null) + { + S.push(u); + u = previous.get(u); + } + } + S.push(source); + return S; + } +} diff --git a/src/cu/edu/cujae/graphy/core/Tree.java b/src/cu/edu/cujae/graphy/core/Tree.java index 6b79d84..6035c38 100644 --- a/src/cu/edu/cujae/graphy/core/Tree.java +++ b/src/cu/edu/cujae/graphy/core/Tree.java @@ -1,73 +1,73 @@ -/* - * Copyright (C) 2022 CUJAE. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ -package cu.edu.cujae.graphy.core; - -/** - * A tree is a data structure represented by a directed acyclic graph, imitating the shape of a tree.It is a set of - * connected nodes. A node is the basic unit over which the tree is constructed and may have zero or several children. - * A node A is parent of a node B if there is a direct connection from A to B. There can be only a single node without - * a parent and that is called root. - *

- * This interface represents trees on its most wide definition. - * - * @see Graph - * - * @author Javier Marrero - * @param - */ -public interface Tree extends Graph -{ - - /** - * Adds a new children to the parent node. - * - * @param parent - * @param data - * - * @return - */ - public boolean add(TreeNode parent, E data); - - /** - * Returns the height of the tree. The height of a tree is a recursive relation defined by the following formula: - *

- * - * @return an integer representing the tree height - */ - public int getHeight(); - - /** - * Returns a reference to the root of this tree. - * - * @return {@link TreeNode} - */ - public TreeNode getRoot(); - - /** - * Returns the result of testing wether the provided node is the root node of this tree. - * - * @param node - * - * @return - */ - public boolean isRoot(TreeNode node); -} +/* + * Copyright (C) 2022 CUJAE. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package cu.edu.cujae.graphy.core; + +/** + * A tree is a data structure represented by a directed acyclic graph, imitating the shape of a tree.It is a set of + * connected nodes. A node is the basic unit over which the tree is constructed and may have zero or several children. + * A node A is parent of a node B if there is a direct connection from A to B. There can be only a single node without + * a parent and that is called root. + *

+ * This interface represents trees on its most wide definition. + * + * @see Graph + * + * @author Javier Marrero + * @param + */ +public interface Tree extends Graph +{ + + /** + * Adds a new children to the parent node. + * + * @param parent + * @param data + * + * @return + */ + public boolean add(TreeNode parent, E data); + + /** + * Returns the height of the tree. The height of a tree is a recursive relation defined by the following formula: + *

    + *
  • 0 if the tree contains the root only
  • + *
  • max(H(c1), H(c2), ..., H(cn) if the tree contains more nodes
  • + *
+ * + * @return an integer representing the tree height + */ + public int getHeight(); + + /** + * Returns a reference to the root of this tree. + * + * @return {@link TreeNode} + */ + public TreeNode getRoot(); + + /** + * Returns the result of testing wether the provided node is the root node of this tree. + * + * @param node + * + * @return + */ + public boolean isRoot(TreeNode node); +} diff --git a/src/cu/edu/cujae/graphy/core/defaults/DefaultGraphBuilder.java b/src/cu/edu/cujae/graphy/core/defaults/DefaultGraphBuilder.java index 729a990..e5692f3 100644 --- a/src/cu/edu/cujae/graphy/core/defaults/DefaultGraphBuilder.java +++ b/src/cu/edu/cujae/graphy/core/defaults/DefaultGraphBuilder.java @@ -1,64 +1,64 @@ -/* - * Copyright (C) 2022 CUJAE. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ -package cu.edu.cujae.graphy.core.defaults; - -import cu.edu.cujae.graphy.core.Graph; -import cu.edu.cujae.graphy.core.GraphBuilder; - -/** - * This is a default implementation of the {@link GraphBuilder} interface. - * - * @author Javier Marrero - * @param - */ -public class DefaultGraphBuilder implements GraphBuilder -{ - - private DefaultSimpleGraph instance; - - public DefaultGraphBuilder() - { - this.instance = null; - } - - @Override - public GraphBuilder buildGraph() - { - // Create the instance - instance = new DefaultSimpleGraph<>(); - return this; - } - - @Override - public GraphBuilder directed(boolean directed) - { - instance.setDirected(true); - instance.registerEdgeFactory((directed) ? (new DefaultDirectedEdgeFactory()) - : (new DefaultNotDirectedEdgeFactory())); - - return this; - } - - @Override - public Graph get() - { - return instance; - } - -} +/* + * Copyright (C) 2022 CUJAE. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package cu.edu.cujae.graphy.core.defaults; + +import cu.edu.cujae.graphy.core.Graph; +import cu.edu.cujae.graphy.core.GraphBuilder; + +/** + * This is a default implementation of the {@link GraphBuilder} interface. + * + * @author Javier Marrero + * @param + */ +public class DefaultGraphBuilder implements GraphBuilder +{ + + private DefaultSimpleGraph instance; + + public DefaultGraphBuilder() + { + this.instance = null; + } + + @Override + public GraphBuilder buildGraph() + { + // Create the instance + instance = new DefaultSimpleGraph<>(); + return this; + } + + @Override + public GraphBuilder directed(boolean directed) + { + instance.setDirected(true); + instance.registerEdgeFactory((directed) ? (new DefaultDirectedEdgeFactory()) + : (new DefaultNotDirectedEdgeFactory())); + + return this; + } + + @Override + public Graph get() + { + return instance; + } + +} diff --git a/test/cu/edu/cujae/graphy/tests/WeightedGraphTest.java b/test/cu/edu/cujae/graphy/tests/WeightedGraphTest.java index ac7361b..e5cc931 100644 --- a/test/cu/edu/cujae/graphy/tests/WeightedGraphTest.java +++ b/test/cu/edu/cujae/graphy/tests/WeightedGraphTest.java @@ -18,7 +18,9 @@ */ package cu.edu.cujae.graphy.tests; +import cu.edu.cujae.graphy.algorithms.HamiltonianCycleDetection; import cu.edu.cujae.graphy.core.WeightedGraph; +import cu.edu.cujae.graphy.core.utility.GraphBuilders; import cu.edu.cujae.graphy.core.utility.Weights; import java.util.Iterator; import java.util.Random; diff --git a/test/cu/edu/cujae/graphy/tests/algorithms/CyclesTest.java b/test/cu/edu/cujae/graphy/tests/algorithms/CyclesTest.java index dd991ab..2bff5f8 100644 --- a/test/cu/edu/cujae/graphy/tests/algorithms/CyclesTest.java +++ b/test/cu/edu/cujae/graphy/tests/algorithms/CyclesTest.java @@ -1,72 +1,72 @@ -/* - * Copyright (C) 2022 CUJAE. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ -package cu.edu.cujae.graphy.tests.algorithms; - -import cu.edu.cujae.graphy.algorithms.CycleDetection; -import cu.edu.cujae.graphy.core.defaults.DefaultGraphBuilder; -import cu.edu.cujae.graphy.core.Graph; - -/** - * This class tests the different cycle detectors. - * - * @author Javier Marrero - */ -public class CyclesTest -{ - - public static void checkSimpleCycle(Graph graph) - { - System.out.println("Contains cycle?: " + (new CycleDetection<>(graph).apply().get())); - } - - public static void main(String[] args) - { - Graph g1 = new DefaultGraphBuilder().buildGraph().directed(false).get(); - Graph g2 = new DefaultGraphBuilder().buildGraph().directed(false).get(); - - // Populate the graph - for (int i = 0; i < 5; ++i) - { - g1.add(i); - if (i < 3) - { - g2.add(i); - } - } - - // Connect G1 - g1.connect(0, 1); - g1.connect(0, 2); - g1.connect(2, 1); - g1.connect(0, 3); - g1.connect(3, 4); - - System.out.println("Built g1..."); - - // Connect G2 - g2.connect(0, 1); - g2.connect(1, 2); - - System.out.println("Built g2..."); - - // Contains cycle? - checkSimpleCycle(g1); - checkSimpleCycle(g2); - } -} +/* + * Copyright (C) 2022 CUJAE. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package cu.edu.cujae.graphy.tests.algorithms; + +import cu.edu.cujae.graphy.algorithms.CycleDetection; +import cu.edu.cujae.graphy.core.Graph; +import cu.edu.cujae.graphy.core.defaults.DefaultGraphBuilder; + +/** + * This class tests the different cycle detectors. + * + * @author Javier Marrero + */ +public class CyclesTest +{ + + public static void checkSimpleCycle(Graph graph) + { + System.out.println("Contains cycle?: " + (new CycleDetection<>(graph).apply().get())); + } + + public static void main(String[] args) + { + Graph g1 = new DefaultGraphBuilder().buildGraph().directed(false).get(); + Graph g2 = new DefaultGraphBuilder().buildGraph().directed(false).get(); + + // Populate the graph + for (int i = 0; i < 5; ++i) + { + g1.add(i); + if (i < 3) + { + g2.add(i); + } + } + + // Connect G1 + g1.connect(0, 1); + g1.connect(0, 2); + g1.connect(2, 1); + g1.connect(0, 3); + g1.connect(3, 4); + + System.out.println("Built g1..."); + + // Connect G2 + g2.connect(0, 1); + g2.connect(1, 2); + + System.out.println("Built g2..."); + + // Contains cycle? + checkSimpleCycle(g1); + checkSimpleCycle(g2); + } +} diff --git a/test/cu/edu/cujae/graphy/tests/algorithms/TreeDetectionTest.java b/test/cu/edu/cujae/graphy/tests/algorithms/TreeDetectionTest.java index fb37731..50a1155 100644 --- a/test/cu/edu/cujae/graphy/tests/algorithms/TreeDetectionTest.java +++ b/test/cu/edu/cujae/graphy/tests/algorithms/TreeDetectionTest.java @@ -1,94 +1,96 @@ -/* - * Copyright (C) 2022 Jose. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ -package cu.edu.cujae.graphy.tests.algorithms; - -import cu.edu.cujae.graphy.algorithms.TreeDetection; -import cu.edu.cujae.graphy.core.Graph; -import cu.edu.cujae.graphy.core.defaults.DefaultGraphBuilder; -import cu.edu.cujae.graphy.core.iterators.GraphIterator; - -/** - * - * @author Jose - */ -public class TreeDetectionTest -{ - - public static void checkIsATree(Graph graph) - { - System.out.println("Is a tree?: " + (new TreeDetection<>(graph, (GraphIterator) graph.depthFirstSearchIterator(0, Boolean.FALSE)).apply().get())); - } - - public static void main(String[] args) - { - /*Juego de datos para cuando un grafo es un árbol*/ - Graph graph = new DefaultGraphBuilder().buildGraph().directed(false).get(); - for (int i = 0; i < 10; i++) - { - graph.add(i, i); - } - graph.connect(0, 1); - graph.connect(0, 2); - graph.connect(1, 4); - graph.connect(2, 5); - graph.connect(5, 7); - graph.connect(2, 3); - graph.connect(3, 6); - graph.connect(6, 8); - graph.connect(3, 9); - - /*Juego de datos para cuando un grafo no es un árbol, posee un ciclo*/ - Graph graph2 = new DefaultGraphBuilder().buildGraph().directed(false).get(); - for (int i = 0; i < 10; i++) - { - graph2.add(i, i); - } - graph2.connect(0, 1); - graph2.connect(0, 2); - graph2.connect(1, 2); - graph2.connect(1, 4); - graph2.connect(2, 5); - graph2.connect(5, 7); - graph2.connect(2, 3); - graph2.connect(3, 6); - graph2.connect(6, 8); - graph2.connect(3, 9); - - /*Juego de datos para cuando un grafo no es un árbol, posee un nodo desconectado, label=9*/ - Graph graph3 = new DefaultGraphBuilder().buildGraph().directed(false).get(); - for (int i = 0; i < 10; i++) - { - graph3.add(i, i); - } - graph3.connect(0, 1); - graph3.connect(0, 2); - graph3.connect(1, 4); - graph3.connect(2, 5); - graph3.connect(5, 7); - graph3.connect(2, 3); - graph3.connect(3, 6); - graph3.connect(6, 8); - - /*Is a tree*/ - checkIsATree(graph); - checkIsATree(graph2); - checkIsATree(graph3); - - } -} +/* + * Copyright (C) 2022 Jose. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package cu.edu.cujae.graphy.tests.algorithms; + +import cu.edu.cujae.graphy.algorithms.TreeDetection; +import cu.edu.cujae.graphy.core.Graph; +import cu.edu.cujae.graphy.core.defaults.DefaultGraphBuilder; +import cu.edu.cujae.graphy.core.iterators.GraphIterator; + +/** + * + * @author Jose + */ +public class TreeDetectionTest +{ + + public static void checkIsATree(Graph graph) + { + System.out.println("Is a tree?: " + (new TreeDetection<>(graph, (GraphIterator) graph. + depthFirstSearchIterator(0, Boolean.FALSE)).apply(). + get())); + } + + public static void main(String[] args) + { + /*Juego de datos para cuando un grafo es un árbol*/ + Graph graph = new DefaultGraphBuilder().buildGraph().directed(false).get(); + for (int i = 0; i < 10; i++) + { + graph.add(i, i); + } + graph.connect(0, 1); + graph.connect(0, 2); + graph.connect(1, 4); + graph.connect(2, 5); + graph.connect(5, 7); + graph.connect(2, 3); + graph.connect(3, 6); + graph.connect(6, 8); + graph.connect(3, 9); + + /*Juego de datos para cuando un grafo no es un árbol, posee un ciclo*/ + Graph graph2 = new DefaultGraphBuilder().buildGraph().directed(false).get(); + for (int i = 0; i < 10; i++) + { + graph2.add(i, i); + } + graph2.connect(0, 1); + graph2.connect(0, 2); + graph2.connect(1, 2); + graph2.connect(1, 4); + graph2.connect(2, 5); + graph2.connect(5, 7); + graph2.connect(2, 3); + graph2.connect(3, 6); + graph2.connect(6, 8); + graph2.connect(3, 9); + + /*Juego de datos para cuando un grafo no es un árbol, posee un nodo desconectado, label=9*/ + Graph graph3 = new DefaultGraphBuilder().buildGraph().directed(false).get(); + for (int i = 0; i < 10; i++) + { + graph3.add(i, i); + } + graph3.connect(0, 1); + graph3.connect(0, 2); + graph3.connect(1, 4); + graph3.connect(2, 5); + graph3.connect(5, 7); + graph3.connect(2, 3); + graph3.connect(3, 6); + graph3.connect(6, 8); + + /*Is a tree*/ + checkIsATree(graph); + checkIsATree(graph2); + checkIsATree(graph3); + + } +} From 50beff22821e3d79d796fd32e762859b7ddced3d Mon Sep 17 00:00:00 2001 From: Javier Marrero Date: Thu, 10 Nov 2022 18:06:09 -0500 Subject: [PATCH 2/2] Minor updates Added a tridimensional associative array implemented with trees. --- .../edu/cujae/graphy/utils/MapTriArray.java | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/cu/edu/cujae/graphy/utils/MapTriArray.java diff --git a/src/cu/edu/cujae/graphy/utils/MapTriArray.java b/src/cu/edu/cujae/graphy/utils/MapTriArray.java new file mode 100644 index 0000000..cd0fad0 --- /dev/null +++ b/src/cu/edu/cujae/graphy/utils/MapTriArray.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2022 Javier Marrero. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package cu.edu.cujae.graphy.utils; + +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +/** + * This class represents an associative tridimensional array.However, this is implemented using maps to allow for non + * sequential keys to be used. + *

+ * This implementation actually uses red black trees to implement the subjacent data structure. + * + * @author Javier Marrero + * @param First key type + * @param Second key type + * @param Third key type + * @param Value type + */ +public class MapTriArray +{ + + /// An associative array of maps. + private final Map>> dictionary; + + /** + * Creates a new tridimensional array. + */ + public MapTriArray() + { + this.dictionary = new TreeMap<>(); + } + + /** + * Similar to operator [] on tridimensional arrays. Can be imagined as Map[i][j][k]. + * + * @param k + * @param i + * @param j + * + * @return + */ + public V get(K k, I i, J j) + { + return dictionary.get(k).get(i).get(j); + } + + /** + * Similar to operator [] on tridimensional arrays. It returns a {@link Map} instance holding all the elements on + * the row j. The returned map is unmodifiable. + * + * @param k + * @param i + * + * @return + */ + public Map get(K k, I i) + { + return Collections.unmodifiableMap(dictionary.get(k).get(i)); + } + + /** + * Similar to operator [] on tridimensional arrays. It returns a {@link Map} instance holding all the elements on + * the kth row. The returned map is inmutable. + * + * @param k + * + * @return + */ + public Map> get(K k) + { + return Collections.unmodifiableMap(dictionary.get(k)); + } + + /** + * Similar to the operation Map[k][i][j] = newValue + * + * @param k + * @param i + * @param j + * @param newValue + * + * @return + */ + public V put(K k, I i, J j, V newValue) + { + Map> secondLevel = dictionary.get(k); + if (secondLevel == null) + { + secondLevel = new TreeMap<>(); + dictionary.put(k, secondLevel); + } + + Map thirdLevel = secondLevel.get(i); + if (thirdLevel == null) + { + thirdLevel = new TreeMap<>(); + secondLevel.put(i, thirdLevel); + } + + return thirdLevel.put(j, newValue); + } +}