Package edu.ucla.sspace.graph

Source Code of edu.ucla.sspace.graph.SparseDirectedGraph

/*
* Copyright 2011 David Jurgens
*
* This file is part of the S-Space package and is covered under the terms and
* conditions therein.
*
* The S-Space package is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation and distributed hereunder to you.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND NO REPRESENTATIONS OR WARRANTIES,
* EXPRESS OR IMPLIED ARE MADE.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, WE MAKE
* NO REPRESENTATIONS OR WARRANTIES OF MERCHANT- ABILITY OR FITNESS FOR ANY
* PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE OR DOCUMENTATION
* WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER
* RIGHTS.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package edu.ucla.sspace.graph;

import java.util.AbstractSet;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;

import edu.ucla.sspace.util.primitive.IntSet;
import edu.ucla.sspace.util.primitive.TroveIntSet;


/**
* An implementation of {@link DirectedGraph} that uses a sparse backing
* representation.  This implementation assumes that the total number of edges
* is less than the {@code n}<sup>2</sup> possible, where {@code n} is the
* number of vertices.
*
* <p> This class supports all optional {@link Graph} and {@link DirectedGraph}
* methods.  All returned {@link DirectedEdge}-based collections will reflect
* the state of the graph and may be modified to change the graph; i.e., adding
* an edge to the adjacency list of a vertex or edge list of the graph will add
* that edge in the backing graph.  Adding vertices by adding to the {@link
* #vertices()} set is supported.  Adding edges by adding a vertex to the set of
* adjacent vertex is <i>not</i> supported.
*
* @author David Jurgens
*/
@SuppressWarnings("unchecked")
public class SparseDirectedGraph extends AbstractGraph<DirectedEdge,SparseDirectedEdgeSet>
        implements DirectedGraph<DirectedEdge> {

    private static final long serialVersionUID = 1L;

    /**
     * Creates an empty directed graph
     */
    public SparseDirectedGraph() { }

    /**
     * Creates a directed graph with the provided vertices
     */
    public SparseDirectedGraph(Set<Integer> vertices) {
        super(vertices);
    }

    /**
     * Creates a directed graph with a copy of all the vertices and edges in
     * {@code g}.
     */
    public SparseDirectedGraph(Graph<? extends DirectedEdge> g) {
        for (Integer v : g.vertices())
            add(v);
        for (DirectedEdge e : g.edges())
            add(e);
    }

    /**
     * {@inheritDoc}
     */
    @Override public DirectedGraph<DirectedEdge> copy(Set<Integer> vertices) {
        // special case for If the called is requesting a copy of the entire
        // graph, which is more easily handled with the copy constructor
        if (vertices.size() == order() && vertices.equals(vertices()))
            return new SparseDirectedGraph(this);
        SparseDirectedGraph g = new SparseDirectedGraph();
        for (int v : vertices) {
            if (!contains(v))
                throw new IllegalArgumentException(
                    "Requested copy with non-existant vertex: " + v);
            g.add(v);
            for (DirectedEdge e : getAdjacencyList(v))
                if (vertices.contains(e.from()) && vertices.contains(e.to()))
                    g.add(e);
        }
        return g;
    }
   
    /**
     * Creates an {@link EdgeSet} for storing {@link DirectedEdge} instances for
     * the specified vertex.
     */
    @Override protected SparseDirectedEdgeSet createEdgeSet(int vertex) {
        return new SparseDirectedEdgeSet(vertex);
    }

    /**
     * {@inheritDoc}
     */
    public int inDegree(int vertex) {
        SparseDirectedEdgeSet edges = getEdgeSet(vertex);
        return (edges == null) ? 0 : edges.inEdges().size();
    }

    /**
     * {@inheritDoc}
     */
    public Set<DirectedEdge> inEdges(int vertex) {
        SparseDirectedEdgeSet edges = getEdgeSet(vertex);
        return (edges == null)
            ? Collections.<DirectedEdge>emptySet()
            : new EdgeSetDecorator(edges.inEdges());
    }

    /**
     * {@inheritDoc}
     */
    public int outDegree(int vertex) {
        SparseDirectedEdgeSet edges = getEdgeSet(vertex);
        return (edges == null) ? 0 : edges.outEdges().size();
    }

    /**
     * {@inheritDoc}
     */
    public Set<DirectedEdge> outEdges(int vertex) {
        SparseDirectedEdgeSet edges = getEdgeSet(vertex);
        return (edges == null)
            ? Collections.<DirectedEdge>emptySet()
            : new EdgeSetDecorator(edges.outEdges());
    }

    /**
     * {@inheritDoc}
     */
    public IntSet predecessors(int vertex) {
        IntSet preds = new TroveIntSet();
        for (DirectedEdge e : inEdges(vertex))
            preds.add(e.from());
        return preds;
    }

    /**
     * {@inheritDoc}
     */
    public DirectedGraph subgraph(Set<Integer> vertices) {
        Graph<DirectedEdge> subgraph = super.subgraph(vertices);
        return new SubgraphAdaptor(subgraph);
    }

    /**
     * {@inheritDoc}
     */
    public IntSet successors(int vertex) {
        IntSet succs = new TroveIntSet();
        for (DirectedEdge e : outEdges(vertex))
            succs.add(e.to());
        return succs;
    }

    /***
     * A wrapper around the set of edges returned for {@code inEdges} and {@code
     * outEdges} that properly handles edge additions and removals.
     */
    private class EdgeSetDecorator extends AbstractSet<DirectedEdge> {

        private final Set<DirectedEdge> edges;
       
        public EdgeSetDecorator(Set<DirectedEdge> edges) {
            this.edges = edges;
        }

        @Override public boolean add(DirectedEdge e) {
            // Rather than add the edge to the set directly, add it to the
            // graph, which will propagate the edge to the appropriate EdgeSet
            // instances.
            return SparseDirectedGraph.this.add(e);
        }

        @Override public boolean contains(Object o) {
            return edges.contains(o);
        }

        @Override public Iterator<DirectedEdge> iterator() {
            return new EdgeSetIteratorDecorator();
        }

        @Override public boolean remove(Object o) {
            if (!(o instanceof DirectedEdge))
                return false;
            // Rather than removing the edge to the set directly, removing it
            // from the graph, which will remove the edge froma the appropriate
            // EdgeSet instances.
            return SparseDirectedGraph.this.remove((DirectedEdge)o);
        }

        @Override public int size() {
            return edges.size();
        }

        private class EdgeSetIteratorDecorator
                implements Iterator<DirectedEdge> {

            private final Iterator<DirectedEdge> iter;

            private boolean alreadyRemoved;

            public EdgeSetIteratorDecorator() {
                iter = edges.iterator();
                alreadyRemoved = true;
            }

            public boolean hasNext() {
                return iter.hasNext();
            }

            public DirectedEdge next() {
                alreadyRemoved = false;
                return iter.next();
            }

            public void remove() {
                // REMINDER: I think this method would be extremely problematic
                // to actually implement.  The call to iter.remove() would leave
                // the symmetric edge in place in the AbstractGraph, while
                // calling remove() would likely result in a concurrent
                // modification to the EdgeSet being iterated over, which may
                // have unpredictable results. Therefore, we just throw an
                // exception to indicate it's not supported until we can
                // identify a better implementation solution.  -david
                throw new UnsupportedOperationException();
            }
        }
    }

    /**
     * A decorator over the {@link Graph} returned by {@link #subgraph(Set)}
     * that extends the functionality to support the {@link DirectedGraph}
     * interface.
     */
    private class SubgraphAdaptor extends GraphAdaptor<DirectedEdge>
            implements DirectedGraph<DirectedEdge>, java.io.Serializable {

        private static final long serialVersionUID = 1L;

        /**
         * Constructs a new adaptor over the provided subgraph.
         */
        public SubgraphAdaptor(Graph<DirectedEdge> subgraph) {
            super(subgraph);
        }

        /**
         * {@inheritDoc}
         */
        @Override public DirectedGraph<DirectedEdge> copy(Set<Integer> vertices) {
            // special case for If the called is requesting a copy of the entire
            // graph, which is more easily handled with the copy constructor
            if (vertices.size() == order() && vertices.equals(vertices()))
                return new SparseDirectedGraph(this);
            SparseDirectedGraph g = new SparseDirectedGraph();
            for (int v : vertices) {
                if (!contains(v))
                    throw new IllegalArgumentException(
                        "Requested copy with non-existant vertex: " + v);
                g.add(v);
                for (DirectedEdge e : getAdjacencyList(v))
                    if (vertices.contains(e.from())
                            && vertices.contains(e.to()))
                        g.add(e);
            }
            return g;
        }

        /**
         * {@inheritDoc}
         */
        public int inDegree(int vertex) {
            int degree = 0;
            Set<DirectedEdge> edges = getAdjacencyList(vertex);
            if (edges.isEmpty())
                return 0;
            for (DirectedEdge e : edges) {
                if (e.to() == vertex)
                    degree++;
            }
            return degree;
        }

        /**
         * {@inheritDoc}
         */
        public Set<DirectedEdge> inEdges(int vertex) {
            // REMINDER: this is probably best wrapped with yet another
            // decorator class to avoid the O(n) penality of iteration over all
            // the edges
            Set<DirectedEdge> edges = getAdjacencyList(vertex);
            if (edges.isEmpty())
                return Collections.<DirectedEdge>emptySet();

            Set<DirectedEdge> in = new HashSet<DirectedEdge>();
            for (DirectedEdge e : edges) {
                if (e.to() == vertex)
                    in.add(e);
            }
            return in;
        }

        /**
         * {@inheritDoc}
         */
        public int outDegree(int vertex) {
            int degree = 0;
            Set<DirectedEdge> edges = getAdjacencyList(vertex);
            if (edges.isEmpty())
                return 0;
            for (DirectedEdge e : edges) {
                if (e.from() == vertex)
                    degree++;
            }
            return degree;
        }

        /**
         * {@inheritDoc}
         */
        public Set<DirectedEdge> outEdges(int vertex) {
            // REMINDER: this is probably best wrapped with yet another
            // decorator class to avoid the O(n) penality of iteration over all
            // the edges
            Set<DirectedEdge> edges = getAdjacencyList(vertex);
            if (edges.isEmpty())
                return Collections.<DirectedEdge>emptySet();
            Set<DirectedEdge> out = new HashSet<DirectedEdge>();
            for (DirectedEdge e : edges) {
                if (e.from() == vertex)
                    out.add(e);
            }
            return out;
        }

        /**
         * {@inheritDoc}
         */
        public IntSet predecessors(int vertex) {
            IntSet preds = new TroveIntSet();
            for (DirectedEdge e : inEdges(vertex))
                preds.add(e.from());
            return preds;
        }

        /**
         * {@inheritDoc}
         */
        public IntSet successors(int vertex) {
            IntSet succs = new TroveIntSet();
            for (DirectedEdge e : outEdges(vertex))
                succs.add(e.to());
            return succs;
        }

        /**
         * {@inheritDoc}
         */
        public DirectedGraph subgraph(Set<Integer> vertices) {
            Graph<DirectedEdge> g = super.subgraph(vertices);
            return new SubgraphAdaptor(g);
        }
    }
}
TOP

Related Classes of edu.ucla.sspace.graph.SparseDirectedGraph

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.