diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/Graph.java b/jgalgo-core/src/main/java/com/jgalgo/graph/Graph.java index 90adcbc9bc..89a1eda5d0 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/Graph.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/Graph.java @@ -17,7 +17,6 @@ package com.jgalgo.graph; import java.util.Collection; -import java.util.Optional; import java.util.Set; /** @@ -957,7 +956,7 @@ default > WeightsT addEdgesWeights(String key, *

* An identical copy of this graph will be created, with the same vertices, edges, capabilities (inclusive) such as * self edges and parallel edges support, without copying the vertices/edges weights. The returned graph will always - * be modifiable, with no side affects on the original graph. + * be mutable, with no side affects on the original graph. * * @return an identical copy of this graph, with the same vertices and edges, without this graph weights */ @@ -971,7 +970,7 @@ default Graph copy() { *

* An identical copy of this graph will be created, with the same vertices, edges, capabilities (inclusive) such as * self edges and parallel edges support, with/without copying the vertices/edges weights. The returned graph will - * always be modifiable, with no side affects on the original graph. + * always be mutable, with no side affects on the original graph. * *

* Note that although {@code g.equals(g.copy())} is always {@code true} if both {@code copyVerticesWeights} @@ -1037,23 +1036,7 @@ default Graph immutableCopy() { * graph weights */ default Graph immutableCopy(boolean copyVerticesWeights, boolean copyEdgesWeights) { - IndexIdMap viMap = indexGraphVerticesMap(); - IndexIdMap eiMap = indexGraphEdgesMap(); - /* create a new factory with no vertex and edge builders */ - GraphFactoryImpl factory = new GraphFactoryImpl<>(isDirected()); - factory.setVertexBuilder(null); - factory.setEdgeBuilder(null); - if (isDirected()) { - IndexGraphBuilder.ReIndexedGraph reIndexedGraph = - GraphCsrDirectedReindexed.newInstance(indexGraph(), copyVerticesWeights, copyEdgesWeights); - IndexGraph iGraph = reIndexedGraph.graph(); - Optional vReIndexing = reIndexedGraph.verticesReIndexing(); - Optional eReIndexing = reIndexedGraph.edgesReIndexing(); - return new GraphImpl<>(factory, iGraph, viMap, eiMap, vReIndexing.orElse(null), eReIndexing.orElse(null)); - } else { - IndexGraph iGraph = new GraphCsrUndirected(indexGraph(), copyVerticesWeights, copyEdgesWeights); - return new GraphImpl<>(factory, iGraph, viMap, eiMap, null, null); - } + return Graphs.immutableCopy(this, copyVerticesWeights, copyEdgesWeights); } /** diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphBuilderImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphBuilderImpl.java index a9ecfde797..6dda889348 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphBuilderImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphBuilderImpl.java @@ -45,8 +45,9 @@ class GraphBuilderImpl implements GraphBuilder { boolean copyEdgesWeights) { this.factory = factory; this.ibuilder = factory.indexFactory.newBuilderCopyOf(g.indexGraph(), copyVerticesWeights, copyEdgesWeights); - viMap = IndexIdMapImpl.newCopyOf(g.indexGraphVerticesMap(), null, ibuilder.vertices(), false, false); - eiMap = IndexIdMapImpl.newCopyOf(g.indexGraphEdgesMap(), null, ibuilder.edges(), true, false); + viMap = IndexIdMapImpl.newCopyOf(g.indexGraphVerticesMap(), Optional.empty(), ibuilder.vertices(), false, + false); + eiMap = IndexIdMapImpl.newCopyOf(g.indexGraphEdgesMap(), Optional.empty(), ibuilder.edges(), true, false); resetVertexAndEdgeBuilders(); } @@ -227,7 +228,7 @@ private Graph buildFromReIndexed(IndexGraphBuilder.ReIndexedGraph reIndexe IndexGraph iGraph = reIndexedGraph.graph(); Optional vReIndexing = reIndexedGraph.verticesReIndexing(); Optional eReIndexing = reIndexedGraph.edgesReIndexing(); - return new GraphImpl<>(factory, iGraph, viMap, eiMap, vReIndexing.orElse(null), eReIndexing.orElse(null)); + return new GraphImpl<>(factory, iGraph, viMap, eiMap, vReIndexing, eReIndexing); } } diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrAbstractUnindexed.java b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrAbstractUnindexed.java index 3e2cb3846a..059e95d810 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrAbstractUnindexed.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrAbstractUnindexed.java @@ -15,6 +15,8 @@ */ package com.jgalgo.graph; +import java.util.Optional; + import com.jgalgo.internal.util.JGAlgoUtils.Variant2; abstract class GraphCsrAbstractUnindexed extends GraphCsrBase { @@ -22,7 +24,7 @@ abstract class GraphCsrAbstractUnindexed extends GraphCsrBase { final int[] edgesOut; GraphCsrAbstractUnindexed(boolean directed, IndexGraphBuilderImpl builder, BuilderProcessEdges processEdges) { - super(directed, Variant2.ofB(builder), processEdges, null, true, true); + super(directed, Variant2.ofB(builder), processEdges, Optional.empty(), true, true); edgesOut = processEdges.edgesOut; for (int m = builder.edges.size(), e = 0; e < m; e++) diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrBase.java b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrBase.java index 80468d8d8f..26e44164e1 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrBase.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrBase.java @@ -42,7 +42,7 @@ abstract class GraphCsrBase extends IndexGraphBase implements ImmutableGraph { private boolean containsParallelEdgesValid; GraphCsrBase(boolean directed, Variant2 graphOrBuilder, - BuilderProcessEdges processEdges, IndexGraphBuilder.ReIndexingMap edgesReIndexing, + BuilderProcessEdges processEdges, Optional edgesReIndexing, boolean copyVerticesWeights, boolean copyEdgesWeights) { super(graphOrBuilder, false); final int n = verticesNum(graphOrBuilder); @@ -83,7 +83,7 @@ abstract class GraphCsrBase extends IndexGraphBase implements ImmutableGraph { } if (copyEdgesWeights && inputCsrGraph.isPresent()) { - assert edgesReIndexing == null; + assert edgesReIndexing.isEmpty(); edgesUserWeights = inputCsrGraph.get().edgesUserWeights; } else if (copyEdgesWeights) { @@ -94,12 +94,13 @@ abstract class GraphCsrBase extends IndexGraphBase implements ImmutableGraph { WeightsImpl.IndexImmutable.Builder edgesUserWeightsBuilder = new WeightsImpl.IndexImmutable.Builder(edges, true); - if (edgesReIndexing == null) { + if (edgesReIndexing.isEmpty()) { for (String key : edgesWeightsKeys) edgesUserWeightsBuilder.copyAndAddWeights(key, getWeights.apply(key)); } else { for (String key : edgesWeightsKeys) - edgesUserWeightsBuilder.copyAndAddWeightsReindexed(key, getWeights.apply(key), edgesReIndexing); + edgesUserWeightsBuilder.copyAndAddWeightsReindexed(key, getWeights.apply(key), + edgesReIndexing.get()); } edgesUserWeights = edgesUserWeightsBuilder.build(); diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrDirectedReindexed.java b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrDirectedReindexed.java index cc25a0f54d..41cd1fa1e0 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrDirectedReindexed.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphCsrDirectedReindexed.java @@ -25,7 +25,7 @@ class GraphCsrDirectedReindexed extends GraphCsrBase { private final int[] edgesInBegin; private GraphCsrDirectedReindexed(Variant2 graphOrBuilder, - BuilderProcessEdgesDirected processEdges, IndexGraphBuilder.ReIndexingMap edgesReIndexing, + BuilderProcessEdgesDirected processEdges, Optional edgesReIndexing, boolean copyVerticesWeights, boolean copyEdgesWeights) { super(true, graphOrBuilder, processEdges, edgesReIndexing, copyVerticesWeights, copyEdgesWeights); final int n = verticesNum(graphOrBuilder); @@ -33,7 +33,7 @@ private GraphCsrDirectedReindexed(Variant2 gr if (graphOrBuilder.contains(IndexGraph.class) && graphOrBuilder.get(IndexGraph.class) instanceof GraphCsrDirectedReindexed) { - assert edgesReIndexing == null; + assert edgesReIndexing.isEmpty(); GraphCsrDirectedReindexed g = (GraphCsrDirectedReindexed) graphOrBuilder.get(IndexGraph.class); edgesIn = g.edgesIn; edgesInBegin = g.edgesInBegin; @@ -46,10 +46,10 @@ private GraphCsrDirectedReindexed(Variant2 gr assert edgesIn.length == m; assert edgesInBegin.length == n + 1; - assert edgesReIndexing != null; + IndexGraphBuilder.ReIndexingMap edgesReIndexing0 = edgesReIndexing.get(); for (int eIdx = 0; eIdx < m; eIdx++) { int eOrig = edgesIn[eIdx]; - int eCsr = edgesReIndexing.origToReIndexed(eOrig); + int eCsr = edgesReIndexing0.origToReIndexed(eOrig); edgesIn[eIdx] = eCsr; } @@ -58,7 +58,7 @@ private GraphCsrDirectedReindexed(Variant2 gr assert g.isDirected(); for (int eCsr = 0; eCsr < m; eCsr++) { - int eOrig = edgesReIndexing.reIndexedToOrig(eCsr); + int eOrig = edgesReIndexing0.reIndexedToOrig(eCsr); setEndpoints(eCsr, g.edgeSource(eOrig), g.edgeTarget(eOrig)); } } else { @@ -66,7 +66,7 @@ private GraphCsrDirectedReindexed(Variant2 gr assert builder.isDirected(); for (int eCsr = 0; eCsr < m; eCsr++) { - int eOrig = edgesReIndexing.reIndexedToOrig(eCsr); + int eOrig = edgesReIndexing0.reIndexedToOrig(eCsr); setEndpoints(eCsr, builder.edgeSource(eOrig), builder.edgeTarget(eOrig)); } } @@ -94,7 +94,7 @@ private static IndexGraphBuilder.ReIndexedGraph newInstance( GraphCsrBase.BuilderProcessEdgesDirected processEdges = GraphCsrBase.BuilderProcessEdgesDirected.valueOf(graphOrBuilder); - IndexGraphBuilder.ReIndexingMap edgesReIndexing = null; + Optional edgesReIndexing = Optional.empty(); if (!graphOrBuilder.contains(IndexGraph.class) || !(graphOrBuilder.get(IndexGraph.class) instanceof GraphCsrDirectedReindexed)) { final int m = edgesNum(graphOrBuilder); @@ -102,12 +102,12 @@ private static IndexGraphBuilder.ReIndexedGraph newInstance( int[] edgesOrigToCsr = new int[m]; for (int eCsr = 0; eCsr < m; eCsr++) edgesOrigToCsr[edgesCsrToOrig[eCsr]] = eCsr; - edgesReIndexing = new IndexGraphBuilderImpl.ReIndexingMapImpl(edgesOrigToCsr, edgesCsrToOrig); + edgesReIndexing = Optional.of(new IndexGraphBuilderImpl.ReIndexingMapImpl(edgesOrigToCsr, edgesCsrToOrig)); } GraphCsrDirectedReindexed g = new GraphCsrDirectedReindexed(graphOrBuilder, processEdges, edgesReIndexing, copyVerticesWeights, copyEdgesWeights); - return new IndexGraphBuilderImpl.ReIndexedGraphImpl(g, Optional.empty(), Optional.ofNullable(edgesReIndexing)); + return new IndexGraphBuilderImpl.ReIndexedGraphImpl(g, Optional.empty(), edgesReIndexing); } @Override diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphFactory.java b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphFactory.java index f1b0e5e609..f16917940c 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphFactory.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphFactory.java @@ -52,14 +52,16 @@ public interface GraphFactory { * *

* An identical copy of the given graph will be created, with the same vertices and edges, without copying the - * vertices/edges weights. The returned Graph will always be modifiable, with no side affects on the original graph. + * vertices/edges weights. The returned Graph will always be mutable, with no side affects on the original graph. * *

* Differing from {@link Graph#copy()}, the capabilities of the new graph are determined by the factory * configuration, rather than copied from the given graph. Note for example that if the factory chooses to use an - * implementation that does not (have to) support self edges (if {@link #allowSelfEdges(boolean)} was not called - * with {@code true}), attempting to create a copy of a graph that does contains self edges will result in an - * exception. + * implementation that does not support self edges (if {@link #allowSelfEdges(boolean)} was not called with + * {@code true}), attempting to create a copy of a graph that does contains self edges will result in an exception. + * + *

+ * For an immutable copy of a graph, see {@link #newImmutableCopyOf(Graph, boolean, boolean)}. * * @param g the original graph to copy * @return an identical copy of the given graph, with the same vertices and edges, without the original graph @@ -74,14 +76,16 @@ default Graph newCopyOf(Graph g) { * *

* An identical copy of the given graph will be created, with the same vertices and edges, with/without copying the - * vertices/edges weights. The returned Graph will always be modifiable, with no side affects on the original graph. + * vertices/edges weights. The returned Graph will always be mutable, with no side affects on the original graph. * *

* Differing from {@link Graph#copy(boolean, boolean)}, the capabilities of the new graph are determined by the * factory configuration, rather than copied from the given graph. Note for example that if the factory chooses to - * use an implementation that does not (have to) support self edges (if {@link #allowSelfEdges(boolean)} was not - * called with {@code true}), attempting to create a copy of a graph that does contains self edges will result in an - * exception. + * use an implementation that does not support self edges (if {@link #allowSelfEdges(boolean)} was not called with + * {@code true}), attempting to create a copy of a graph that does contains self edges will result in an exception. + * + *

+ * For an immutable copy of a graph, see {@link #newImmutableCopyOf(Graph, boolean, boolean)}. * * @param g the original graph to copy * @param copyVerticesWeights if {@code true}, the weights of the vertices will be copied to the new graph @@ -91,6 +95,55 @@ default Graph newCopyOf(Graph g) { */ Graph newCopyOf(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights); + /** + * Create a new immutable copy of a given graph, with the same vertices and edges, without copying weights. + * + *

+ * An identical copy of the given graph will be created, with the same vertices and edges, without copying the + * vertices/edges weights. The returned Graph will be immutable, with no side affects on the original graph. + * + *

+ * Differing from {@link Graph#immutableCopy()}, the capabilities of the new graph are determined by the factory + * configuration, rather than copied from the given graph. Note for example that if the factory chooses to use an + * implementation that does not support self edges (if {@link #allowSelfEdges(boolean)} was not called with + * {@code true}), attempting to create a copy of a graph that does contains self edges will result in an exception. + * + *

+ * For a mutable copy of a graph, see {@link #newCopyOf(Graph, boolean, boolean)}. + * + * @param g the original graph to copy + * @return an identical immutable copy of the given graph, with the same vertices and edges, without the original + * graph weights + */ + default Graph newImmutableCopyOf(Graph g) { + return newImmutableCopyOf(g, false, false); + } + + /** + * Create a new immutable copy of a given graph, with the same vertices and edges, with/without copying weights. + * + *

+ * An identical copy of the given graph will be created, with the same vertices and edges, with/without copying the + * vertices/edges weights. The returned Graph will be immutable, with no side affects on the original graph. + * + *

+ * Differing from {@link Graph#immutableCopy(boolean, boolean)}, the capabilities of the new graph are determined by + * the factory configuration, rather than copied from the given graph. Note for example that if the factory chooses + * to use an implementation that does not support self edges (if {@link #allowSelfEdges(boolean)} was not called + * with {@code true}), attempting to create a copy of a graph that does contains self edges will result in an + * exception. + * + *

+ * For a mutable copy of a graph, see {@link #newCopyOf(Graph, boolean, boolean)}. + * + * @param g the original graph to copy + * @param copyVerticesWeights if {@code true}, the weights of the vertices will be copied to the new graph + * @param copyEdgesWeights if {@code true}, the weights of the edges will be copied to the new graph + * @return an identical immutable copy of the given graph, with the same vertices and edges, + * without the original graph weights + */ + Graph newImmutableCopyOf(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights); + /** * Create a new graph builder with the factory parameters. * diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphFactoryImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphFactoryImpl.java index ff7cce915c..fa76ab8e53 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphFactoryImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphFactoryImpl.java @@ -15,6 +15,7 @@ */ package com.jgalgo.graph; +import java.util.Optional; import java.util.function.Supplier; class GraphFactoryImpl implements GraphFactory { @@ -34,7 +35,22 @@ public Graph newGraph() { @Override public Graph newCopyOf(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights) { - return new GraphImpl<>(this, g, copyVerticesWeights, copyEdgesWeights); + IndexGraph ig = indexFactory.newCopyOf(g.indexGraph(), copyVerticesWeights, copyEdgesWeights); + IndexIdMap viMap = g.indexGraphVerticesMap(); + IndexIdMap eiMap = g.indexGraphEdgesMap(); + return new GraphImpl<>(this, ig, viMap, eiMap, Optional.empty(), Optional.empty()); + } + + @Override + public Graph newImmutableCopyOf(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights) { + IndexGraphBuilder.ReIndexedGraph reIndexedGraph = indexFactory.immutableImpl() + .newCopyOfWithReIndex(g.indexGraph(), true, true, copyVerticesWeights, copyEdgesWeights); + IndexIdMap viMap = g.indexGraphVerticesMap(); + IndexIdMap eiMap = g.indexGraphEdgesMap(); + IndexGraph iGraph = reIndexedGraph.graph(); + Optional vReIndexing = reIndexedGraph.verticesReIndexing(); + Optional eReIndexing = reIndexedGraph.edgesReIndexing(); + return new GraphImpl<>(this, iGraph, viMap, eiMap, vReIndexing, eReIndexing); } @Override diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphImpl.java index e6606142a2..10384c2f3d 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/GraphImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/GraphImpl.java @@ -20,6 +20,7 @@ import java.util.IdentityHashMap; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import com.jgalgo.graph.Graphs.ImmutableGraph; import it.unimi.dsi.fastutil.ints.AbstractIntSet; @@ -46,7 +47,8 @@ class GraphImpl extends AbstractGraph { } GraphImpl(GraphFactoryImpl factory, IndexGraph indexGraph, IndexIdMap viMap, IndexIdMap eiMap, - IndexGraphBuilder.ReIndexingMap vReIndexing, IndexGraphBuilder.ReIndexingMap eReIndexing) { + Optional vReIndexing, + Optional eReIndexing) { this.indexGraph = Objects.requireNonNull(indexGraph); boolean immutable = this.indexGraph instanceof ImmutableGraph; this.viMap = IndexIdMapImpl.newCopyOf(viMap, vReIndexing, this.indexGraph.vertices(), false, immutable); @@ -59,12 +61,6 @@ class GraphImpl extends AbstractGraph { edgeBuilder = factory.edgeFactory != null ? factory.edgeFactory.get() : null; } - /* copy constructor */ - GraphImpl(GraphFactoryImpl factory, Graph orig, boolean copyVerticesWeights, boolean copyEdgesWeights) { - this(factory, factory.indexFactory.newCopyOf(orig.indexGraph(), copyVerticesWeights, copyEdgesWeights), - orig.indexGraphVerticesMap(), orig.indexGraphEdgesMap(), null, null); - } - @Override public IndexGraph indexGraph() { return indexGraph; diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/Graphs.java b/jgalgo-core/src/main/java/com/jgalgo/graph/Graphs.java index 6db2ce3241..8f4781d8f3 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/Graphs.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/Graphs.java @@ -46,8 +46,16 @@ public class Graphs { private Graphs() {} - @SuppressWarnings("unchecked") static Graph copy(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights) { + return factoryForCopy(g).newCopyOf(g, copyVerticesWeights, copyEdgesWeights); + } + + static Graph immutableCopy(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights) { + return factoryForCopy(g).newImmutableCopyOf(g, copyVerticesWeights, copyEdgesWeights); + } + + @SuppressWarnings("unchecked") + private static GraphFactory factoryForCopy(Graph g) { GraphFactory factory; if (g instanceof IndexGraph) { factory = (GraphFactory) IndexGraphFactory.newInstance(g.isDirected()); @@ -60,7 +68,7 @@ static Graph copy(Graph g, boolean copyVerticesWeights, boole factory.allowSelfEdges(); if (g.isAllowParallelEdges()) factory.allowParallelEdges(); - return factory.newCopyOf(g, copyVerticesWeights, copyEdgesWeights); + return factory; } /** diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraph.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraph.java index ec9d80b2aa..8c0d673ec3 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraph.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraph.java @@ -539,11 +539,7 @@ default IndexGraph immutableCopy() { @Override default IndexGraph immutableCopy(boolean copyVerticesWeights, boolean copyEdgesWeights) { - if (isDirected()) { - return new GraphCsrDirected(this, copyVerticesWeights, copyEdgesWeights); - } else { - return new GraphCsrUndirected(this, copyVerticesWeights, copyEdgesWeights); - } + return (IndexGraph) IntGraph.super.immutableCopy(copyVerticesWeights, copyEdgesWeights); } @Override diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphBuilderImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphBuilderImpl.java index 3617b42bfb..c2f86fb5f3 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphBuilderImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphBuilderImpl.java @@ -34,8 +34,8 @@ class IndexGraphBuilderImpl implements IndexGraphBuilder { final WeightsImpl.IndexMutable.Manager verticesUserWeights; final WeightsImpl.IndexMutable.Manager edgesUserWeights; - IndexGraphFactoryImpl.Impl mutableImpl; - IndexGraphFactoryImpl.Impl immutableImpl; + IndexGraphFactoryImpl.MutableImpl mutableImpl; + IndexGraphFactoryImpl.ImmutableImpl immutableImpl; IndexGraphBuilderImpl(boolean directed) { this.directed = directed; @@ -97,11 +97,11 @@ private void setDefaultImpls() { immutableImpl = new IndexGraphFactoryImpl(directed).immutableImpl(); } - void setMutableImpl(IndexGraphFactoryImpl.Impl mutableImpl) { + void setMutableImpl(IndexGraphFactoryImpl.MutableImpl mutableImpl) { this.mutableImpl = Objects.requireNonNull(mutableImpl); } - void setImmutableImpl(IndexGraphFactoryImpl.Impl immutableImpl) { + void setImmutableImpl(IndexGraphFactoryImpl.ImmutableImpl immutableImpl) { this.immutableImpl = Objects.requireNonNull(immutableImpl); } @@ -312,16 +312,12 @@ public IndexGraph buildMutable() { @Override public IndexGraphBuilder.ReIndexedGraph reIndexAndBuild(boolean reIndexVertices, boolean reIndexEdges) { - if (directed && reIndexEdges) { - return GraphCsrDirectedReindexed.newInstance(this); - } else { - return new ReIndexedGraphImpl(build(), Optional.empty(), Optional.empty()); - } + return immutableImpl.newFromBuilderWithReIndex(this, reIndexVertices, reIndexEdges); } @Override public IndexGraphBuilder.ReIndexedGraph reIndexAndBuildMutable(boolean reIndexVertices, boolean reIndexEdges) { - return new ReIndexedGraphImpl(buildMutable(), Optional.empty(), Optional.empty()); + return mutableImpl.newFromBuilderWithReIndex(this, reIndexVertices, reIndexEdges); } @Override diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphFactory.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphFactory.java index 91bd6f0d42..c6b485f241 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphFactory.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphFactory.java @@ -52,6 +52,14 @@ default IndexGraph newCopyOf(Graph g) { @Override IndexGraph newCopyOf(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights); + @Override + default IndexGraph newImmutableCopyOf(Graph g) { + return (IndexGraph) IntGraphFactory.super.newImmutableCopyOf(g); + } + + @Override + IndexGraph newImmutableCopyOf(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights); + @Override IndexGraphBuilder newBuilder(); diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphFactoryImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphFactoryImpl.java index 4d28d0d6f6..5cebce4e88 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphFactoryImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexGraphFactoryImpl.java @@ -16,6 +16,9 @@ package com.jgalgo.graph; import java.util.EnumSet; +import java.util.Optional; +import com.jgalgo.graph.IndexGraphBuilder.ReIndexedGraph; +import com.jgalgo.graph.IndexGraphBuilderImpl.ReIndexedGraphImpl; import it.unimi.dsi.fastutil.booleans.Boolean2ObjectFunction; class IndexGraphFactoryImpl implements IndexGraphFactory { @@ -45,6 +48,15 @@ public IndexGraph newCopyOf(Graph g, boolean copyVerticesWeigh return mutableImpl().newCopyOf((IndexGraph) g, copyVerticesWeights, copyEdgesWeights); } + @Override + public IndexGraph newImmutableCopyOf(Graph g, boolean copyVerticesWeights, + boolean copyEdgesWeights) { + if (directed != g.isDirected()) + throw new IllegalArgumentException("graph is " + (g.isDirected() ? "directed" : "undirected") + + " while factory is " + (directed ? "directed" : "undirected")); + return immutableImpl().newCopyOf((IndexGraph) g, copyVerticesWeights, copyEdgesWeights); + } + @Override public IndexGraphBuilder newBuilder() { IndexGraphBuilderImpl builder = new IndexGraphBuilderImpl(directed); @@ -62,7 +74,7 @@ public IndexGraphBuilder newBuilderCopyOf(Graph g, boolean cop return builder; } - static interface Impl { + static interface MutableImpl { IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum); @@ -70,11 +82,16 @@ static interface Impl { IndexGraph newFromBuilder(IndexGraphBuilderImpl builder); + default IndexGraphBuilder.ReIndexedGraph newFromBuilderWithReIndex(IndexGraphBuilderImpl builder, + boolean reIndexVertices, boolean reIndexEdges) { + return new ReIndexedGraphImpl(newFromBuilder(builder), Optional.empty(), Optional.empty()); + } + } - Impl mutableImpl() { - Boolean2ObjectFunction arrayImplFactory = selfEdges -> { - return directed ? new Impl() { + MutableImpl mutableImpl() { + Boolean2ObjectFunction arrayImplFactory = selfEdges -> { + return directed ? new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -90,7 +107,7 @@ public IndexGraph newCopyOf(IndexGraph graph, boolean copyVerticesWeights, boole public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { return new GraphArrayDirected(selfEdges, builder); } - } : new Impl() { + } : new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -108,11 +125,11 @@ public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { } }; }; - Impl arrayImpl = arrayImplFactory.get(false); - Impl arrayImplWithSelfEdges = arrayImplFactory.get(true); + MutableImpl arrayImpl = arrayImplFactory.get(false); + MutableImpl arrayImplWithSelfEdges = arrayImplFactory.get(true); - Boolean2ObjectFunction linkedImplFactory = selfEdges -> { - return directed ? new Impl() { + Boolean2ObjectFunction linkedImplFactory = selfEdges -> { + return directed ? new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -128,7 +145,7 @@ public IndexGraph newCopyOf(IndexGraph graph, boolean copyVerticesWeights, boole public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { return new GraphLinkedDirected(selfEdges, builder); } - } : new Impl() { + } : new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -146,10 +163,10 @@ public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { } }; }; - Impl linkedImpl = linkedImplFactory.get(false); - Impl linkedImplWithSelfEdges = linkedImplFactory.get(true); - Boolean2ObjectFunction linkedPtrImplFactory = selfEdges -> { - return directed ? new Impl() { + MutableImpl linkedImpl = linkedImplFactory.get(false); + MutableImpl linkedImplWithSelfEdges = linkedImplFactory.get(true); + Boolean2ObjectFunction linkedPtrImplFactory = selfEdges -> { + return directed ? new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -165,7 +182,7 @@ public IndexGraph newCopyOf(IndexGraph graph, boolean copyVerticesWeights, boole public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { return new GraphLinkedPtrDirected(selfEdges, builder); } - } : new Impl() { + } : new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -183,10 +200,10 @@ public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { } }; }; - Impl linkedPtrImpl = linkedPtrImplFactory.get(false); - Impl linkedPtrImplWithSelfEdges = linkedPtrImplFactory.get(true); - Boolean2ObjectFunction hashtableImplFactory = selfEdges -> { - return directed ? new Impl() { + MutableImpl linkedPtrImpl = linkedPtrImplFactory.get(false); + MutableImpl linkedPtrImplWithSelfEdges = linkedPtrImplFactory.get(true); + Boolean2ObjectFunction hashtableImplFactory = selfEdges -> { + return directed ? new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -202,7 +219,7 @@ public IndexGraph newCopyOf(IndexGraph graph, boolean copyVerticesWeights, boole public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { return new GraphHashmapDirected(selfEdges, builder); } - } : new Impl() { + } : new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -220,10 +237,10 @@ public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { } }; }; - Impl hashtableImpl = hashtableImplFactory.get(false); - Impl hashtableImplWithSelfEdges = hashtableImplFactory.get(true); - Boolean2ObjectFunction hashtableMultiImplFactory = selfEdges -> { - return directed ? new Impl() { + MutableImpl hashtableImpl = hashtableImplFactory.get(false); + MutableImpl hashtableImplWithSelfEdges = hashtableImplFactory.get(true); + Boolean2ObjectFunction hashtableMultiImplFactory = selfEdges -> { + return directed ? new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -239,7 +256,7 @@ public IndexGraph newCopyOf(IndexGraph graph, boolean copyVerticesWeights, boole public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { return new GraphHashmapMultiDirected(selfEdges, builder); } - } : new Impl() { + } : new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -257,10 +274,10 @@ public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { } }; }; - Impl hashtableMultiImpl = hashtableMultiImplFactory.get(false); - Impl hashtableMultiImplWithSelfEdges = hashtableMultiImplFactory.get(true); - Boolean2ObjectFunction matrixImplFactory = selfEdges -> { - return directed ? new Impl() { + MutableImpl hashtableMultiImpl = hashtableMultiImplFactory.get(false); + MutableImpl hashtableMultiImplWithSelfEdges = hashtableMultiImplFactory.get(true); + Boolean2ObjectFunction matrixImplFactory = selfEdges -> { + return directed ? new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -276,7 +293,7 @@ public IndexGraph newCopyOf(IndexGraph graph, boolean copyVerticesWeights, boole public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { return new GraphMatrixDirected(selfEdges, builder); } - } : new Impl() { + } : new MutableImpl() { @Override public IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { @@ -294,8 +311,8 @@ public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { } }; }; - Impl matrixImpl = matrixImplFactory.get(false); - Impl matrixImplWithSelfEdges = matrixImplFactory.get(true); + MutableImpl matrixImpl = matrixImplFactory.get(false); + MutableImpl matrixImplWithSelfEdges = matrixImplFactory.get(true); if (impl != null) { switch (impl) { @@ -346,38 +363,81 @@ public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { } } - private static interface ImplImmutable extends Impl { - @Override - default IndexGraph newGraph(int expectedVerticesNum, int expectedEdgesNum) { - throw new UnsupportedOperationException(); - } + static interface ImmutableImpl { + + IndexGraph newCopyOf(IndexGraph graph, boolean copyVerticesWeights, boolean copyEdgesWeights); + + IndexGraph newFromBuilder(IndexGraphBuilderImpl builder); + + IndexGraphBuilder.ReIndexedGraph newCopyOfWithReIndex(IndexGraph graph, boolean reIndexVertices, + boolean reIndexEdges, boolean copyVerticesWeights, boolean copyEdgesWeights); + + IndexGraphBuilder.ReIndexedGraph newFromBuilderWithReIndex(IndexGraphBuilderImpl builder, + boolean reIndexVertices, boolean reIndexEdges); + } - Impl immutableImpl() { - Impl csrImpl = directed ? new ImplImmutable() { + ImmutableImpl immutableImpl() { + ImmutableImpl csrImpl = directed ? new ImmutableImpl() { @Override public IndexGraph newCopyOf(IndexGraph graph, boolean copyVerticesWeights, boolean copyEdgesWeights) { return new GraphCsrDirected(graph, copyVerticesWeights, copyEdgesWeights); } + @Override + public IndexGraphBuilder.ReIndexedGraph newCopyOfWithReIndex(IndexGraph graph, boolean reIndexVertices, + boolean reIndexEdges, boolean copyVerticesWeights, boolean copyEdgesWeights) { + if (reIndexEdges) { + return GraphCsrDirectedReindexed.newInstance(graph, copyVerticesWeights, copyEdgesWeights); + } else { + return new ReIndexedGraphImpl(newCopyOf(graph, copyVerticesWeights, copyEdgesWeights), + Optional.empty(), Optional.empty()); + } + } + @Override public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { GraphCsrBase.BuilderProcessEdgesDirected processEdges = GraphCsrBase.BuilderProcessEdgesDirected.valueOf(builder); return new GraphCsrDirected(builder, processEdges); } - } : new ImplImmutable() { + + @Override + public ReIndexedGraph newFromBuilderWithReIndex(IndexGraphBuilderImpl builder, boolean reIndexVertices, + boolean reIndexEdges) { + if (reIndexEdges) { + return GraphCsrDirectedReindexed.newInstance(builder); + } else { + return new ReIndexedGraphImpl(newFromBuilder(builder), Optional.empty(), Optional.empty()); + } + } + } : new ImmutableImpl() { @Override public IndexGraph newCopyOf(IndexGraph graph, boolean copyVerticesWeights, boolean copyEdgesWeights) { return new GraphCsrUndirected(graph, copyVerticesWeights, copyEdgesWeights); } + @Override + public IndexGraphBuilder.ReIndexedGraph newCopyOfWithReIndex(IndexGraph graph, boolean reIndexVertices, + boolean reIndexEdges, boolean copyVerticesWeights, boolean copyEdgesWeights) { + /* no re-indexing for undirected graph */ + return new ReIndexedGraphImpl(newCopyOf(graph, copyVerticesWeights, copyEdgesWeights), Optional.empty(), + Optional.empty()); + } + @Override public IndexGraph newFromBuilder(IndexGraphBuilderImpl builder) { GraphCsrBase.BuilderProcessEdgesUndirected processEdges = GraphCsrBase.BuilderProcessEdgesUndirected.valueOf(builder); return new GraphCsrUndirected(builder, processEdges); } + + @Override + public ReIndexedGraph newFromBuilderWithReIndex(IndexGraphBuilderImpl builder, boolean reIndexVertices, + boolean reIndexEdges) { + /* no re-indexing for undirected graph */ + return new ReIndexedGraphImpl(newFromBuilder(builder), Optional.empty(), Optional.empty()); + } }; return csrImpl; } @@ -439,5 +499,4 @@ public IndexGraphFactory setOption(String key, Object value) { } return this; } - } diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexIdMapImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexIdMapImpl.java index 27d826ae23..27096cabd4 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexIdMapImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexIdMapImpl.java @@ -18,6 +18,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Objects; +import java.util.Optional; import java.util.Set; import com.jgalgo.internal.util.Assertions; import it.unimi.dsi.fastutil.ints.IntSet; @@ -46,11 +47,11 @@ private IndexIdMapImpl(IntSet indicesSet, boolean isEdges, int expectedSize) { immutable = false; } - private IndexIdMapImpl(IndexIdMap orig, IndexGraphBuilder.ReIndexingMap reIndexing, IntSet indicesSet, + private IndexIdMapImpl(IndexIdMap orig, Optional reIndexing, IntSet indicesSet, boolean isEdges, boolean immutable) { this.indicesSet = indicesSet; int elementsSize = this.indicesSet.size(); - if (orig instanceof IndexIdMapImpl && reIndexing == null) { + if (orig instanceof IndexIdMapImpl && reIndexing.isEmpty()) { IndexIdMapImpl orig0 = (IndexIdMapImpl) orig; idToIndex = new Object2IntOpenHashMap<>(orig0.idToIndex); idToIndex.defaultReturnValue(-1); @@ -63,7 +64,7 @@ private IndexIdMapImpl(IndexIdMap orig, IndexGraphBuilder.ReIndexingMap reInd indexToId = ObjectArrays.DEFAULT_EMPTY_ARRAY; } else { indexToId = new Object[elementsSize]; - if (reIndexing == null) { + if (reIndexing.isEmpty()) { for (int idx : this.indicesSet) { K id = orig.indexToId(idx); if (id == null) @@ -76,8 +77,9 @@ private IndexIdMapImpl(IndexIdMap orig, IndexGraphBuilder.ReIndexingMap reInd } } else { + IndexGraphBuilder.ReIndexingMap reIndexing0 = reIndexing.get(); for (int idx : this.indicesSet) { - K id = orig.indexToId(reIndexing.reIndexedToOrig(idx)); + K id = orig.indexToId(reIndexing0.reIndexedToOrig(idx)); if (id == null) throw new NullPointerException("null id"); indexToId[idx] = id; @@ -97,7 +99,7 @@ static IndexIdMapImpl newEmpty(IntSet indicesSet, boolean isEdges, int ex return new IndexIdMapImpl<>(indicesSet, isEdges, expectedSize); } - static IndexIdMapImpl newCopyOf(IndexIdMap orig, IndexGraphBuilder.ReIndexingMap reIndexing, + static IndexIdMapImpl newCopyOf(IndexIdMap orig, Optional reIndexing, IntSet indicesSet, boolean isEdges, boolean immutable) { return new IndexIdMapImpl<>(orig, reIndexing, indicesSet, isEdges, immutable); } diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexIntIdMapImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexIntIdMapImpl.java index 4ddefdae1f..b529f3c046 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IndexIntIdMapImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IndexIntIdMapImpl.java @@ -17,6 +17,7 @@ import java.util.Arrays; import java.util.Collection; +import java.util.Optional; import com.jgalgo.internal.util.Assertions; import it.unimi.dsi.fastutil.ints.AbstractIntSet; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; @@ -45,11 +46,11 @@ private IndexIntIdMapImpl(IntSet indicesSet, boolean isEdges, int expectedSize) immutable = false; } - private IndexIntIdMapImpl(IndexIdMap orig, IndexGraphBuilder.ReIndexingMap reIndexing, IntSet indicesSet, - boolean isEdges, boolean immutable) { + private IndexIntIdMapImpl(IndexIdMap orig, Optional reIndexing, + IntSet indicesSet, boolean isEdges, boolean immutable) { this.indicesSet = indicesSet; int elementsSize = this.indicesSet.size(); - if (orig instanceof IndexIntIdMapImpl && reIndexing == null) { + if (orig instanceof IndexIntIdMapImpl && reIndexing.isEmpty()) { IndexIntIdMapImpl orig0 = (IndexIntIdMapImpl) orig; idToIndex = new Int2IntOpenHashMap(orig0.idToIndex); idToIndex.defaultReturnValue(-1); @@ -62,7 +63,7 @@ private IndexIntIdMapImpl(IndexIdMap orig, IndexGraphBuilder.ReIndexing indexToId = IntArrays.DEFAULT_EMPTY_ARRAY; } else { indexToId = new int[elementsSize]; - if (reIndexing == null) { + if (reIndexing.isEmpty()) { for (int idx = 0; idx < elementsSize; idx++) { int id = orig.indexToId(idx).intValue(); if (id < 0) @@ -75,8 +76,9 @@ private IndexIntIdMapImpl(IndexIdMap orig, IndexGraphBuilder.ReIndexing } } else { + IndexGraphBuilder.ReIndexingMap reIndexing0 = reIndexing.get(); for (int idx = 0; idx < elementsSize; idx++) { - int id = orig.indexToId(reIndexing.reIndexedToOrig(idx)).intValue(); + int id = orig.indexToId(reIndexing0.reIndexedToOrig(idx)).intValue(); if (id < 0) throw new IllegalArgumentException("negative id: " + id); indexToId[idx] = id; @@ -96,7 +98,7 @@ static IndexIntIdMapImpl newEmpty(IntSet indicesSet, boolean isEdges, int expect return new IndexIntIdMapImpl(indicesSet, isEdges, expectedSize); } - static IndexIntIdMapImpl newCopyOf(IndexIdMap orig, IndexGraphBuilder.ReIndexingMap reIndexing, + static IndexIntIdMapImpl newCopyOf(IndexIdMap orig, Optional reIndexing, IntSet indicesSet, boolean isEdges, boolean immutable) { return new IndexIntIdMapImpl(orig, reIndexing, indicesSet, isEdges, immutable); } diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraph.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraph.java index 75115b26ca..dfe619fde0 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraph.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraph.java @@ -18,7 +18,6 @@ import java.util.Collection; import java.util.Map; -import java.util.Optional; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.IntCollection; import it.unimi.dsi.fastutil.ints.IntSet; @@ -724,23 +723,7 @@ default IntGraph immutableCopy() { @Override default IntGraph immutableCopy(boolean copyVerticesWeights, boolean copyEdgesWeights) { - IndexIntIdMap viMap = indexGraphVerticesMap(); - IndexIntIdMap eiMap = indexGraphEdgesMap(); - /* create a new factory with no vertex and edge builders */ - IntGraphFactoryImpl factory = new IntGraphFactoryImpl(isDirected()); - factory.setVertexBuilder(null); - factory.setEdgeBuilder(null); - if (isDirected()) { - IndexGraphBuilder.ReIndexedGraph reIndexedGraph = - GraphCsrDirectedReindexed.newInstance(indexGraph(), copyVerticesWeights, copyEdgesWeights); - IndexGraph iGraph = reIndexedGraph.graph(); - Optional vReIndexing = reIndexedGraph.verticesReIndexing(); - Optional eReIndexing = reIndexedGraph.edgesReIndexing(); - return new IntGraphImpl(factory, iGraph, viMap, eiMap, vReIndexing.orElse(null), eReIndexing.orElse(null)); - } else { - IndexGraph iGraph = new GraphCsrUndirected(indexGraph(), copyVerticesWeights, copyEdgesWeights); - return new IntGraphImpl(factory, iGraph, viMap, eiMap, null, null); - } + return (IntGraph) Graph.super.immutableCopy(copyVerticesWeights, copyEdgesWeights); } @Override diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphBuilderImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphBuilderImpl.java index ea548ba781..9138f51eca 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphBuilderImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphBuilderImpl.java @@ -47,8 +47,9 @@ class IntGraphBuilderImpl implements IntGraphBuilder { boolean copyEdgesWeights) { this.factory = factory; this.ibuilder = factory.indexFactory.newBuilderCopyOf(g.indexGraph(), copyVerticesWeights, copyEdgesWeights); - viMap = IndexIntIdMapImpl.newCopyOf(g.indexGraphVerticesMap(), null, ibuilder.vertices(), false, false); - eiMap = IndexIntIdMapImpl.newCopyOf(g.indexGraphEdgesMap(), null, ibuilder.edges(), true, false); + viMap = IndexIntIdMapImpl.newCopyOf(g.indexGraphVerticesMap(), Optional.empty(), ibuilder.vertices(), false, + false); + eiMap = IndexIntIdMapImpl.newCopyOf(g.indexGraphEdgesMap(), Optional.empty(), ibuilder.edges(), true, false); resetVertexAndEdgeBuilders(); } @@ -239,7 +240,7 @@ private IntGraph buildFromReIndexed(IndexGraphBuilder.ReIndexedGraph reIndexedGr IndexGraph iGraph = reIndexedGraph.graph(); Optional vReIndexing = reIndexedGraph.verticesReIndexing(); Optional eReIndexing = reIndexedGraph.edgesReIndexing(); - return new IntGraphImpl(factory, iGraph, viMap, eiMap, vReIndexing.orElse(null), eReIndexing.orElse(null)); + return new IntGraphImpl(factory, iGraph, viMap, eiMap, vReIndexing, eReIndexing); } } diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphFactory.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphFactory.java index 4942d0308e..bbd25dde39 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphFactory.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphFactory.java @@ -52,6 +52,14 @@ default IntGraph newCopyOf(Graph g) { @Override IntGraph newCopyOf(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights); + @Override + default IntGraph newImmutableCopyOf(Graph g) { + return (IntGraph) GraphFactory.super.newImmutableCopyOf(g); + } + + @Override + IntGraph newImmutableCopyOf(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights); + @Override IntGraphBuilder newBuilder(); diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphFactoryImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphFactoryImpl.java index e741c5336e..3764aa68d8 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphFactoryImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphFactoryImpl.java @@ -16,6 +16,7 @@ package com.jgalgo.graph; import java.util.Objects; +import java.util.Optional; import java.util.function.Supplier; class IntGraphFactoryImpl implements IntGraphFactory { @@ -35,7 +36,23 @@ public IntGraph newGraph() { @Override public IntGraph newCopyOf(Graph g, boolean copyVerticesWeights, boolean copyEdgesWeights) { - return new IntGraphImpl(this, g, copyVerticesWeights, copyEdgesWeights); + IndexGraph ig = indexFactory.newCopyOf(g.indexGraph(), copyVerticesWeights, copyEdgesWeights); + IndexIdMap viMap = g.indexGraphVerticesMap(); + IndexIdMap eiMap = g.indexGraphEdgesMap(); + return new IntGraphImpl(this, ig, viMap, eiMap, Optional.empty(), Optional.empty()); + } + + @Override + public IntGraph newImmutableCopyOf(Graph g, boolean copyVerticesWeights, + boolean copyEdgesWeights) { + IndexGraphBuilder.ReIndexedGraph reIndexedGraph = indexFactory.immutableImpl() + .newCopyOfWithReIndex(g.indexGraph(), true, true, copyVerticesWeights, copyEdgesWeights); + IndexIdMap viMap = g.indexGraphVerticesMap(); + IndexIdMap eiMap = g.indexGraphEdgesMap(); + IndexGraph iGraph = reIndexedGraph.graph(); + Optional vReIndexing = reIndexedGraph.verticesReIndexing(); + Optional eReIndexing = reIndexedGraph.edgesReIndexing(); + return new IntGraphImpl(this, iGraph, viMap, eiMap, vReIndexing, eReIndexing); } @Override @@ -130,5 +147,4 @@ public IntGraphFactory setOption(String key, Object value) { indexFactory.setOption(key, value); return this; } - } diff --git a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphImpl.java b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphImpl.java index 5c9cb28bcd..3e1221a265 100644 --- a/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphImpl.java +++ b/jgalgo-core/src/main/java/com/jgalgo/graph/IntGraphImpl.java @@ -19,6 +19,7 @@ import java.util.Collection; import java.util.IdentityHashMap; import java.util.Map; +import java.util.Optional; import java.util.Set; import com.jgalgo.graph.Graphs.ImmutableGraph; import it.unimi.dsi.fastutil.ints.AbstractIntSet; @@ -46,8 +47,8 @@ class IntGraphImpl extends AbstractGraph implements IntGraph { } IntGraphImpl(IntGraphFactoryImpl factory, IndexGraph indexGraph, IndexIdMap viMap, - IndexIdMap eiMap, IndexGraphBuilder.ReIndexingMap vReIndexing, - IndexGraphBuilder.ReIndexingMap eReIndexing) { + IndexIdMap eiMap, Optional vReIndexing, + Optional eReIndexing) { this.indexGraph = indexGraph; boolean immutable = this.indexGraph instanceof ImmutableGraph; this.viMap = IndexIntIdMapImpl.newCopyOf(viMap, vReIndexing, this.indexGraph.vertices(), false, immutable); @@ -60,13 +61,6 @@ class IntGraphImpl extends AbstractGraph implements IntGraph { edgeBuilder = factory.edgeFactory != null ? factory.edgeFactory.get() : null; } - /* copy constructor */ - IntGraphImpl(IntGraphFactoryImpl factory, Graph orig, boolean copyVerticesWeights, - boolean copyEdgesWeights) { - this(factory, factory.indexFactory.newCopyOf(orig.indexGraph(), copyVerticesWeights, copyEdgesWeights), - orig.indexGraphVerticesMap(), orig.indexGraphEdgesMap(), null, null); - } - @Override public IndexGraph indexGraph() { return indexGraph; diff --git a/jgalgo-core/src/test/java/com/jgalgo/graph/GraphFactoryTest.java b/jgalgo-core/src/test/java/com/jgalgo/graph/GraphFactoryTest.java index 3970a61c09..0e851937fc 100644 --- a/jgalgo-core/src/test/java/com/jgalgo/graph/GraphFactoryTest.java +++ b/jgalgo-core/src/test/java/com/jgalgo/graph/GraphFactoryTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import com.jgalgo.internal.util.TestBase; import it.unimi.dsi.fastutil.ints.IntSet; @@ -39,6 +40,10 @@ public void newCopyOf() { Graph g2 = factory.newCopyOf(g1); assertEquals(g1, g2); + + /* check mutable */ + g2.addVertex(100); + assertTrue(g2.vertices().contains(100)); }); foreachBoolConfig(directed -> { GraphFactory factory = GraphFactory.newInstance(directed); @@ -72,6 +77,42 @@ public void newCopyOf() { }); } + @SuppressWarnings("boxing") + @Test + public void newImmutableCopyOf() { + foreachBoolConfig(directed -> { + GraphFactory factory = GraphFactory.newInstance(directed); + + Graph g1 = factory.newGraph(); + g1.addVertices(range(10, 20)); + g1.addEdge(10, 11, 5); + g1.addEdge(11, 12, 6); + + Graph g2 = factory.newImmutableCopyOf(g1); + assertEquals(g1, g2); + + /* check immutable */ + assertThrows(UnsupportedOperationException.class, () -> g2.addVertex(100)); + }); + foreachBoolConfig(directed -> { + GraphFactory factory = GraphFactory.newInstance(directed); + + Graph g1 = factory.newGraph(); + g1.addVertices(range(10, 20)); + g1.addEdge(10, 11, 5); + g1.addEdge(11, 12, 6); + WeightsDouble weights1 = g1.addEdgesWeights("weights", double.class); + weights1.set(5, 1.0); + weights1.set(6, 2.0); + + Graph g2 = factory.newImmutableCopyOf(g1, true, true); + assertEquals(g1, g2); + + Graph g3 = factory.newImmutableCopyOf(g1, false, false); + assertNotEquals(g1, g3); + }); + } + @Test public void setDirected() { foreachBoolConfig(directed -> { diff --git a/jgalgo-core/src/test/java/com/jgalgo/graph/IndexGraphFactoryTest.java b/jgalgo-core/src/test/java/com/jgalgo/graph/IndexGraphFactoryTest.java index de803cb1c2..17cf343bbe 100644 --- a/jgalgo-core/src/test/java/com/jgalgo/graph/IndexGraphFactoryTest.java +++ b/jgalgo-core/src/test/java/com/jgalgo/graph/IndexGraphFactoryTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import com.jgalgo.internal.util.TestBase; @@ -37,6 +38,10 @@ public void newCopyOf() { IndexGraph g2 = factory.newCopyOf(g1); assertEquals(g1, g2); + + /* check mutable */ + int v = g2.addVertexInt(); + assertTrue(g2.vertices().contains(v)); }); foreachBoolConfig(directed -> { IndexGraphFactory factory = IndexGraphFactory.newInstance(directed); @@ -62,6 +67,46 @@ public void newCopyOf() { }); } + @Test + public void newImmutableCopyOf() { + foreachBoolConfig(directed -> { + IndexGraphFactory factory = IndexGraphFactory.newInstance(directed); + + IndexGraph g1 = factory.newGraph(); + g1.addVertices(range(10)); + g1.addEdge(1, 2); + g1.addEdge(3, 4); + + IndexGraph g2 = factory.newImmutableCopyOf(g1); + assertEquals(g1, g2); + + /* check immutable */ + assertThrows(UnsupportedOperationException.class, () -> g2.addVertexInt()); + }); + foreachBoolConfig(directed -> { + IndexGraphFactory factory = IndexGraphFactory.newInstance(directed); + + IndexGraph g1 = factory.newGraph(); + g1.addVertices(range(10)); + g1.addEdge(1, 2); + g1.addEdge(3, 4); + IWeightsDouble weights1 = g1.addEdgesWeights("weights", double.class); + weights1.set(0, 1.0); + weights1.set(1, 2.0); + + IndexGraph g2 = factory.newImmutableCopyOf(g1, true, true); + assertEquals(g1, g2); + + IndexGraph g3 = factory.newImmutableCopyOf(g1, false, false); + assertNotEquals(g1, g3); + }); + foreachBoolConfig(directed -> { + IndexGraphFactory factory = IndexGraphFactory.newInstance(directed); + IndexGraph g1 = IndexGraphFactory.newInstance(!directed).newGraph(); + assertThrows(IllegalArgumentException.class, () -> factory.newImmutableCopyOf(g1)); + }); + } + @Test public void setDirected() { foreachBoolConfig(directed -> { diff --git a/jgalgo-core/src/test/java/com/jgalgo/graph/IndexIdMapImplTest.java b/jgalgo-core/src/test/java/com/jgalgo/graph/IndexIdMapImplTest.java index 59ce4c646f..981542281d 100644 --- a/jgalgo-core/src/test/java/com/jgalgo/graph/IndexIdMapImplTest.java +++ b/jgalgo-core/src/test/java/com/jgalgo/graph/IndexIdMapImplTest.java @@ -18,6 +18,7 @@ import static com.jgalgo.internal.util.Range.range; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.Optional; import java.util.Random; import java.util.Set; import org.junit.jupiter.api.Test; @@ -45,7 +46,7 @@ public void newCopyOf() { Set ids = idToIndex.keySet(); IndexIdMap map1 = fromMap(idToIndex); - IndexIdMap map2 = IndexIdMapImpl.newCopyOf(map1, null, indices, false, false); + IndexIdMap map2 = IndexIdMapImpl.newCopyOf(map1, Optional.empty(), indices, false, false); for (int idx : indices) { assertEquals(map1.indexToId(idx), map2.indexToId(idx)); assertEquals(map1.indexToId(idx), map2.indexToIdIfExist(idx)); @@ -70,7 +71,8 @@ public void newCopyOfNullId() { idToIndex.put(null, 0); IntSet indices = range(1); IndexIdMap map1 = fromMap(idToIndex); - assertThrows(NullPointerException.class, () -> IndexIdMapImpl.newCopyOf(map1, null, indices, false, false)); + assertThrows(NullPointerException.class, + () -> IndexIdMapImpl.newCopyOf(map1, Optional.empty(), indices, false, false)); } @Test @@ -105,7 +107,8 @@ public int idToIndexIfExist(String id) { return -1; } }; - assertThrows(IllegalArgumentException.class, () -> IndexIdMapImpl.newCopyOf(map1, null, indices, false, false)); + assertThrows(IllegalArgumentException.class, + () -> IndexIdMapImpl.newCopyOf(map1, Optional.empty(), indices, false, false)); } @Test @@ -132,7 +135,7 @@ public void newCopyOfWithReIndexing() { new IndexGraphBuilderImpl.ReIndexingMapImpl(origToReIndexed, reIndexedToOrig); IndexIdMap map1 = fromMap(idToIndex); - IndexIdMap map2 = IndexIdMapImpl.newCopyOf(map1, reindexing, indices, false, false); + IndexIdMap map2 = IndexIdMapImpl.newCopyOf(map1, Optional.of(reindexing), indices, false, false); for (int idx : indices) { assertEquals(map1.indexToId(reindexing.reIndexedToOrig(idx)), map2.indexToId(idx)); assertEquals(map1.indexToId(reindexing.reIndexedToOrig(idx)), map2.indexToIdIfExist(idx)); @@ -174,7 +177,7 @@ public int reIndexedToOrig(int reindexed) { IndexIdMap map1 = fromMap(idToIndex); assertThrows(NullPointerException.class, - () -> IndexIdMapImpl.newCopyOf(map1, reindexing, indices, false, false)); + () -> IndexIdMapImpl.newCopyOf(map1, Optional.of(reindexing), indices, false, false)); } @Test @@ -222,7 +225,7 @@ public int reIndexedToOrig(int reindexed) { }; assertThrows(IllegalArgumentException.class, - () -> IndexIdMapImpl.newCopyOf(map1, reindexing, indices, false, false)); + () -> IndexIdMapImpl.newCopyOf(map1, Optional.of(reindexing), indices, false, false)); } private static IndexIdMap fromMap(Object2IntMap map) { diff --git a/jgalgo-core/src/test/java/com/jgalgo/graph/IndexIntIdMapImplTest.java b/jgalgo-core/src/test/java/com/jgalgo/graph/IndexIntIdMapImplTest.java index b89d606697..67ee923cd5 100644 --- a/jgalgo-core/src/test/java/com/jgalgo/graph/IndexIntIdMapImplTest.java +++ b/jgalgo-core/src/test/java/com/jgalgo/graph/IndexIntIdMapImplTest.java @@ -18,6 +18,7 @@ import static com.jgalgo.internal.util.Range.range; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.Optional; import java.util.Random; import org.junit.jupiter.api.Test; import com.jgalgo.internal.util.TestBase; @@ -44,7 +45,7 @@ public void newCopyOf() { IntSet ids = idToIndex.keySet(); IndexIntIdMap map1 = fromMap(idToIndex); - IndexIntIdMap map2 = IndexIntIdMapImpl.newCopyOf(map1, null, indices, false, false); + IndexIntIdMap map2 = IndexIntIdMapImpl.newCopyOf(map1, Optional.empty(), indices, false, false); for (int idx : indices) { assertEquals(map1.indexToIdInt(idx), map2.indexToIdInt(idx)); assertEquals(map1.indexToIdInt(idx), map2.indexToIdIfExistInt(idx)); @@ -68,7 +69,7 @@ public void newCopyOfNegativeId() { IntSet indices = range(1); IndexIntIdMap map1 = fromMap(idToIndex); assertThrows(IllegalArgumentException.class, - () -> IndexIntIdMapImpl.newCopyOf(map1, null, indices, false, false)); + () -> IndexIntIdMapImpl.newCopyOf(map1, Optional.empty(), indices, false, false)); } @Test @@ -104,7 +105,7 @@ public int idToIndexIfExist(int id) { } }; assertThrows(IllegalArgumentException.class, - () -> IndexIntIdMapImpl.newCopyOf(map1, null, indices, false, false)); + () -> IndexIntIdMapImpl.newCopyOf(map1, Optional.empty(), indices, false, false)); } @Test @@ -131,7 +132,7 @@ public void newCopyOfWithReIndexing() { new IndexGraphBuilderImpl.ReIndexingMapImpl(origToReIndexed, reIndexedToOrig); IndexIntIdMap map1 = fromMap(idToIndex); - IndexIntIdMap map2 = IndexIntIdMapImpl.newCopyOf(map1, reindexing, indices, false, false); + IndexIntIdMap map2 = IndexIntIdMapImpl.newCopyOf(map1, Optional.of(reindexing), indices, false, false); for (int idx : indices) { assertEquals(map1.indexToIdInt(reindexing.reIndexedToOrig(idx)), map2.indexToIdInt(idx)); assertEquals(map1.indexToIdInt(reindexing.reIndexedToOrig(idx)), map2.indexToIdIfExistInt(idx)); @@ -172,7 +173,7 @@ public int reIndexedToOrig(int reindexed) { IndexIntIdMap map1 = fromMap(idToIndex); assertThrows(IllegalArgumentException.class, - () -> IndexIntIdMapImpl.newCopyOf(map1, reindexing, indices, false, false)); + () -> IndexIntIdMapImpl.newCopyOf(map1, Optional.of(reindexing), indices, false, false)); } @Test @@ -220,7 +221,7 @@ public int reIndexedToOrig(int reindexed) { }; assertThrows(IllegalArgumentException.class, - () -> IndexIntIdMapImpl.newCopyOf(map1, reindexing, indices, false, false)); + () -> IndexIntIdMapImpl.newCopyOf(map1, Optional.of(reindexing), indices, false, false)); } private static IndexIntIdMap fromMap(Int2IntMap map) { diff --git a/jgalgo-core/src/test/java/com/jgalgo/graph/IntGraphBuilderTest.java b/jgalgo-core/src/test/java/com/jgalgo/graph/IntGraphBuilderTest.java index 25ffe48952..032e0691fe 100644 --- a/jgalgo-core/src/test/java/com/jgalgo/graph/IntGraphBuilderTest.java +++ b/jgalgo-core/src/test/java/com/jgalgo/graph/IntGraphBuilderTest.java @@ -73,7 +73,17 @@ public void addVertex() { IntGraphBuilder b = IntGraphBuilder.newInstance(directed); IntSet vertices = new IntOpenHashSet(); for (int i = 0; i < 15; i++) - assertTrue(vertices.add(b.addVertexInt()));; + assertTrue(vertices.add(b.addVertexInt())); + assertEquals(vertices, b.vertices()); + }); + foreachBoolConfig(directed -> { + IntGraphBuilder b = IntGraphBuilder.newInstance(directed); + IntSet vertices = new IntOpenHashSet(); + for (int i = 0; i < 15; i++) { + @SuppressWarnings("deprecation") + int v = b.addVertex().intValue(); + assertTrue(vertices.add(v)); + } assertEquals(vertices, b.vertices()); }); foreachBoolConfig(directed -> { diff --git a/jgalgo-core/src/test/java/com/jgalgo/graph/IntGraphFactoryTest.java b/jgalgo-core/src/test/java/com/jgalgo/graph/IntGraphFactoryTest.java index e1cf230ec8..ddc7875a52 100644 --- a/jgalgo-core/src/test/java/com/jgalgo/graph/IntGraphFactoryTest.java +++ b/jgalgo-core/src/test/java/com/jgalgo/graph/IntGraphFactoryTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.function.Supplier; import org.junit.jupiter.api.Test; import com.jgalgo.internal.util.TestBase; @@ -39,6 +40,10 @@ public void newCopyOf() { IntGraph g2 = factory.newCopyOf(g1); assertEquals(g1, g2); + + /* check mutable */ + g2.addVertex(100); + assertTrue(g2.vertices().contains(100)); }); foreachBoolConfig(directed -> { IntGraphFactory factory = IntGraphFactory.newInstance(directed); @@ -72,6 +77,41 @@ public void newCopyOf() { }); } + @Test + public void newImmutableCopyOf() { + foreachBoolConfig(directed -> { + IntGraphFactory factory = IntGraphFactory.newInstance(directed); + + IntGraph g1 = factory.newGraph(); + g1.addVertices(range(10, 20)); + g1.addEdge(10, 11, 5); + g1.addEdge(11, 12, 6); + + IntGraph g2 = factory.newImmutableCopyOf(g1); + assertEquals(g1, g2); + + /* check immutable */ + assertThrows(UnsupportedOperationException.class, () -> g2.addVertex(100)); + }); + foreachBoolConfig(directed -> { + IntGraphFactory factory = IntGraphFactory.newInstance(directed); + + IntGraph g1 = factory.newGraph(); + g1.addVertices(range(10, 20)); + g1.addEdge(10, 11, 5); + g1.addEdge(11, 12, 6); + IWeightsDouble weights1 = g1.addEdgesWeights("weights", double.class); + weights1.set(5, 1.0); + weights1.set(6, 2.0); + + IntGraph g2 = factory.newImmutableCopyOf(g1, true, true); + assertEquals(g1, g2); + + IntGraph g3 = factory.newImmutableCopyOf(g1, false, false); + assertNotEquals(g1, g3); + }); + } + @Test public void setDirected() { foreachBoolConfig(directed -> {