// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU Lesser General Public License (LGPL): http://www.gnu.org/licenses/
/*
* BaseGraph.java
*
* Created on November 13, 2004, 8:20 PM
*/
package graphtea.library;
import Jama.Matrix;
import graphtea.library.exceptions.InvalidEdgeException;
import graphtea.library.exceptions.InvalidGraphException;
import graphtea.library.exceptions.InvalidVertexException;
import graphtea.library.genericcloners.EdgeVertexCopier;
import java.util.AbstractList;
import java.util.Iterator;
/**
* Generic base class for representation of all types of graphs.
* @author Hooman Mohajeri Moghaddam, added weighted version of weightOfEdge method
* @author Omid Aladini
*/
abstract public class BaseGraph<VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>>
implements Iterable<VertexType> {
/**
* Returns the number of vertices.
*
* @return Number of vertices in the graph.
*/
public abstract int getVerticesCount();
/**
*
* @return the same as getVerticesCount()
* @see graphtea.library.BaseGraph#getVerticesCount()
*/
public int numOfVertices(){
return getVerticesCount();
}
/**
* Creates a clone of the current graph using the GraphConverter object which is responsible
* for duplication of the graph elements (edges and vertices).
*
* @param gc Reference to EdgeVertexCopier object.
* @return Clone of the current graph which is independent of it's source graph.
* @throws InvalidGraphException If the graph is not a valid graph object.
*/
public abstract BaseGraph<VertexType, EdgeType>
copy(EdgeVertexCopier<VertexType, EdgeType> gc)
throws InvalidGraphException;
/**
* Inserts an edge in the graph.
*
* @param newEdge Reference to the new edge object.
* @throws graphtea.library.exceptions.InvalidVertexException
* Thrown when the edge object tries
* to connect two vertices whom their indexes are invalid.
*/
public abstract void insertEdge(EdgeType newEdge)
throws InvalidVertexException;
/**
*
* @param newEdge the new edge to be added
* @throws InvalidVertexException the vertex is invalid
* @see BaseGraph#insertEdge(EdgeType)
*/
public void addEdge(EdgeType newEdge)
throws InvalidVertexException{
insertEdge(newEdge);
}
/**
* Removes all edges between two vertices.
*
* @param source Index of the edges' start point.
* @param target Index of the edges' end point.
* @throws graphtea.library.exceptions.InvalidVertexException
* Thrown when two supplied indexes of vertices are invalid.
*/
public abstract void removeAllEdges(VertexType source, VertexType target)
throws InvalidVertexException;
/**
* Removes an edge from the graph.
*
* @param edge Edge to be removed.
* @throws InvalidEdgeException If <code>edge</code> is an invalid edge object.
*/
public abstract void removeEdge(EdgeType edge)
throws InvalidEdgeException;
/**
* Returns a collection of all edges which connects two vertices supplied as first and second arguments of
* this method.
*
* @param source of the desired edges.
* @param target of the desired edges.
* @return Returns a collection of all edges which connects two vertices supplied as first and second arguments of
* this method.
* @throws InvalidVertexException if supplied source or target are invalid.
*/
public abstract AbstractList<EdgeType> getEdges(VertexType source, VertexType target)
throws InvalidVertexException;
/**
* Returns true if there is an edge between specified vertices (direction considered for directed graphs).
* * @param Source of the edge for existance check.
*
* @param source of the desired edges.
* @param target of the edge for existance check.
* @return true if there is an edge between specified vertices (direction considered for directed graphs).
* @throws InvalidVertexException if supplied source or target are invalid.
*/
public abstract boolean isEdge(VertexType source, VertexType target)
throws InvalidVertexException;
/**
* Gets the weight of the edge between two vertices(if an edge exists).\
* Note that it currently supports only one edge between two vertices!!!!
* However the return type is an array to support hyper-graphs.
* @param source of the edge to check.
* @param target of the edge to check.
* @return the weight of the edge if it exists, null otherwise (direction considered for directed graphs).
* @throws InvalidVertexException if supplied source or target are invalid.
*/
public abstract int[] weightOfEdge(VertexType source, VertexType target)
throws InvalidVertexException;
/**
* Inserts a new vertex to the graph.
*
* @param newVertex The new vertex to be inserted.
*/
public abstract void insertVertex(VertexType newVertex);
/**
*
* @param newVertex the new vertex
* @see BaseGraph#insertVertex(VertexType)
*/
public void addVertex(VertexType newVertex){
insertVertex(newVertex);
}
/**
* Removes a vertex and all it's connected edges.
*
* @param v the vertex to be removed.
*/
public abstract void removeVertex(VertexType v)
throws InvalidVertexException;
/**
* Returns iterator object for the vertices.
*
* @return iterator object for the vertices.
*/
public abstract Iterator<VertexType> iterator();
/**
* Returns in-degree of vertex <I>vertexId</I>, the number of edges which
* their target goes to the specified vertex.
*
* @return in-degree of vertex <I>vertexId</I>.
* @throws InvalidVertexException the vertex is invalid
* @see graphtea.library.BaseGraph#getDegree(BaseVertex)
*/
public abstract int getInDegree(VertexType v)
throws InvalidVertexException;
/**
* Returns out-degree of the supplied vertex, the number of edges which
* their source is attached to the specified vertex.
*
* @return out-degree of vertex <I>vertexId</I>.
* @throws InvalidVertexException the vertex is invalid
* @see graphtea.library.BaseGraph#getDegree(BaseVertex)
*/
public abstract int getOutDegree(VertexType v)
throws InvalidVertexException;
/**
* Returns a Jama Matrix object that represents adjacency matrix of
* the graph. the Matrix object have the ability apply simple linear
* algebra operations on the adjacency matrix.
*
* @return Adjacency Matrix of the graph as a Jama Matrix object.
*/
public abstract Matrix getAdjacencyMatrix();
/**
* Returns a Jama Matrix object that represents weighted adjacency matrix of
* the graph. the Matrix object have the ability apply simple linear
* algebra operations on the adjacency matrix.
*
* @return Adjacency Matrix of the graph as a Jama Matrix object.
*/
public abstract Matrix getWeightedAdjacencyMatrix();
/**
* Returns whether the graph is directed.
*
* @return True is graph is constructed as a directed graph and false otherwise.
*/
public abstract boolean isDirected();
/**
* Prints the Adjacency Matrix to the standard output.
*/
public abstract void dump();
/**
* Constructs and returns an Edge Iterator object which iterates through all the edges in the graph.
* Note that if the graph object is changed during iteration, the iteration may not
* actually represent current state of the graph. For example, if you deleted an edge
* after construction of this object, the edge would be included in the iteration.
*
* @return Iterator object on edges.
* @see BaseGraph#lightEdgeIterator()
*/
public abstract Iterator<EdgeType> edgeIterator();
/**
* Constructs an Edge Iterator object which iterates through all the edges going to
* or coming from the specified vertex <code>v</code>.
* Note that if the graph object is changed during iteration, the iteration may not
* actually represent current state of the graph. For example, if you deleted an edge
* after construction of this object, the edge would be included in the iteration.
*
* @param v Source or target of desired edges.
* @return Iterator object on edges which their sources or targets are the supplied vertex.
* @see graphtea.library.BaseGraph#lightEdgeIterator(BaseVertex)
* @see graphtea.library.BaseGraph#getNeighbors(BaseVertex)
*/
public abstract Iterator<EdgeType> edgeIterator(VertexType v)
throws InvalidVertexException;
/**
* Constructs an Edge Iterator object which iterates through all the edges going to
* or coming from (depending on the second parameter) the specified vertex <code>v</code>.
* If the second parameter it true, then the first parameter is considered to be source of
* all desired edges, and if it's false the first parameter is considered to be target of desired edges.
* Note that if the graph object is changed during iteration, the iteration may not
* actually represent current state of the graph. For example, if you deleted an edge
* after construction of this object, the edge would be included in the iteration.
*
* @param v If the second parameter is true indicated the vertex which is source of desired edges, otherwise
* it is considered to be target of desired edges.
* @param source True means the first parameter should be considered source of desired edges.
* @return Iterator on edges which either their sources or their targets, but not necessarily both,
* are the supplied vertex.
*/
public abstract Iterator<EdgeType> edgeIterator(VertexType v, boolean source)
throws InvalidVertexException;
/**
* This method returns true if the graph contains the specified vertex, false otherwise.
*
* @param v Vertex to check existance.
* @return True if the graph contains the specified vertex, false otherwise.
*/
public abstract boolean containsVertex(VertexType v);
/**
* If the supplied vertex is invalid (Not one of graph's vertices), throws InvalidVertexException. This
* method should be called before any operation by algorithms where some vertices
* are supplied as their arguments.
*
* @param v The vertex to be checked.
* @throws InvalidVertexException If the supplied vertex is invalid.
*/
public abstract void checkVertex(VertexType v)
throws InvalidVertexException;
/**
* Returns a new instance of an empty graph of the current graph type.
*
* @return A new instance of an empty graph of the current graph type.
*/
public abstract <GraphType extends BaseGraph<VertexType, EdgeType>>
GraphType createEmptyGraph();
/**
* Returns array of vertices upcasted to BaseVertex.
*
* @return Array of vertices upcasted to BaseVertex.
*/
public abstract BaseVertex[] getVertexArray();
/**
* Returns array of array of 'int's where represents a simple adjacency list.
*
* @return Array of array of 'int's where represents a simple adjacency list.
*/
public abstract int[][] getEdgeArray();
/**
* Returns a light(weight) Edge Iterator object which iterates through all the edges in the graph.
* The light(weight) edge iterator presents an iterator with O(1) constructor. Note that you should
* not change the content of the graph during your iteration. You can still change properties of
* each edge or vertex.
*
* @return Returns a light(weight) Edge Iterator object.
*/
public abstract Iterator<EdgeType> lightEdgeIterator();
/**
* Constructs a light(weight) Edge Iterator object which iterates through all the edges going to
* or coming from the specified vertex <code>v</code>.
* The light(weight) edge iterator presents an iterator with O(1) constructor. Note that you should
* not change the content of the graph during your iteration. You can still change properties of
* each edge or vertex.
*
* @param v Source or target of desired edges.
* @return A light(weight) Edge Iterator object which iterates through all the edges going to
* or coming from the specified vertex.
*/
public abstract Iterator<EdgeType> lightEdgeIterator(VertexType v)
throws InvalidVertexException;
/**
* in a directed graph this method returns edges whose targets are v
*
* @param v The given vertex
* @return An iterator over the edges with the target v
*/
public abstract Iterator<EdgeType> lightBackEdgeIterator(VertexType v)
throws InvalidVertexException;
/**
* Clears the graph.
*/
public abstract void clear();
public abstract void setDirected(boolean isDirected);
/**
* If zero, indicates that the graph is not a subgraph. If greater than zero,
* it indicates that it's a subgraph with Id <code>subgraphId</code>.
*/
int subgraphIndex = 0;
/**
* Whether the graph is a subgraph. Then it shares it's contents.
*/
private boolean isSubgraph = false;
private BaseGraph<VertexType, EdgeType> superGraph = null;
/**
* Sets the graph as a subgraph.
*
* @param superGraph The supergraph
*/
public void registerSubgraph(BaseGraph<VertexType, EdgeType> superGraph) {
isSubgraph = true;
this.superGraph = superGraph;
superGraph.informVertices();
}
private void informVertices() {
if (isSubgraph)
superGraph.informVertices();
for (VertexType v : this) {
v.informNewSubgraph();
}
}
/**
* Get new id for a new subgraph;
*
*/
public int getNewSubgraphIndex() {
if (isSubgraph)
return superGraph.getNewSubgraphIndex();
int lastSubgraphIndex = 0;
return lastSubgraphIndex + 1;
}
/**
* Set's the subgraph index.
*
* @param i the subgraph index.
*/
public void setSubGraphIndex(int i) {
subgraphIndex = i;
}
/**
* A wrapper for getting vertex Id's which supports multiple vertex owners.
*
* @param v Vertex which the caller intends to get its Id.
* @return The Id.
*/
protected int getId(VertexType v) {
if (subgraphIndex != 0) {
return v.getSubgraphId(subgraphIndex);
}
return v.getId();
}
public abstract int getEdgesCount();
// ------------------- Some Helper Methods ----------------------
/**
* @see BaseGraph#lightEdgeIterator()
*/
public Iterable<EdgeType> edges() {
return new Iterable<EdgeType>() {
public Iterator<EdgeType> iterator() {
return lightEdgeIterator();
}
};
}
/**
* to make loop over edges connected to a vertex,
* for (EdgeType e: edges(v))
* yeah
*/
public Iterable<EdgeType> edges(final VertexType v){
return new Iterable<EdgeType>(){
@Override
public Iterator<EdgeType> iterator() {
return lightEdgeIterator(v);
}
};
}
/**
* Returns degree of vertex, the number of edges which their target or source is the specified vertex.
*
* @param vertex The given vertex
*/
public int getDegree(VertexType vertex) {
return isDirected() ? getInDegree(vertex) + getOutDegree(vertex) : getInDegree(vertex);
}
/**
* @param vertex The given vertex
* @return an Iterable object which can be iterated trough all neighbours of the given vertex using lightEdgeIterator(vertex)
* @see graphtea.library.BaseGraph#lightEdgeIterator(BaseVertex)
*/
public Iterable<VertexType> getNeighbors(final VertexType vertex) {
return new Iterable<VertexType>() {
public Iterator<VertexType> iterator() {
final Iterator<EdgeType> ei = lightEdgeIterator(vertex);
return new Iterator<VertexType>() {
public boolean hasNext() {
return ei.hasNext();
}
public VertexType next() {
EdgeType edg = ei.next();
if (edg.source == vertex)
return edg.target;
else
return edg.source;
}
public void remove() {
ei.remove();
}
};
}
};
}
/**
* Its the same as edges
*/
public Iterable<EdgeType> getEdges() {
return edges();
}
/**
* @return an Iterable which can iterated on all vertices of graph
*/
public Iterable<VertexType> vertices() {
return this;
}
/**
* this method is usefull in directed graphs which you want to know which vertices are sources of v(as target)
*
* @param vertex The given vertex
* @return an Iterable object which can be iterated trough all neighbours of the given vertex using lightEdgeIterator(vertex, false)
* @see ListGraph#lightBackEdgeIterator(graphtea.library.BaseVertex)
*/
public Iterable<VertexType> getBackNeighbours(final VertexType vertex) {
return new Iterable<VertexType>() {
public Iterator<VertexType> iterator() {
final Iterator<EdgeType> ei = lightBackEdgeIterator(vertex);
return new Iterator<VertexType>() {
public boolean hasNext() {
return ei.hasNext();
}
public VertexType next() {
EdgeType edg = ei.next();
if (edg.source == vertex)
return edg.target;
else
return edg.source;
}
public void remove() {
ei.remove();
}
};
}
};
}
//same as methods, yes we cool
/**
* same as #removeVertex
*/
public void deleteVertex(VertexType v){
removeVertex(v);
}
/**
* same as #removeEdge
*/
public void deleteEdge(EdgeType e){
removeEdge(e);
}
/**
* same as #getNeighbors
*/
public Iterable<VertexType> neighbors(final VertexType vertex) {
return getNeighbors(vertex);
}
/**
* same as #getBackNeighbors
*/
public Iterable<VertexType> backNeighbours(final VertexType vertex) {
return getBackNeighbours(vertex);
}
}