// Copyright (C) 1996 DIMACS Center, Rutgers, The State University of New Jersey
// Author(s): Jonathan Berry
// This software is copyrighted by the DIMACS Center at Rutgers, The State
// University of New Jersey.  IT IS PROVIDED AS IS, AND THE AUTHORS, DIMACS, AND
// RUTGERS, THE STATE UNIVERSITY OF NEW JERSEY  DISCLAIM
// ALL LIABILITY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
// DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
// IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
// NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
// MODIFICATIONS.
// The authors hereby grant permission to use, copy, modify, distribute,
// and license this software and its documentation for any purpose, provided
// that existing copyright notices are retained in all copies and that this
// notice is included verbatim in any distributions. No written agreement,
// license, or royalty fee is required for any of the authorized uses.
// Modifications to this software may be copyrighted by their authors
// and need not follow the licensing terms described here, provided that
// the new terms are clearly indicated on the first page of each file where
// they apply.
// Last File Update: 18-Jun-1997
// 
#ifndef Graph_h
#define Graph_h
#define EXTDEFS                 // must define this to prevent multiple
#include <LINK/graph/nauty.h>   // definitions of some nauty arrays
#include <LINK/graph/GraphObject.h>
#include <LINK/basic/MSet.h>
#include <LINK/basic/Set.h>
#include <LINK/basic/Sequence.h>
#include <LINK/basic/SortedArray.h>
#include <LINK/basic/Array.h>
#include <LINK/basic/general.h>
#include <LINK/basic/Matrix.h>
#define REVERSE 		1
#define CLONE 			1
#define LINK_STATIC 		1
#define LINK_DYNAMIC 		0
#define DEFAULT_WIDTH 		1
#define DEFAULT_SIZE 		10
#define DEFAULT_WEIGHT		((double)1.0)
#define DEFAULT_X               (0.5)
#define DEFAULT_Y               (0.5)
#define DEFAULT_COLOR_VERTEX 	BLUE
#define DEFAULT_COLOR_EDGE 	BLACK
#define DEFAULT_COLOR           BLACK
#define DEFAULT_LABEL           ((char*)"")
#define DEFAULT_MARK            (0)
#define DEFAULT_STARTTIME       (0)
#define DEFAULT_FINISHTIME      (0)
#define DEFAULT_BACK            (0)
#define DEFAULT_LOW             (0)
#define DEFAULT_DISTANCE        ((double)0)
#define DEFAULT_PRED            ((Vertex*)0)
#define DEFAULT_TYPE      0x00
#define TREE_EDGE_TYPE    0x11
#define CROSS_EDGE_TYPE   0x12
#define BACK_EDGE_TYPE    0x13
#define FORWARD_EDGE_TYPE 0x14
#define UNDIRECTED        0
#define DIRECTED          1
#define MIXED             2
#define SIMPLE		  0
#define MULTI		  1
#define HYPER		  0
#define BIN		  1

