/*******************************************************************\

Module:

Author: Daniel Kroening, kroening@kroening.com

\*******************************************************************/

#ifndef CPROVER_GRAPH_H
#define CPROVER_GRAPH_H

#include <list>
#include <sorted_vector.h>

class graph
{
public:
  typedef sorted_vector<unsigned, true> node_sett;

  class nodet
  {
  public:
    node_sett in, out;
    bool visited;
    
    // for Dijkstra
    unsigned distance, previous;
    
    // for the connected subgraphs
    unsigned subgraph_nr;
  };
  
protected:
  typedef std::vector<nodet> nodest;
  nodest nodes;
  
public:
  void swap(graph &other)
  {
    nodes.swap(other.nodes);
  }

  friend void intersection(
    const node_sett &a,
    const node_sett &b,
    node_sett &dest);
    
  bool has_edge(unsigned i, unsigned j) const
  {
    return nodes[i].out.find(j)!=nodes[i].out.end();
  }

  inline const nodet &operator[](unsigned n) const
  {
    return nodes[n];
  }

  inline nodet &operator[](unsigned n)
  {
    return nodes[n];
  }
  
  inline void resize(unsigned s)
  {
    nodes.resize(s);
  }
  
  inline unsigned size() const
  {
    return nodes.size();
  }
  
  inline const node_sett &in(unsigned n) const
  {
    return nodes[n].in;
  }

  inline const node_sett &out(unsigned n) const
  {
    return nodes[n].out;
  }
  
  void add_edge(unsigned a, unsigned b)
  {
    nodes[a].out.insert(b);
    nodes[b].in.insert(a);
  }
  
  void remove_edge(unsigned a, unsigned b)
  {
    nodes[a].out.erase(a);
    nodes[b].in.erase(a);
  }

  void add_undirected_edge(unsigned a, unsigned b);
  void remove_undirected_edge(unsigned a, unsigned b);
  void remove_in_edges(unsigned n);
  void remove_out_edges(unsigned n);
  
  void remove_edges(unsigned n)
  {
    remove_in_edges(n);
    remove_out_edges(n);
  }
  
  void clear_visited();
  
  void clear()
  {
    nodes.clear();
  }
  
  typedef std::list<unsigned> patht;
  
  void shortest_path(
    unsigned src,
    unsigned dest,
    patht &path);
    
  void visit_reachable(unsigned src);
  
  void make_chordal();
  
  // return value: number of connected subgraphs
  unsigned connected_subgraphs();
    
protected:
  void compute_path(unsigned dest, patht &path);
};

#endif
