All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgrapht.graph.guava.BaseValueGraphAdapter Maven / Gradle / Ivy

There is a newer version: 1.5.2
Show newest version
/*
 * (C) Copyright 2018-2018, by Dimitrios Michail and Contributors.
 *
 * JGraphT : a free Java graph-theory library
 *
 * This program and the accompanying materials are dual-licensed under
 * either
 *
 * (a) the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation, or (at your option) any
 * later version.
 *
 * or (per the licensee's choosing)
 *
 * (b) the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation.
 */
package org.jgrapht.graph.guava;

import com.google.common.graph.*;
import org.jgrapht.*;
import org.jgrapht.Graph;
import org.jgrapht.graph.AbstractGraph;
import org.jgrapht.graph.*;

import java.io.*;
import java.util.*;
import java.util.function.*;

import static java.util.stream.Collectors.*;

/**
 * A base abstract implementation for the graph adapter class using Guava's {@link ValueGraph}. This
 * is a helper class in order to support both mutable and immutable value graphs.
 * 
 * @author Dimitrios Michail
 *
 * @param  the graph vertex type
 * @param  the value type
 * @param  type of the underlying Guava's value graph
 */
public abstract class BaseValueGraphAdapter>
    extends
    AbstractGraph>
    implements
    Graph>,
    Cloneable,
    Serializable
{
    private static final long serialVersionUID = 3833510139696864917L;

    protected static final String LOOPS_NOT_ALLOWED = "loops not allowed";

    protected transient Set unmodifiableVertexSet = null;
    protected transient Set> unmodifiableEdgeSet = null;

    protected Supplier vertexSupplier;
    protected Supplier> edgeSupplier;
    protected ToDoubleFunction valueConverter;
    protected transient VG valueGraph;

    /**
     * Create a new adapter.
     * 
     * @param valueGraph the mutable value graph
     * @param valueConverter a function that converts a value to a double
     */
    public BaseValueGraphAdapter(VG valueGraph, ToDoubleFunction valueConverter)
    {
        this(valueGraph, valueConverter, null, null);
    }

    /**
     * Create a new adapter.
     * 
     * @param valueGraph the mutable value graph
     * @param valueConverter a function that converts a value to a double
     * @param vertexSupplier the vertex supplier
     * @param edgeSupplier the edge supplier
     */
    public BaseValueGraphAdapter(
        VG valueGraph, ToDoubleFunction valueConverter, Supplier vertexSupplier,
        Supplier> edgeSupplier)
    {
        this.vertexSupplier = vertexSupplier;
        this.edgeSupplier = edgeSupplier;
        this.valueGraph = Objects.requireNonNull(valueGraph);
        this.valueConverter = Objects.requireNonNull(valueConverter);
    }

    @Override
    public Supplier getVertexSupplier()
    {
        return vertexSupplier;
    }

    /**
     * Set the vertex supplier that the graph uses whenever it needs to create new vertices.
     * 
     * 

* A graph uses the vertex supplier to create new vertex objects whenever a user calls method * {@link Graph#addVertex()}. Users can also create the vertex in user code and then use method * {@link Graph#addVertex(Object)} to add the vertex. * *

* In contrast with the {@link Supplier} interface, the vertex supplier has the additional * requirement that a new and distinct result is returned every time it is invoked. More * specifically for a new vertex to be added in a graph v must not be equal * to any other vertex in the graph. More formally, the graph must not contain any vertex * v2 such that v2.equals(v). * * @param vertexSupplier the vertex supplier */ public void setVertexSupplier(Supplier vertexSupplier) { this.vertexSupplier = vertexSupplier; } @Override public Supplier> getEdgeSupplier() { return edgeSupplier; } /** * Set the edge supplier that the graph uses whenever it needs to create new edges. * *

* A graph uses the edge supplier to create new edge objects whenever a user calls method * {@link Graph#addEdge(Object, Object)}. Users can also create the edge in user code and then * use method {@link Graph#addEdge(Object, Object, Object)} to add the edge. * *

* In contrast with the {@link Supplier} interface, the edge supplier has the additional * requirement that a new and distinct result is returned every time it is invoked. More * specifically for a new edge to be added in a graph e must not be equal to * any other edge in the graph (even if the graph allows edge-multiplicity). More formally, the * graph must not contain any edge e2 such that e2.equals(e). * * @param edgeSupplier the edge supplier */ public void setEdgeSupplier(Supplier> edgeSupplier) { this.edgeSupplier = edgeSupplier; } @Override public EndpointPair getEdge(V sourceVertex, V targetVertex) { if (sourceVertex == null || targetVertex == null) { return null; } else if (!valueGraph.hasEdgeConnecting(sourceVertex, targetVertex)) { return null; } else { return createEdge(sourceVertex, targetVertex); } } @Override @Deprecated public EdgeFactory> getEdgeFactory() { return null; } @Override public Set vertexSet() { if (unmodifiableVertexSet == null) { unmodifiableVertexSet = Collections.unmodifiableSet(valueGraph.nodes()); } return unmodifiableVertexSet; } @Override public V getEdgeSource(EndpointPair e) { return e.nodeU(); } @Override public V getEdgeTarget(EndpointPair e) { return e.nodeV(); } @Override public GraphType getType() { return (valueGraph.isDirected() ? new DefaultGraphType.Builder().directed() : new DefaultGraphType.Builder().undirected()) .weighted(true).allowMultipleEdges(false) .allowSelfLoops(valueGraph.allowsSelfLoops()).build(); } @Override public boolean containsEdge(EndpointPair e) { return valueGraph.edges().contains(e); } @Override public boolean containsVertex(V v) { return valueGraph.nodes().contains(v); } @Override public Set> edgeSet() { if (unmodifiableEdgeSet == null) { unmodifiableEdgeSet = Collections.unmodifiableSet(valueGraph.edges()); } return unmodifiableEdgeSet; } @Override public int degreeOf(V vertex) { return valueGraph.degree(vertex); } @Override public Set> edgesOf(V vertex) { return valueGraph.incidentEdges(vertex); } @Override public int inDegreeOf(V vertex) { return valueGraph.inDegree(vertex); } @Override public Set> incomingEdgesOf(V vertex) { return valueGraph .predecessors(vertex).stream().map(other -> createEdge(other, vertex)) .collect(collectingAndThen(toSet(), Collections::unmodifiableSet)); } @Override public int outDegreeOf(V vertex) { return valueGraph.outDegree(vertex); } @Override public Set> outgoingEdgesOf(V vertex) { return valueGraph .successors(vertex).stream().map(other -> createEdge(vertex, other)) .collect(collectingAndThen(toSet(), Collections::unmodifiableSet)); } @Override public double getEdgeWeight(EndpointPair e) { if (e == null) { throw new NullPointerException(); } else if (!valueGraph.hasEdgeConnecting(e.nodeU(), e.nodeV())) { throw new IllegalArgumentException("no such edge in graph: " + e.toString()); } else { return valueGraph .edgeValue(e.nodeU(), e.nodeV()).map(valueConverter::applyAsDouble) .orElse(Graph.DEFAULT_EDGE_WEIGHT); } } @Override public Set> getAllEdges(V sourceVertex, V targetVertex) { if (sourceVertex == null || targetVertex == null || !valueGraph.nodes().contains(sourceVertex) || !valueGraph.nodes().contains(targetVertex)) { return null; } else if (!valueGraph.hasEdgeConnecting(sourceVertex, targetVertex)) { return Collections.emptySet(); } else { return Collections.singleton(createEdge(sourceVertex, targetVertex)); } } /** * Create an edge * * @param s the source vertex * @param t the target vertex * @return the edge */ final EndpointPair createEdge(V s, V t) { return valueGraph.isDirected() ? EndpointPair.ordered(s, t) : EndpointPair.unordered(s, t); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy