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

com.salesforce.jgrapht.graph.specifics.UndirectedSpecifics Maven / Gradle / Ivy

Go to download

This project contains the apt processor that implements all the checks enumerated in @Verify. It is a self contained, and shaded jar.

There is a newer version: 2.0.7
Show newest version
/*
 * (C) Copyright 2015-2017, by Barak Naveh 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 com.salesforce.jgrapht.graph.specifics;

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

import com.salesforce.jgrapht.graph.*;
import com.salesforce.jgrapht.util.*;

/**
 * Plain implementation of UndirectedSpecifics. This implementation requires the least amount of
 * memory, at the expense of slow edge retrievals. Methods which depend on edge retrievals, e.g.
 * getEdge(V u, V v), containsEdge(V u, V v), addEdge(V u, V v), etc may be relatively slow when the
 * average degree of a vertex is high (dense graphs). For a fast implementation, use
 * {@link FastLookupUndirectedSpecifics}.
 *
 * @param  the graph vertex type
 * @param  the graph edge type
 *
 * @author Barak Naveh
 * @author Joris Kinable
 */
public class UndirectedSpecifics
    implements Specifics, Serializable
{
    private static final long serialVersionUID = 6494588405178655873L;
    private static final String NOT_IN_UNDIRECTED_GRAPH =
        "no such operation in an undirected graph";

    protected AbstractBaseGraph abstractBaseGraph;
    protected Map> vertexMapUndirected;
    protected EdgeSetFactory edgeSetFactory;

    /**
     * Construct a new undirected specifics.
     * 
     * @param abstractBaseGraph the graph for which these specifics are for
     */
    public UndirectedSpecifics(AbstractBaseGraph abstractBaseGraph)
    {
        this(abstractBaseGraph, new LinkedHashMap<>(), new ArrayUnenforcedSetEdgeSetFactory<>());
    }

    /**
     * Construct a new undirected specifics.
     * 
     * @param abstractBaseGraph the graph for which these specifics are for
     * @param vertexMap map for the storage of vertex edge sets
     */
    public UndirectedSpecifics(
        AbstractBaseGraph abstractBaseGraph, Map> vertexMap)
    {
        this(abstractBaseGraph, vertexMap, new ArrayUnenforcedSetEdgeSetFactory<>());
    }

    /**
     * Construct a new undirected specifics.
     * 
     * @param abstractBaseGraph the graph for which these specifics are for
     * @param vertexMap map for the storage of vertex edge sets
     * @param edgeSetFactory factory for the creation of vertex edge sets
     */
    public UndirectedSpecifics(
        AbstractBaseGraph abstractBaseGraph, Map> vertexMap,
        EdgeSetFactory edgeSetFactory)
    {
        this.abstractBaseGraph = abstractBaseGraph;
        this.vertexMapUndirected = vertexMap;
        this.edgeSetFactory = edgeSetFactory;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addVertex(V v)
    {
        // add with a lazy edge container entry
        vertexMapUndirected.put(v, null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set getVertexSet()
    {
        return vertexMapUndirected.keySet();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set getAllEdges(V sourceVertex, V targetVertex)
    {
        Set edges = null;

        if (abstractBaseGraph.containsVertex(sourceVertex)
            && abstractBaseGraph.containsVertex(targetVertex))
        {
            edges = new ArrayUnenforcedSet<>();

            for (E e : getEdgeContainer(sourceVertex).vertexEdges) {
                boolean equal = isEqualsStraightOrInverted(sourceVertex, targetVertex, e);

                if (equal) {
                    edges.add(e);
                }
            }
        }

        return edges;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public E getEdge(V sourceVertex, V targetVertex)
    {
        if (abstractBaseGraph.containsVertex(sourceVertex)
            && abstractBaseGraph.containsVertex(targetVertex))
        {

            for (E e : getEdgeContainer(sourceVertex).vertexEdges) {
                boolean equal = isEqualsStraightOrInverted(sourceVertex, targetVertex, e);

                if (equal) {
                    return e;
                }
            }
        }

        return null;
    }

    private boolean isEqualsStraightOrInverted(Object sourceVertex, Object targetVertex, E e)
    {
        boolean equalStraight = sourceVertex.equals(abstractBaseGraph.getEdgeSource(e))
            && targetVertex.equals(abstractBaseGraph.getEdgeTarget(e));

        boolean equalInverted = sourceVertex.equals(abstractBaseGraph.getEdgeTarget(e))
            && targetVertex.equals(abstractBaseGraph.getEdgeSource(e));
        return equalStraight || equalInverted;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addEdgeToTouchingVertices(E e)
    {
        V source = abstractBaseGraph.getEdgeSource(e);
        V target = abstractBaseGraph.getEdgeTarget(e);

        getEdgeContainer(source).addEdge(e);

        if (!source.equals(target)) {
            getEdgeContainer(target).addEdge(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int degreeOf(V vertex)
    {
        if (abstractBaseGraph.isAllowingLoops()) { // then we must count, and add loops twice

            int degree = 0;
            Set edges = getEdgeContainer(vertex).vertexEdges;

            for (E e : edges) {
                if (abstractBaseGraph.getEdgeSource(e).equals(abstractBaseGraph.getEdgeTarget(e))) {
                    degree += 2;
                } else {
                    degree += 1;
                }
            }

            return degree;
        } else {
            return getEdgeContainer(vertex).edgeCount();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set edgesOf(V vertex)
    {
        return getEdgeContainer(vertex).getUnmodifiableVertexEdges();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int inDegreeOf(V vertex)
    {
        throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set incomingEdgesOf(V vertex)
    {
        throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int outDegreeOf(V vertex)
    {
        throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set outgoingEdgesOf(V vertex)
    {
        throw new UnsupportedOperationException(NOT_IN_UNDIRECTED_GRAPH);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removeEdgeFromTouchingVertices(E e)
    {
        V source = abstractBaseGraph.getEdgeSource(e);
        V target = abstractBaseGraph.getEdgeTarget(e);

        getEdgeContainer(source).removeEdge(e);

        if (!source.equals(target)) {
            getEdgeContainer(target).removeEdge(e);
        }
    }

    /**
     * A lazy build of edge container for specified vertex.
     *
     * @param vertex a vertex in this graph
     *
     * @return an edge container
     */
    protected UndirectedEdgeContainer getEdgeContainer(V vertex)
    {
        // abstractBaseGraph.assertVertexExist(vertex); //JK: I don't think we need this here. This
        // should have been verified upstream

        UndirectedEdgeContainer ec = vertexMapUndirected.get(vertex);

        if (ec == null) {
            ec = new UndirectedEdgeContainer<>(edgeSetFactory, vertex);
            vertexMapUndirected.put(vertex, ec);
        }

        return ec;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy