// Graph of strongly connected components -*- c++ -*-

#ifndef COMPONENTGRAPH_H_
# define COMPONENTGRAPH_H_
# ifdef __GNUC__
#  pragma interface
# endif // __GNUC__
# include "typedefs.h"
# include "file.h"

/** @file ComponentGraph.h
 * Graph of strongly connected components
 */

/* Copyright © 2000-2001 Marko Mäkelä (msmakela@tcs.hut.fi).

   This file is part of MARIA, a reachability analyzer and model checker
   for high-level Petri nets.

   MARIA is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   MARIA is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */

/** Graph of strongly connected components */
class ComponentGraph
{
public:
  /** Constructor
   * @param graph	the underlying graph
   */
  explicit ComponentGraph (const class Graph& graph);
private:
  /** Copy constructor */
  ComponentGraph (const class ComponentGraph& old);
  /** Assignment operator */
  class ComponentGraph& operator= (const class ComponentGraph& old);
public:
  /** Destructor */
  ~ComponentGraph ();

private:
  /** Open the component graph files with temporary names
   * @return		true if everything succeeded
   */
  inline bool openFiles ();
  /** Set the component number of a state
   * @param state	the state
   * @param comp	the component
   */
  inline void setComponent (card_t state, card_t comp);
  /** Compute the arcs of the component graph */
  inline void computeArcs ();
public:

  /** Compute the strongly connected components
   * @param state	start state of the search
   * @param cond	condition for exploring states (NULL=true)
   * @return		number of strongly connected components (0=fail)
   */
  unsigned compute (card_t state,
		    const class Expression* cond);

  /** Determine the number of strongly connected components in the graph */
  unsigned size () const { return myNumComponents; }

  /** Determine the number of terminal components in the component graph */
  unsigned getNumTerminals () const { return myNumTerminals; }

  /** Determine the component a state belongs to
   * @param state	the state number
   * @return		the corresponding component, or CARD_T_MAX if none
   */
  card_t getComponent (card_t state) const;
  /** Determine the states a component consists of
   * @param comp	the component number
   * @return		the amount and numbers of the contained states
   */
  card_t* getStates (card_t comp) const;
  /** Determine the number of successors of a component
   * @param comp	the component number
   * @return		the number of successors
   */
  card_t getNumSucc (card_t comp) const;
  /** Determine the number of predecessors of a component
   * @param comp	the component number
   * @return		the number of predecessors
   */
  card_t getNumPred (card_t comp) const;
  /** Determine the successors of a component
   * @param comp	the component number
   * @return		the amount and numbers of the successor components
   */
  card_t* getSucc (card_t comp) const;
  /** Determine the predecessors of a component
   * @param comp	the component number
   * @return		the amount and numbers of the predecessor components
   */
  card_t* getPred (card_t comp) const;

  /** Determine the shortest path from a state to a component
   * @param state	the state number
   * @param comp	the component number
   * @param pathc	condition that must hold in every state on the path
   * @return		the amount and numbers of the states on the path
   */
  card_t* path (card_t state, card_t comp,
		const class Expression* pathc) const;

  /** Determine the shortest path to a state from a component
   * @param state	the state number
   * @param comp	the component number
   * @param pathc	condition that must hold in every state on the path
   * @return		the amount and numbers of the states on the path
   */
  card_t* rpath (card_t state, card_t comp,
		 const class Expression* pathc) const;

private:
  /** The underlying graph */
  const class Graph& myGraph;
  /** Number of components in the graph (0=not computed) */
  card_t myNumComponents;
  /** Number of terminal components in the graph (0=not computed) */
  card_t myNumTerminals;
  /** Mapping from state numbers to component numbers */
  file_t myStateComponents;
  /** Component directory */
  file_t myComponentDirectory;
  /** Mapping from component numbers to state numbers */
  FILE* myComponentStates;
  /** Successor components of a component (forward arcs) */
  FILE* mySuccComponents;
  /** Predecessor components of a component (backward arcs) */
  FILE* myPredComponents;
};

#endif // COMPONENTGRAPH_H_