class Vertex;
class Edge;
class ostream;
//class DBinGraph;
//class UBinGraph;
class Graph : public GraphObject {
    friend class HyperGraph;		// this to protect the addEdge(Edge*)
					// and addVertex(Vertex*) methods
					// which subgraphs need but shouldn't
					// be available to objects
protected:
    Graph();
    Graph(const Graph &G, Flag clone=CLONE, Flag reverse=0);
    void			addVertex(Vertex* passed_vertex);
    friend class MHyperGraph;
public:
    virtual ~Graph();
				// managing subgraphs
    virtual Graph*		newGraph() = 0;
    virtual Graph*		copyGraph(Flag clone=CLONE, Flag reverse=0) = 0;
            Graph*		transpose(Flag clone=0)
				{ return copyGraph(clone, REVERSE); }
            Graph*		inducedSubgraph(Set<Vertex*>vs,Flag clone)const;
            Graph*		edgeInducedSubgraph(Set<Edge*>vs,
						    Flag clone) const;
            MSet<Edge*>		inducedEdges(Set<Vertex*> vs) const;
    	    Vertex*		addSubgraph(const List<Vertex*>& v);
    	    Vertex*		addSubgraph(const Set<Vertex*>& v);
   	    void 		expandComponents();
   	    void  		collapseComponents(Set<Set<Vertex*> >);
    virtual Set<Vertex*>	dissolveSubgraph(Vertex* super_vertex) = 0;
    virtual void		openSubgraph(Vertex* super_vertex) = 0;
    virtual void		closeSubgraph(Vertex* super_vertex) = 0;
    Bool			open();
				// add vertices
    Vertex*			addVertex(String passed_name);
    void			addVertices(int n);
				// remove from graph without destructor
				// the following 3 should be protected,	
				// but parser.y currently depends on seeing
				// them
    void			removeVertex(Vertex* passed_vertex);
    void			removeEdge(Edge* passed_edge);
   	    Matrix<double>    	adjacencyMatrix() const;
    virtual Edge*        	addEdge(Edge* passed_edge) = 0;
				// add edges to graph and vertices
    virtual Edge*       	addEdge(Collection<Vertex*>&vs, String n=0) = 0;
    virtual Edge*       	addEdge(Sequence<Vertex*> vs, String n=0) = 0;
    virtual Edge*       	addEdge(Vertex* v1, Vertex* v2, String n=0) = 0;
    virtual MSet<Edge*>       	addEdges(MSet<Set<Vertex*> > es);
    virtual MSet<Edge*>       	addEdges(MSet<Sequence<Vertex*> > es);
    void 			deleteEdges(MSet<Set<Vertex*> > es);
    void 			deleteEdges(MSet<Sequence<Vertex*> > es);
				// destructive remove from graph
    virtual void		deleteVertex(Vertex* passed_vertex) = 0;
    virtual void		deleteVertex(String name) = 0;
    virtual void		deleteEdge(Edge* passed_edge) = 0;
    void 	      		deleteEdge(Collection<Vertex*>&vs);
    void 	      		deleteEdge(Vertex* v1, Vertex* v2);
    				// subgraph add and remove is recursive up
    virtual void		subgraphAddVertex(Vertex* passed_vertex) = 0;
    virtual void		subgraphRemoveVertex(Vertex* passed_vertex) = 0;
    virtual void		subgraphAddEdge(Edge* passed_edge) = 0;
    virtual void		subgraphRemoveEdge(Edge* passed_edge) = 0;
    virtual Bool		internalEdge(Edge* passed_edge) const = 0;
            Bool		isomorphicQ(const Graph*) const;
            Bool		isomorphicQ(const Graph&) const;
            Bool		directedQ() const;
            Bool		binaryQ() const;
            Bool		simpleQ() const;
				// graph relationships
    virtual Bool		adjacentQ(Vertex* v1, Vertex* v2) const = 0;
    virtual MSet<Edge*>		incidentEdges(const Vertex* passed_vertex)
								const= 0;
    virtual MSet<Edge*>		inIncidentEdges(const Vertex* passed_vertex) 
								const= 0;
    virtual MSet<Edge*>		outIncidentEdges(const Vertex* passed_vertex)
								const= 0;
    virtual int			degree(const Vertex* passed_vertex)    const= 0;
    virtual int			inDegree(const Vertex* passed_vertex)  const= 0;
    virtual int			outDegree(const Vertex* passed_vertex) const= 0;
    int				maxDegree() const;
    int				minDegree() const;
				// bookkeeping
    const SortedArray<Vertex*>&	vertices() const;	   
    const MSet<Edge*>&		edges()	const	   { return _edges;           }
    Vertex**			vertexStart() const{ return _vertices.start();}
    int				order()       const{ return _vertices.size(); }
    Vertex*			vertex(int i) const{ return _vertices[i];     }
    Vertex*			randomVertex() const;
    int				rank(Vertex*v)const
						 { return _vertices.search(v);}
    Edge*			edge(int i) const{ return _edges.ref(i);      }
    int				rank(Edge*e)const
						 { return _edges.rank(e);}
    int				size() const     { return _edges.size();      }
    virtual DataType		type() const	 { return GRAPH;              }
    String			name() const;
    ostream&			display(ostream& os) const;
    void			display(int indent);
    virtual void		saveToFile(ofstream* fout) = 0;
    virtual void		saveToFile(ofstream* fout, int indent) = 0;
    Vertex*			findVertexByName(String name) const;
    Edge*			findEdgeByName(String name) const;
    Vertex*			findVertexWithEdge(Edge* edge) const;
    Edge*			isEdge(Vertex*, Vertex*) const;
    Edge*			isEdge(Edge*) const;
    Edge*			isEdge(const Collection<Vertex*>&,
				       int new_graph_type=MIXED) const;
    Bool			memberQ(Vertex* v) const;
    Bool			memberQ(Edge* e)   const;
    Sequence<Edge*>		pathEdges(Sequence<Vertex*> vs);
    Sequence<Vertex*>		pathVertices(Sequence<Edge*> es);
    Sequence<Edge*>		treePath(Vertex* ancestor, Vertex* descendent);
    String			makeVertexName();
    String			makeEdgeName();
    String			makeSubgraphName();
    void			setVertexName(int i)  {_cur_vertex_name = i;  }
    void			setEdgeName(int i)    {_cur_edge_name = i;    }
    void			setSubgraphName(int i){_cur_subgraph_name = i;}
    int 			operator<(const Graph& g) const;
    int 			operator==(const Graph& g) const;
    // uses GraphObject::operator<< now
    //friend ostream& operator<<(ostream& os, const Graph& g)
    //				{ return g.display(os); }
protected:
    virtual Vertex*		addSubgraph(Graph* owner, 	
					    const List<Vertex*>&v)= 0;
    ostream&			displayAllGraphObjects(ostream& os) const;
    SortedArray<Vertex*> 	_vertices;
    MSet<Edge*>			_edges;
    int				_cur_vertex_name;       // naming of vertices
    int				_cur_edge_name;         // naming of edges
    int				_cur_subgraph_name;     // naming of subgraphs
private:
    static int			graph_count;
};
int compareVertexNames(char *str1, char *str2); // definition in Vertex.cpp:
Graph *LoadGraph(char*); 		// definition in parseGraph.cpp
int    SaveGraph(Graph*, char*); 	// definition in GraphBuild.cpp
Graph *LoadDimacsGraph(char*); 		// definition in LoadDimacsGraph.cpp
int    SaveDimacsGraph(Graph*, char*);	// definition in SaveDimacsGraph.cpp
// definitions in AdjacencyMatrix.cpp
class MBinGraph;
Matrix<double> AdjacencyMatrix(const Graph *);
MBinGraph AdjacencyMatrix2Graph(const Matrix<int>&);
MBinGraph AdjacencyMatrix2Graph(const Matrix<double>&);
MBinGraph AdjacencyMatrix2Digraph(const Matrix<int>&);
MBinGraph AdjacencyMatrix2Digraph(const Matrix<double>&);
// definitions in IncidenceMatrix.cpp
Matrix<int> IncidenceMatrix(const Graph* graph, int direction=1);
MHyperGraph       IncidenceMatrix2Graph(const Matrix<int>&);
// definitions in LaplacianMatrix.cpp
Matrix<int> LaplacianMatrix(Matrix<int>& M);
// definitions in GraphBuild.cpp:
Graph* newEmpty(const Graph *);
Graph* multiGraph(const Graph *, Flag c=CLONE, Flag r=0);
Graph* simpleGraph(const Graph *, Flag c=CLONE, Flag r=0);
Graph* directedGraph(const Graph *, Flag c=CLONE, Flag r=0);
Graph* undirectedGraph(const Graph *, Flag c=CLONE, Flag r=0);
Graph* makeGraph(Set<Vertex*> vset, MSet<Edge*> eset);
Graph* makeGraph(MSet<Vertex*> vset, MSet<Set<Vertex*> > eset);
Graph* makeGraph(MSet<Vertex*> vset, MSet<Sequence<Vertex*> > eset);
Graph* makeGraph(MSet<char*> vset, MSet<Set<char*> > eset);
Graph* makeGraph(Set<char*> vseq, MSet<Sequence<char*> > eseq);
Graph* makeGraph(Set<int*> vset, MSet<Set<int*> > eset);
Graph* bipartiteRepresentation(Graph *);
//Graph* makeGraph(Set<int*> vseq, MSet<Sequence<int*> > eseq);
graph *nautyGraph(const Graph *);
graph *canonicalNautyGraph(const Graph *, graph *g, nvector *lab);
#endif
