
org.jgrapht.webgraph.ImmutableUndirectedBigGraphAdapter Maven / Gradle / Ivy
/*
* (C) Copyright 2020-2020, by Sebastiano Vigna and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* See the CONTRIBUTORS.md file distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the
* GNU Lesser General Public License v2.1 or later
* which is available at
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
*
* SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
*/
package org.jgrapht.webgraph;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import org.jgrapht.GraphIterables;
import org.jgrapht.GraphType;
import org.jgrapht.graph.DefaultGraphType;
import it.unimi.dsi.big.webgraph.ImmutableGraph;
import it.unimi.dsi.big.webgraph.LazyLongIterator;
import it.unimi.dsi.big.webgraph.LazyLongIterators;
import it.unimi.dsi.big.webgraph.NodeIterator;
import it.unimi.dsi.fastutil.longs.LongLongSortedPair;
import it.unimi.dsi.fastutil.longs.LongSets;
import it.unimi.dsi.fastutil.objects.ObjectIterables;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashBigSet;
import it.unimi.dsi.lang.FlyweightPrototype;
/**
* An adapter class for undirected graphs using WebGraph
* (big)'s {@link ImmutableGraph}.
*
*
* This class is equivalent to {@link ImmutableUndirectedGraphAdapter}, except that nodes are
* instances of {@link Long}, and edges are instances of {@link LongLongSortedPair}.
*
*
* If necessary, you can adapt a {@linkplain it.unimi.dsi.webgraph.ImmutableGraph standard WebGraph
* graph} using the suitable {@linkplain ImmutableGraph#wrap(it.unimi.dsi.webgraph.ImmutableGraph)
* wrapper}.
*
* @see ImmutableUndirectedGraphAdapter
* @author Sebastiano Vigna
*/
public class ImmutableUndirectedBigGraphAdapter
extends
AbstractImmutableBigGraphAdapter
implements
FlyweightPrototype
{
/**
* Creates an adapter for an undirected (i.e., symmetric) big immutable graph.
*
*
* It is responsibility of the caller that the provided graph has is symmetric (for each arc
* x → y there is an arc y →
* x). If this property is not true, results will be unpredictable.
*
* @param immutableGraph a symmetric big immutable graph.
*/
public ImmutableUndirectedBigGraphAdapter(final ImmutableGraph immutableGraph)
{
super(immutableGraph);
}
@Override
protected LongLongSortedPair makeEdge(final long x, final long y)
{
return LongLongSortedPair.of(x, y);
}
@Override
public boolean containsEdge(final LongLongSortedPair e)
{
if (e == null)
return false;
return containsEdgeFast(e.leftLong(), e.rightLong());
}
@Override
public Set edgeSet()
{
final NodeIterator nodeIterator = immutableGraph.nodeIterator();
final long m = iterables().edgeCount();
final ObjectOpenHashBigSet edges = new ObjectOpenHashBigSet<>(m);
for (long i = 0; i < n; i++) {
final long x = nodeIterator.nextLong();
final LazyLongIterator successors = nodeIterator.successors();
for (long y; (y = successors.nextLong()) != -1;)
if (x <= y)
edges.add(LongLongSortedPair.of(x, y));
}
return edges;
}
@Override
public int degreeOf(final Long vertex)
{
final long d = inDegreeOf(vertex) + (containsEdgeFast(vertex, vertex) ? 1L : 0L);
if (d > Integer.MAX_VALUE)
throw new ArithmeticException();
return (int) d;
}
@Override
public Set edgesOf(final Long vertex)
{
final ObjectLinkedOpenHashSet set = new ObjectLinkedOpenHashSet<>();
final long source = vertex;
final LazyLongIterator predecessors = immutableGraph.successors(source);
for (long target; (target = predecessors.nextLong()) != -1;)
set.add(LongLongSortedPair.of(source, target));
return set;
}
@Override
public int inDegreeOf(final Long vertex)
{
final long d = immutableGraph.outdegree(vertex);
if (d > Integer.MAX_VALUE)
throw new ArithmeticException();
return (int) d;
}
@Override
public Set incomingEdgesOf(final Long vertex)
{
return edgesOf(vertex);
}
@Override
public int outDegreeOf(final Long vertex)
{
final long d = immutableGraph.outdegree(vertex);
if (d > Integer.MAX_VALUE)
throw new ArithmeticException();
return (int) d;
}
@Override
public Set outgoingEdgesOf(final Long vertex)
{
return edgesOf(vertex);
}
@Override
public LongLongSortedPair removeEdge(final Long sourceVertex, final Long targetVertex)
{
throw new UnsupportedOperationException();
}
@Override
public boolean removeEdge(final LongLongSortedPair e)
{
throw new UnsupportedOperationException();
}
@Override
public boolean removeVertex(final Long v)
{
throw new UnsupportedOperationException();
}
@Override
public Set vertexSet()
{
return LongSets.fromTo(0, n);
}
@Override
public Long getEdgeSource(final LongLongSortedPair e)
{
return e.leftLong();
}
@Override
public Long getEdgeTarget(final LongLongSortedPair e)
{
return e.rightLong();
}
@Override
public double getEdgeWeight(final LongLongSortedPair e)
{
return DEFAULT_EDGE_WEIGHT;
}
@Override
public void setEdgeWeight(final LongLongSortedPair e, final double weight)
{
if (weight != 1)
throw new UnsupportedOperationException();
}
@Override
public GraphType getType()
{
return new DefaultGraphType.Builder()
.weighted(false).modifiable(false).allowMultipleEdges(false).allowSelfLoops(true)
.undirected().build();
}
@Override
public ImmutableUndirectedBigGraphAdapter copy()
{
return new ImmutableUndirectedBigGraphAdapter(immutableGraph.copy());
}
private final GraphIterables ITERABLES = new GraphIterables<>()
{
@Override
public ImmutableUndirectedBigGraphAdapter getGraph()
{
return ImmutableUndirectedBigGraphAdapter.this;
}
@Override
public long vertexCount()
{
return n;
}
@Override
public long edgeCount()
{
if (m != -1)
return m;
return m = ObjectIterables.size(edges());
}
@Override
public long degreeOf(final Long vertex)
{
return inDegreeOf(vertex) + (containsEdgeFast(vertex, vertex) ? 1 : 0);
}
@Override
public Iterable edgesOf(final Long vertex)
{
final long x = vertex;
return () -> new Iterator<>()
{
final LazyLongIterator successors = immutableGraph.successors(x);
long y = -1;
@Override
public boolean hasNext()
{
if (y == -1)
y = successors.nextLong();
return y != -1;
}
@Override
public LongLongSortedPair next()
{
final LongLongSortedPair edge = LongLongSortedPair.of(y, x);
y = -1;
return edge;
}
};
}
@Override
public long inDegreeOf(final Long vertex)
{
return immutableGraph.outdegree(vertex);
}
public Iterable incomingEdgesOf(final Long vertex)
{
return edgesOf(vertex);
}
@Override
public long outDegreeOf(final Long vertex)
{
return immutableGraph.outdegree(vertex);
}
@Override
public Iterable outgoingEdgesOf(final Long vertex)
{
return edgesOf(vertex);
}
@Override
public Iterable edges()
{
return () -> new Iterator<>()
{
final NodeIterator nodeIterator = immutableGraph.nodeIterator();
LazyLongIterator successors = LazyLongIterators.EMPTY_ITERATOR;
long x, y = -1;
@Override
public boolean hasNext()
{
if (y != -1)
return true;
do {
while ((y = successors.nextLong()) == -1) {
if (!nodeIterator.hasNext())
return false;
x = nodeIterator.nextLong();
successors = nodeIterator.successors();
}
} while (y < x);
return true;
}
@Override
public LongLongSortedPair next()
{
if (!hasNext())
throw new NoSuchElementException();
final LongLongSortedPair edge = LongLongSortedPair.of(x, y);
y = -1;
return edge;
}
};
}
};
@Override
public GraphIterables iterables()
{
return ITERABLES;
}
}