//==================================================================================================
// G r a p h                                                                              Interface
// A l g o r i t h m
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library 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 Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This module provides basic algorithms for graphs. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "graph/algorithm.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guGraphAlgorithm
#define guGraphAlgorithm

// Headers //---------------------------------------------------------------------------------------
#include <algorithm> /*INCLUDE*/
#include <bpp/graph/structure.hpp> /*INCLUDE*/

namespace bpp {

// Importation/Exportation //-----------------------------------------------------------------------
#ifdef GRAPH_DLL
 #define dll_export DLL_EXPORT
#else
 #define dll_export DLL_IMPORT
#endif

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphAlgorithm
#define private_area graphAlgorithm_private

namespace public_area  { /*NAMESPACE*/ using namespace graphStructure; }
namespace private_area { using namespace public_area; }

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniGraphAlgorithm
has_initializer;

// Macrocommands //---------------------------------------------------------------------------------
/*ALIAS*/
#define tdGraph class prArcData,class prNodeData //

/*ALIAS*/
#define tuGraph prArcData,prNodeData //

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Classes
 template <tdGraph> class clArcAdmissibility;
 template <tdGraph> class clDecreaseDegreeNodeOrder;
 template <tdGraph> class clIncreaseDegreeNodeOrder;
 template <tdGraph> class clMintyColor;
 //-----------------------------------------------------------------------------------Variable Types
 /*TYPE*/ /* Cocycle of a graph (association of arc keys with their direction in the cocycle). */
 typedef std_map(tyArcKey,tyInteger) clCocycle;

 /*TYPE*/ /* Cycle of a graph (association of arc keys with their direction in the cycle). */
 typedef std_map(tyArcKey,tyInteger) clCycle;

 /*TYPE*/ /* List of cocycles. */
 typedef std_vector(clCocycle) clCocycleS;

 /*TYPE*/ /* List of cycles. */
 typedef std_vector(clCycle) clCycleS;

 /*TYPE*/ /* Symbolic constants for the colors used by a Minty coloration. */
 enumeration { green, black, blue, red } tyMintyColor;
 //-----------------------------------------------------------------------------------Constant Types
 typedef const clCocycle  ctCocycle;
 typedef const clCocycleS ctCocycleS;
 typedef const clCycle    ctCycle;
 typedef const clCycleS   ctCycleS;

 typedef const tyMintyColor tcMintyColor;
}

namespace private_area {
 template <tdGraph> class clMintyColorForCircuitDetection;
 template <tdGraph> class clMintyColorForCycleDetection;
 template <tdGraph> class clStandardArcAdmissibility;
}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {
 template <tdGraph> void eliminateNonCycles(clGraph<tuGraph> &);

 template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) &,
                                     std_vector(clArc<tuGraph> *) &,std_vector(clArc<tuGraph> *) &);

 template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) &,
                                     std_map(clArc<tuGraph> *,tyInteger) &);

 template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) &,clCocycle &);
 template <tdGraph> void findCycles(clGraph<tuGraph> &,clCycleS &,tyBoolean=false);

 template <tdGraph> void findCycles(clGraph<tuGraph> &,
                                    std_vector(std_map(clArc<tuGraph> *,tyInteger)) &,
                                    tyBoolean=false);

 template <tdGraph> void findFirstNodes(const clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &);
 template <tdGraph> void findLastNodes(const clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &);

 template <tdGraph> clNode<tuGraph> * firstNode(const clGraph<tuGraph> &);
 template <tdGraph> clNode<tuGraph> * lastNode(const clGraph<tuGraph> &);

 template <tdGraph>
 tyNodeKey addSourceNode(clGraph<tuGraph> &,const prArcData &,const prNodeData &);

 template <tdGraph>
 tyNodeKey addTargetNode(clGraph<tuGraph> &,const prArcData &,const prNodeData &);

 template <tdGraph,class prMintyColor>
 tyBoolean findMintyCycle(clGraph<tuGraph> &,tyArcKey,const prMintyColor &,clCycle &,clCocycle &);

 template <tdGraph,class prMintyColor>
 tyBoolean findMintyCycle(clArc<tuGraph> &,const prMintyColor &,
                          std_map(clArc<tuGraph> *,tyInteger) &,
                          std_map(clArc<tuGraph> *,tyInteger) &);

 template <tdGraph> tyBoolean findCircuit(clGraph<tuGraph> &,tyArcKey,clCycle &);
 template <tdGraph> tyBoolean findCycle(clGraph<tuGraph> &,tyArcKey,clCycle &);
 template <tdGraph> tyBoolean findCircuit(clArc<tuGraph> &,std_map(clArc<tuGraph> *,tyInteger) &);
 template <tdGraph> tyBoolean findCycle(clArc<tuGraph> &,std_map(clArc<tuGraph> *,tyInteger) &);

 template <tdGraph> void findCoveringTree(clGraph<tuGraph> &,clGraph<tuGraph> &);

 function clOutStream & operator << (clOutStream &,ctCycle &);

 template <tdGraph>
 function clOutStream & operator << (clOutStream &,const std_map(clArc<tuGraph> *,tyInteger) &);

 template <tdGraph,class prArcAdmissibility>
 tyBoolean findTopologicalOrdering(clGraph<tuGraph> &,const prArcAdmissibility &,
                                   std_vector(clNode<tuGraph> *) &);

 template <tdGraph>
 tyBoolean findTopologicalOrdering(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &);
}

namespace private_area {
 template <tdGraph>
 void destructCycle(const std_vector(clArc<tuGraph> *) &,std_vector(clNode<tuGraph> *) &);

 template <tdGraph,class prMintyColor>
 tyBoolean findMintyCycle(clArc<tuGraph> &,const prMintyColor &,
                          std_vector(clNode<tuGraph> *) &,std_vector(clArc<tuGraph> *) &,
                          std_vector(tyCardinal) &,tyCardinal &);

 template <tdGraph>
 void makeCycleDeepTree(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &,
                        std_vector(clArc<tuGraph> *) &,std_vector(tyCardinal) &);

 template <tdGraph>
 void makeCycleBroadTree(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &,
                         std_vector(clArc<tuGraph> *) &,std_vector(tyCardinal) &);

 template <tdGraph>
 void makeCycle(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &,std_vector(clArc<tuGraph> *) &,
                std_vector(tyCardinal) &,clCycle &,const clArc<tuGraph> &);

 template <tdGraph>
 void makeCycle(clGraph<tuGraph> &,std_vector(clNode<tuGraph> *) &,std_vector(clArc<tuGraph> *) &,
                std_vector(tyCardinal) &,std_map(clArc<tuGraph> *,tyInteger) &,clArc<tuGraph> &);

 testing_mode ( function void test(void); )
}

// Errors //----------------------------------------------------------------------------------------
namespace public_area {
 /*ERROR*/ extern_error erGraphNotConnex; /* The graph is not connex. */
}

// Constants & Variables //-------------------------------------------------------------------------
extern_dynamic_constant(private,clString,goDataLocation,?);

// A r c A d m i s s i b i l i t y  Interface //----------------------------------------------------
namespace public_area {
 /*CLASS clArcAdmissibility */
 /* This class represents arc admissibility. It is used to know if an arc is admissible or not,
    using it in the direct or indirect direction. This object is given as argument to functions
    that search nodes in a graph where only admissible arcs are used (in the direction(s) they
    are admissible for). This class is abstract. */
 template <tdGraph> class clArcAdmissibility {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clArcAdmissibility */ /* Type of arc this object checks. */
  public_property typedef clArc<tuGraph> cpArc;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clArcAdmissibility(const clArcAdmissibility &);
  private_property clArcAdmissibility & operator = (const clArcAdmissibility &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clArcAdmissibility(void);
  public_property virtual destructor clArcAdmissibility(void);

  /*AMETHOD clArcAdmissibility */
  /* Indicates if an arc is admissible in the direct direction. Abstract method. */
  public_property virtual tyBoolean direct(const cpArc &) const = 0;

  /*AMETHOD clArcAdmissibility */
  /* Indicates if an arc is admissible in the indirect direction. Abstract method. */
  public_property virtual tyBoolean indirect(const cpArc &) const = 0;
 };
}

// D e c r e a s e D e g r e e N o d e O r d e r i n g  Interface //--------------------------------
namespace public_area {
 /*CLASS clDecreaseDegreeNodeOrder */
 /* This class represents an ordering between two nodes, based on their degree. <I>x</I>
    is before <I>y</I> if its degree is greater than <I>y</I>'s one. It is a functor
    that can be used by STL functions to sort nodes. */
 template <tdGraph> class clDecreaseDegreeNodeOrder {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clDecreaseDegreeNodeOrder */ /* Type of node this object compares. */
  public_property typedef clNode<tuGraph> cpNode;
  //------------------------------------------------------------------------------------------Public
  public_property constructor clDecreaseDegreeNodeOrder(void);
  public_property constructor clDecreaseDegreeNodeOrder(const clDecreaseDegreeNodeOrder &);
  public_property destructor clDecreaseDegreeNodeOrder(void);

  public_property clDecreaseDegreeNodeOrder & operator = (const clDecreaseDegreeNodeOrder &);
  public_property tyBoolean operator () (cpNode *,cpNode *) const;
 };
}

// I n c r e a s e D e g r e e N o d e O r d e r i n g  Interface //--------------------------------
namespace public_area {
 /*CLASS clIncreaseDegreeNodeOrder */
 /* This class represents an ordering between two nodes, based on their degree. <I>x</I>
    is before <I>y</I> if its degree is lower than <I>y</I>'s one. It is a functor
    that can be used by STL functions to sort nodes. */
 template <tdGraph> class clIncreaseDegreeNodeOrder {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clIncreaseDegreeNodeOrder */ /* Type of node this object compares. */
  public_property typedef clNode<tuGraph> cpNode;
  //------------------------------------------------------------------------------------------Public
  public_property constructor clIncreaseDegreeNodeOrder(void);
  public_property constructor clIncreaseDegreeNodeOrder(const clIncreaseDegreeNodeOrder &);
  public_property destructor clIncreaseDegreeNodeOrder(void);

  public_property clIncreaseDegreeNodeOrder & operator = (const clIncreaseDegreeNodeOrder &);
  public_property tyBoolean operator () (cpNode *,cpNode *) const;
 };
}

// M i n t y C o l o r  Interface //----------------------------------------------------------------
namespace public_area {
 /*CLASS clMintyColor */
 /* This class represents a Minty coloration. It is used to define the color wanted for the arcs
    of a graph. This object is given as argument to the Minty cycle search function. This class
    is abstract. */
 template <tdGraph> class clMintyColor {
  //-------------------------------------------------------------------------------------------Types
  /*TYPE clMintyColor */ /* Type of arc this object colors. */
  public_property typedef clArc<tuGraph> cpArc;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clMintyColor(const clMintyColor &);
  private_property clMintyColor & operator = (const clMintyColor &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clMintyColor(void);
  public_property virtual destructor clMintyColor(void);

  /*AMETHOD clMintyColor */ /* Indicates if an arc is red. Abstract method. */
  public_property virtual tyBoolean red(const cpArc &) const = 0;

  /*AMETHOD clMintyColor */ /* Indicates if an arc is black. Abstract method. */
  public_property virtual tyBoolean black(const cpArc &) const = 0;

  /*AMETHOD clMintyColor */ /* Indicates if an arc is black. Abstract method. */
  public_property virtual tyBoolean blue(const cpArc &) const = 0;

  /*AMETHOD clMintyColor */ /* Indicates if an arc is green. Abstract method. */
  public_property virtual tyBoolean green(const cpArc &) const = 0;

  public_property tcString color(const cpArc &) const;
 };
}

// M i n t y C o l o r F o r C i r c u i t D e t e c t i o n  Interface //--------------------------
namespace private_area {
 template <tdGraph> class clMintyColorForCircuitDetection {
  //-------------------------------------------------------------------------------------------Types
  public_property typedef clArc<tuGraph> cpArc;
  //-----------------------------------------------------------------------------------------Private
  private_property
  constructor clMintyColorForCircuitDetection(const clMintyColorForCircuitDetection &);

  private_property
  clMintyColorForCircuitDetection & operator = (const clMintyColorForCircuitDetection &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clMintyColorForCircuitDetection(void) {}
  public_property destructor clMintyColorForCircuitDetection(void) {}

  public_property tyBoolean red(const cpArc &) const;
  public_property tyBoolean black(const cpArc &) const;
  public_property tyBoolean blue(const cpArc &) const;
  public_property tyBoolean green(const cpArc &) const;

  public_property tcString color(const cpArc &) const;
 };
}

// M i n t y C o l o r F o r C y c l e D e t e c t i o n  Interface //------------------------------
namespace private_area {
 template <tdGraph> class clMintyColorForCycleDetection {
  //-------------------------------------------------------------------------------------------Types
  public_property typedef clArc<tuGraph> cpArc;
  //-----------------------------------------------------------------------------------------Private
  private_property
  constructor clMintyColorForCycleDetection(const clMintyColorForCycleDetection &);

  private_property
  clMintyColorForCycleDetection & operator = (const clMintyColorForCycleDetection &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clMintyColorForCycleDetection(void) {}
  public_property destructor clMintyColorForCycleDetection(void) {}

  public_property tyBoolean red(const cpArc &) const;
  public_property tyBoolean black(const cpArc &) const;
  public_property tyBoolean blue(const cpArc &) const;
  public_property tyBoolean green(const cpArc &) const;

  public_property tcString color(const cpArc &) const;
 };
}

// S t a n d a r d A r c A d m i s s i b i l i t y  Interface //------------------------------------
namespace private_area {
 template <tdGraph> class clStandardArcAdmissibility {
  //-------------------------------------------------------------------------------------------Types
  public_property typedef clArc<tuGraph> cpArc;
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clStandardArcAdmissibility(const clStandardArcAdmissibility &);
  private_property clStandardArcAdmissibility & operator = (const clStandardArcAdmissibility &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clStandardArcAdmissibility(void) {}
  public_property destructor clStandardArcAdmissibility(void) {}

  public_property tyBoolean direct(const cpArc &) const { return (true); }
  public_property tyBoolean indirect(const cpArc &) const { return (false); }
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------FirstNode
 /*FUNCTION*/
 /* Returns the node of a graph that has no predecessor. If no such node exists or if more than one
    such node exist, then <CODE>nil</CODE> is returned. */
 template <tdGraph> inline clNode<tuGraph> * firstNode(const clGraph<tuGraph> & agGraph) {
  std_vector(clNode<tuGraph> *) lcNodeS;

  findFirstNodes(agGraph,lcNodeS);
  if (lcNodeS.size()!=1) return (nil);
  return (*(lcNodeS.begin()));
 }
 //-----------------------------------------------------------------------------------------LastNode
 /*FUNCTION*/
 /* Returns the node of a graph that has no successor. If no such node exists or if more than one
    such node exist, then <CODE>nil</CODE> is returned. */
 template <tdGraph> inline clNode<tuGraph> * lastNode(const clGraph<tuGraph> & agGraph) {
  std_vector(clNode<tuGraph> *) lcNodeS;

  findLastNodes(agGraph,lcNodeS);
  if (lcNodeS.size()!=1) return (nil);
  return (*(lcNodeS.begin()));
 }
 //--------------------------------------------------------------------------------------FindCircuit
 /*FUNCTION*/
 /* Finds a circuit containing a given arc. Returns <CODE>false</CODE> if there is no such
    circuit. The result is a list containing the arc keys of the circuit with their direction
    (always +1). */
 template <tdGraph>
 inline tyBoolean findCircuit(clGraph<tuGraph> & agGraph,tyArcKey agArcKey,clCycle & agCircuit) {
  clCocycle                                              lcCocycle;
  private_area::clMintyColorForCircuitDetection<tuGraph> lcMintyColor;

  return (findMintyCycle(agGraph,agArcKey,lcMintyColor,agCircuit,lcCocycle));
 }
 //----------------------------------------------------------------------------------------FindCycle
 /*FUNCTION*/
 /* Finds a cycle containing a given arc. Returns <CODE>false</CODE> if there is no such cycle. The
    result is a list containing the arc keys of the cycle with their direction. */
 template <tdGraph>
 inline tyBoolean findCycle(clGraph<tuGraph> & agGraph,tyArcKey agArcKey,clCycle & agCycle) {
  clCocycle                                            lcCocycle;
  private_area::clMintyColorForCycleDetection<tuGraph> lcMintyColor;

  return (findMintyCycle(agGraph,agArcKey,lcMintyColor,agCycle,lcCocycle));
 }
 //--------------------------------------------------------------------------------------FindCircuit
 /*FUNCTION*/
 /* Finds a circuit containing a given arc. Returns <CODE>false</CODE> if there is no such
    circuit. The result is a list containing the arc memory pointers of the circuit with their
    direction (always +1). */
 template <tdGraph> inline
 tyBoolean findCircuit(clArc<tuGraph> & agArc,std_map(clArc<tuGraph> *,tyInteger) & agCircuit) {
  std_map(clArc<tuGraph> *,tyInteger)                    lcCocycle;
  private_area::clMintyColorForCircuitDetection<tuGraph> lcMintyColor;

  return (findMintyCycle(agArc,lcMintyColor,agCircuit,lcCocycle));
 }
 //----------------------------------------------------------------------------------------FindCycle
 /*FUNCTION*/
 /* Finds a cycle containing a given arc. Returns <CODE>false</CODE> if there is no such cycle. The
    result is a list containing the arc memory pointers of the cycle with their direction. */
 template <tdGraph>
 inline tyBoolean findCycle(clArc<tuGraph> & agArc,std_map(clArc<tuGraph> *,tyInteger) & agCycle) {
  std_map(clArc<tuGraph> *,tyInteger)                  lcCocycle;
  private_area::clMintyColorForCycleDetection<tuGraph> lcMintyColor;

  return (findMintyCycle(agArc,lcMintyColor,agCycle,lcCocycle));
 }
 //--------------------------------------------------------------------------FindTopologicalOrdering
 /*FUNCTION*/
 /* Finds a topological ordering of the nodes of a graph. There must be no circuit.
    Returns <CODE>true</CODE> if an ordering is found. The result is an ordered list containing
    the node memory pointers. */
 template <tdGraph>
 inline tyBoolean findTopologicalOrdering(clGraph<tuGraph> & agGraph,
                                          std_vector(clNode<tuGraph> *) & agNodeS) {
  private_area::clStandardArcAdmissibility<tuGraph> lcAdmissibility;

  return (findTopologicalOrdering(agGraph,lcAdmissibility,agNodeS));
 }
}

namespace private_area {}

// A r c A d m i s s i b i l i t y  Inline //-------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clArcAdmissibility */ /* Builds an arc admissibility. */
 template <tdGraph> inline clArcAdmissibility<tuGraph>::clArcAdmissibility(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clArcAdmissibility */ /* Destructs the arc admissibility. */
 template <tdGraph> inline clArcAdmissibility<tuGraph>::~clArcAdmissibility(void) {}
}

// D e c r e a s e D e g r e e N o d e O r d e r i n g  Inline //-----------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDecreaseDegreeNodeOrder */ /* Builds a node ordering. */
 template <tdGraph>
 inline clDecreaseDegreeNodeOrder<tuGraph>::clDecreaseDegreeNodeOrder(void) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clDecreaseDegreeNodeOrder */ /* Builds a node ordering by copying another one. */
 template <tdGraph> inline clDecreaseDegreeNodeOrder<tuGraph>::
                           clDecreaseDegreeNodeOrder(const clDecreaseDegreeNodeOrder &) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clDecreaseDegreeNodeOrder */ /* Destructs the ordering. */
 template <tdGraph> inline clDecreaseDegreeNodeOrder<tuGraph>::~clDecreaseDegreeNodeOrder(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clDecreaseDegreeNodeOrder */ /* Copies an ordering. */
 template <tdGraph> inline clDecreaseDegreeNodeOrder<tuGraph> &
 clDecreaseDegreeNodeOrder<tuGraph>::operator = (const clDecreaseDegreeNodeOrder &)
 { return (*this); }
 //--------------------------------------------------------------------------------------Operator ()
 /*METHOD clDecreaseDegreeNodeOrder */ /* Compares two nodes. */
 template <tdGraph> inline tyBoolean
 clDecreaseDegreeNodeOrder<tuGraph>::operator () (cpNode * agNode1,cpNode * agNode2) const {
  tyCardinal lcDegree1 = agNode1->incomingArcs().size()+agNode1->outgoingArcs().size();
  tyCardinal lcDegree2 = agNode2->incomingArcs().size()+agNode2->outgoingArcs().size();

  return (lcDegree1>lcDegree2);
 }
}

// I n c r e a s e D e g r e e N o d e O r d e r i n g  Inline //-----------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clIncreaseDegreeNodeOrder */ /* Builds a node ordering. */
 template <tdGraph>
 inline clIncreaseDegreeNodeOrder<tuGraph>::clIncreaseDegreeNodeOrder(void) {}
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clIncreaseDegreeNodeOrder */ /* Builds a node ordering by copying another one. */
 template <tdGraph> inline clIncreaseDegreeNodeOrder<tuGraph>::
                           clIncreaseDegreeNodeOrder(const clIncreaseDegreeNodeOrder &) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clIncreaseDegreeNodeOrder */ /* Destructs the ordering. */
 template <tdGraph> inline clIncreaseDegreeNodeOrder<tuGraph>::~clIncreaseDegreeNodeOrder(void) {}
 //---------------------------------------------------------------------------------------Operator =
 /*METHOD clIncreaseDegreeNodeOrder */ /* Copies an ordering. */
 template <tdGraph> inline clIncreaseDegreeNodeOrder<tuGraph> &
 clIncreaseDegreeNodeOrder<tuGraph>::operator = (const clIncreaseDegreeNodeOrder &)
 { return (*this); }
 //--------------------------------------------------------------------------------------Operator ()
 /*METHOD clIncreaseDegreeNodeOrder */ /* Compares two nodes. */
 template <tdGraph> inline tyBoolean
 clIncreaseDegreeNodeOrder<tuGraph>::operator () (cpNode * agNode1,cpNode * agNode2) const {
  tyCardinal lcDegree1 = agNode1->incomingArcs().size()+agNode1->outgoingArcs().size();
  tyCardinal lcDegree2 = agNode2->incomingArcs().size()+agNode2->outgoingArcs().size();

  return (lcDegree1<lcDegree2);
 }
}

// M i n t y  C o l o r  Inline //------------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clMintyColor */ /* Builds the Minty coloration. */
 template <tdGraph> inline clMintyColor<tuGraph>::clMintyColor(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clMintyColor */ /* Destructs the Minty coloration. */
 template <tdGraph> inline clMintyColor<tuGraph>::~clMintyColor(void) {}
}

// M i n t y C o l o r F o r C i r c u i t D e t e c t i o n  Inline //-----------------------------
namespace private_area {
 //----------------------------------------------------------------------------------------------Red
 template <tdGraph>
 inline tyBoolean clMintyColorForCircuitDetection<tuGraph>::red(const cpArc &) const
 { return (false); }
 //--------------------------------------------------------------------------------------------Black
 template <tdGraph>
 inline tyBoolean clMintyColorForCircuitDetection<tuGraph>::black(const cpArc &) const
 { return (true); }
 //---------------------------------------------------------------------------------------------Blue
 template <tdGraph>
 inline tyBoolean clMintyColorForCircuitDetection<tuGraph>::blue(const cpArc &) const
 { return (false); }
 //--------------------------------------------------------------------------------------------Green
 template <tdGraph>
 inline tyBoolean clMintyColorForCircuitDetection<tuGraph>::green(const cpArc &) const
 { return (false); }
}

// M i n t y C o l o r F o r C y c l e D e t e c t i o n  Inline //---------------------------------
namespace private_area {
 //----------------------------------------------------------------------------------------------Red
 template <tdGraph>
 inline tyBoolean clMintyColorForCycleDetection<tuGraph>::red(const cpArc &) const
 { return (false); }
 //--------------------------------------------------------------------------------------------Black
 template <tdGraph>
 inline tyBoolean clMintyColorForCycleDetection<tuGraph>::black(const cpArc &) const
 { return (false); }
 //---------------------------------------------------------------------------------------------Blue
 template <tdGraph>
 inline tyBoolean clMintyColorForCycleDetection<tuGraph>::blue(const cpArc &) const
 { return (false); }
 //--------------------------------------------------------------------------------------------Green
 template <tdGraph>
 inline tyBoolean clMintyColorForCycleDetection<tuGraph>::green(const cpArc &) const
 { return (true); }
}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //-------------------------------------------------------------------------------EliminateNonCycles
 /*FUNCTION*/ /* Eliminates the arcs and the nodes of a graph that do not belong to any cycle. */
 template <tdGraph> void eliminateNonCycles(clGraph<tuGraph> & agGraph) {
  typedef clGraph<tuGraph>                          cpGraph;
  typedef clNode<tuGraph>                           cpNode;
  typedef typename cpGraph::cpNodeX::const_iterator cpNodeIterator;

  cpNode * lcNode;

  cpNodeIterator lcCurrentNode = agGraph.nodes().begin();
  cpNodeIterator lcLastNode    = agGraph.nodes().end();

  while (lcCurrentNode!=lcLastNode) {
   lcNode=(*lcCurrentNode).second;
   if (lcNode->outgoingArcs().size()+lcNode->incomingArcs().size() < 2) {
    delete_object(lcNode);
    lcCurrentNode=agGraph.nodes().begin();
   }
   else lcCurrentNode++;
  }
 }
 //--------------------------------------------------------------------------------------FindCocycle
 /*FUNCTION*/
 /* Finds the cocycle that separates a group of nodes from the rest of a graph. The result is the
    list of the incoming arcs and the list of the outgoing arcs. */
 template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) & agNodeS,
                                     std_vector(clArc<tuGraph> *) & agIncomingArcS,
                                     std_vector(clArc<tuGraph> *) & agOutgoingArcS) {
  typedef typename clNode<tuGraph>::cpArcX::const_iterator       clArcIterator;
  typedef typename std_vector(clNode<tuGraph> *)::const_iterator clNodeIterator;

  clArc<tuGraph> * lcArc;
  clArcIterator    lcCurrentArc;
  clArcIterator    lcLastArc;

  if (agNodeS.empty()) return;

  clNodeIterator     lcCurrentNode = agNodeS.begin();
  clNodeIterator     lcLastNode    = agNodeS.end();
  clGraph<tuGraph> & lcGraph       = (*(lcCurrentNode))->graph();
  tyMark             lcBothMark    = ++(lcGraph.mark());
  tyMark             lcSourceMark  = ++(lcGraph.mark());
  tyMark             lcTargetMark  = ++(lcGraph.mark());
  tyCardinal         lcNbIncoming  = 0;
  tyCardinal         lcNbOutgoing  = 0;

  while (lcCurrentNode!=lcLastNode) {
   lcCurrentArc=(*lcCurrentNode)->incomingArcs().begin();
   lcLastArc=(*lcCurrentNode)->incomingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=(*lcCurrentArc).second;
    lcCurrentArc++;

    if (lcArc->mark()==lcSourceMark) {
     lcArc->mark()=lcBothMark;
     lcNbOutgoing--;
    }
    else {
     lcArc->mark()=lcTargetMark;
     lcNbIncoming++;
    }
   }

   lcCurrentArc=(*lcCurrentNode)->outgoingArcs().begin();
   lcLastArc=(*lcCurrentNode)->outgoingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=(*lcCurrentArc).second;
    lcCurrentArc++;

    if (lcArc->mark()==lcTargetMark) {
     lcArc->mark()=lcBothMark;
     lcNbIncoming--;
    }
    else {
     lcArc->mark()=lcSourceMark;
     lcNbOutgoing++;
    }
   }

   lcCurrentNode++;
  }

  agOutgoingArcS.reserve(agOutgoingArcS.size()+lcNbOutgoing);
  agIncomingArcS.reserve(agIncomingArcS.size()+lcNbIncoming);

  lcCurrentArc=lcGraph.arcs().begin();
  lcLastArc=lcGraph.arcs().end();

  while (lcCurrentArc!=lcLastArc) {
   lcArc=(*lcCurrentArc).second;

   if (lcArc->mark()==lcSourceMark) agOutgoingArcS.push_back(lcArc);
   else if (lcArc->mark()==lcTargetMark) agIncomingArcS.push_back(lcArc);

   lcCurrentArc++;
  }
 }
 //--------------------------------------------------------------------------------------FindCocycle
 /*FUNCTION*/
 /* Finds the cocycle that separates a group of nodes from the rest of a graph. The result is a
    list containing the arc keys and their direction in the cocycle. */
 template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) & agNodeS,
                                     clCocycle & agCocycle) {
  typedef typename clNode<tuGraph>::cpArcX::const_iterator       clArcIterator;
  typedef typename std_vector(clNode<tuGraph> *)::const_iterator clNodeIterator;

  clArc<tuGraph>* lcArc;
  clArcIterator   lcCurrentArc;
  clArcIterator   lcLastArc;

  if (agNodeS.empty()) return;

  clNodeIterator     lcCurrentNode = agNodeS.begin();
  clNodeIterator     lcLastNode    = agNodeS.end();
  clGraph<tuGraph> & lcGraph       = (*(lcCurrentNode))->graph();
  tyMark             lcBothMark    = ++(lcGraph.mark());
  tyMark             lcSourceMark  = ++(lcGraph.mark());
  tyMark             lcTargetMark  = ++(lcGraph.mark());

  while (lcCurrentNode!=lcLastNode) {
   lcCurrentArc=(*lcCurrentNode)->incomingArcs().begin();
   lcLastArc=(*lcCurrentNode)->incomingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=(*lcCurrentArc).second;
    lcCurrentArc++;

    if (lcArc->mark()==lcSourceMark) lcArc->mark()=lcBothMark;
    else lcArc->mark()=lcTargetMark;
   }

   lcCurrentArc=(*lcCurrentNode)->outgoingArcs().begin();
   lcLastArc=(*lcCurrentNode)->outgoingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=(*lcCurrentArc).second;
    lcCurrentArc++;

    if (lcArc->mark()==lcTargetMark) lcArc->mark()=lcBothMark;
    else lcArc->mark()=lcSourceMark;
   }

   lcCurrentNode++;
  }

  lcCurrentArc=lcGraph.arcs().begin();
  lcLastArc=lcGraph.arcs().end();

  while (lcCurrentArc!=lcLastArc) {
   lcArc=(*lcCurrentArc).second;

   if (lcArc->mark()==lcSourceMark) agCocycle.insert(clCocycle::value_type(lcArc->key(),+1));
   else if (lcArc->mark()==lcTargetMark) agCocycle.insert(clCocycle::value_type(lcArc->key(),-1));

   lcCurrentArc++;
  }
 }
 //--------------------------------------------------------------------------------------FindCocycle
 /*FUNCTION*/
 /* Finds the cocycle that separates a group of nodes from the rest of a graph. The result is a
    list containing the arc memory pointers and their direction in the cocycle. */
 template <tdGraph> void findCocycle(const std_vector(clNode<tuGraph> *) & agNodeS,
                                     std_map(clArc<tuGraph> *,tyInteger) & agCocycle) {
  typedef typename clNode<tuGraph>::cpArcX::const_iterator       clArcIterator;
  typedef typename std_vector(clNode<tuGraph> *)::const_iterator clNodeIterator;

  clArc<tuGraph>* lcArc;
  clArcIterator   lcCurrentArc;
  clArcIterator   lcLastArc;

  if (agNodeS.empty()) return;

  clNodeIterator     lcCurrentNode = agNodeS.begin();
  clNodeIterator     lcLastNode    = agNodeS.end();
  clGraph<tuGraph> & lcGraph       = (*(lcCurrentNode))->graph();
  tyMark             lcBothMark    = ++(lcGraph.mark());
  tyMark             lcSourceMark  = ++(lcGraph.mark());
  tyMark             lcTargetMark  = ++(lcGraph.mark());

  while (lcCurrentNode!=lcLastNode) {
   lcCurrentArc=(*lcCurrentNode)->incomingArcs().begin();
   lcLastArc=(*lcCurrentNode)->incomingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=(*lcCurrentArc).second;
    lcCurrentArc++;

    if (lcArc->mark()==lcSourceMark) lcArc->mark()=lcBothMark;
    else lcArc->mark()=lcTargetMark;
   }

   lcCurrentArc=(*lcCurrentNode)->outgoingArcs().begin();
   lcLastArc=(*lcCurrentNode)->outgoingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=(*lcCurrentArc).second;
    lcCurrentArc++;

    if (lcArc->mark()==lcTargetMark) lcArc->mark()=lcBothMark;
    else lcArc->mark()=lcSourceMark;
   }

   lcCurrentNode++;
  }

  lcCurrentArc=lcGraph.arcs().begin();
  lcLastArc=lcGraph.arcs().end();

  while (lcCurrentArc!=lcLastArc) {
   lcArc=(*lcCurrentArc).second;

   if (lcArc->mark()==lcSourceMark) agCocycle.insert(std_make_pair(lcArc,+1));
   else if (lcArc->mark()==lcTargetMark) agCocycle.insert(std_make_pair(lcArc,-1));

   lcCurrentArc++;
  }
 }
 //---------------------------------------------------------------------------------------FindCycles
 /*FUNCTION*/
 /* Finds as independent cycles as possible in the graph. Any cycle in the graph is a linear
    combination of these cycles. In other word, any cycle in the graph can be recomposed from those
    cycles. The result is a list of cycles, each cycle is a list containing the arc keys and their
    direction in the cycle. The algorithm can be forced to find short cycles (default is not). */
 template <tdGraph> void findCycles(clGraph<tuGraph> & agGraph,clCycleS & agCycleS,
                                    tyBoolean agShort) {
  typedef clArc<tuGraph>                                    cpArc;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef std_vector(clArc<tuGraph> *)                      cpArcS;
  typedef std_vector(tyCardinal)                            cpIndexS;
  typedef std_vector(clNode<tuGraph> *)                     cpNodeS;

  cpArc *    lcArc;
  cpArcS     lcArcS(agGraph.nodes().size());
  tyMark     lcMark;
  cpNodeS    lcNodeS(agGraph.nodes().size());
  cpIndexS   lcPreviousS(agGraph.nodes().size());

  cpArcIterator lcCurrentArc = agGraph.arcs().begin();
  cpArcIterator lcLastArc    = agGraph.arcs().end();

  if (agShort) private_area::makeCycleBroadTree(agGraph,lcNodeS,lcArcS,lcPreviousS);
  else private_area::makeCycleDeepTree(agGraph,lcNodeS,lcArcS,lcPreviousS);

  agCycleS.erase(agCycleS.begin(),agCycleS.end());
  lcMark=agGraph.mark();

  while (lcCurrentArc!=lcLastArc) {
   lcArc=(*lcCurrentArc).second;

   if (lcArc->mark()!=lcMark) {
    agCycleS.push_back(clCycle());
    private_area::makeCycle(agGraph,lcNodeS,lcArcS,lcPreviousS,agCycleS.back(),*lcArc);
   }

   ++lcCurrentArc;
  }
 }
 //---------------------------------------------------------------------------------------FindCycles
 /*FUNCTION*/
 /* Finds as independent cycles as possible in the graph. Any cycle in the graph is a linear
    combination of these cycles. In other word, any cycle in the graph can be recomposed from those
    cycles. The result is a list of cycles, each cycle is a list containing the arc memory pointers
    and their direction in the cycle. The algorithm can be forced to find short cycles (default is
    not). */
 template <tdGraph> void findCycles(clGraph<tuGraph> & agGraph,
                                    std_vector(std_map(clArc<tuGraph> *,tyInteger)) & agCycleS,
                                    tyBoolean agShort) {
  typedef clArc<tuGraph>                                    cpArc;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef std_vector(clArc<tuGraph> *)                      cpArcS;
  typedef std_map(clArc<tuGraph> *,tyInteger)               cpCycle;
  typedef std_vector(tyCardinal)                            cpIndexS;
  typedef std_vector(clNode<tuGraph> *)                     cpNodeS;

  cpArc *    lcArc;
  cpArcS     lcArcS(agGraph.nodes().size());
  tyMark     lcMark;
  cpNodeS    lcNodeS(agGraph.nodes().size());
  cpIndexS   lcPreviousS(agGraph.nodes().size());

  cpArcIterator lcCurrentArc = agGraph.arcs().begin();
  cpArcIterator lcLastArc    = agGraph.arcs().end();

  if (agShort) private_area::makeCycleBroadTree(agGraph,lcNodeS,lcArcS,lcPreviousS);
  else private_area::makeCycleDeepTree(agGraph,lcNodeS,lcArcS,lcPreviousS);

  agCycleS.erase(agCycleS.begin(),agCycleS.end());
  lcMark=agGraph.mark();

  while (lcCurrentArc!=lcLastArc) {
   lcArc=(*lcCurrentArc).second;
   if (lcArc->mark()!=lcMark) {
    agCycleS.push_back(cpCycle());
    private_area::makeCycle(agGraph,lcNodeS,lcArcS,lcPreviousS,agCycleS.back(),*lcArc);
   }

   ++lcCurrentArc;
  }
 }
 //-----------------------------------------------------------------------------------FindFirstNodes
 /*FUNCTION*/ /* Finds in a graph the nodes that have no predecessor. */
 template <tdGraph>
 void findFirstNodes(const clGraph<tuGraph> & agGraph, std_vector(clNode<tuGraph> *) & agNodeS) {
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;

  cpNodeIterator lcCurrentNode = agGraph.nodes().begin();
  cpNodeIterator lcLastNode    = agGraph.nodes().end();

  while (lcCurrentNode!=lcLastNode) {
   if ((*lcCurrentNode).second->incomingArcs().size()==0)
    agNodeS.push_back((*lcCurrentNode).second);

   lcCurrentNode++;
  }
 }
 //------------------------------------------------------------------------------------FindLastNodes
 /*FUNCTION*/ /* Finds in a graph the nodes that have no successor. */
 template <tdGraph>
 void findLastNodes(const clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS) {
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;

  cpNodeIterator lcCurrentNode = agGraph.nodes().begin();
  cpNodeIterator lcLastNode    = agGraph.nodes().end();

  while (lcCurrentNode!=lcLastNode) {
   if ((*lcCurrentNode).second->outgoingArcs().size()==0)
    agNodeS.push_back((*lcCurrentNode).second);

   lcCurrentNode++;
  }
 }
 //------------------------------------------------------------------------------------AddSourceNode
 /*FUNCTION*/
 /* Adds a node to a graph. This node becomes the predecessor of all the nodes that had not one. */
 template <tdGraph> tyNodeKey addSourceNode(clGraph<tuGraph> & agGraph,
                                            const prArcData & agArcData,
                                            const prNodeData & agNodeData) {
  typedef clArc<tuGraph>       cpArc;
  typedef clNode<tuGraph>      cpNode;
  typedef std_vector(cpNode *) cpNodeS;

  typedef typename cpNodeS::const_iterator                    cpNodeIterator1;
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator  cpNodeIterator2;
  typedef typename clGraph<tuGraph>::cpNodeX::difference_type cpNodeDistance;

  cpNodeIterator1 lcCurrentNode;
  cpNodeIterator1 lcLastNode;
  cpNodeS         lcNodeS;
  cpNodeIterator2 lcRandomNode;
  cpNode *        lcSourceNode;

  findFirstNodes(agGraph,lcNodeS);
  lcCurrentNode=lcNodeS.begin();
  lcLastNode=lcNodeS.end();
  if (lcNodeS.size()==1) return ((*lcCurrentNode)->key());
  lcSourceNode=new_object(cpNode(agGraph,agGraph.getNewNodeKey(),agNodeData));

  if (lcNodeS.size()==0) {
   do {
    lcRandomNode=agGraph.nodes().begin();
    std_advance(lcRandomNode,cpNodeDistance(randomCardinal(agGraph.nodes().size())));
   }
   while (lcSourceNode->key()==(*lcRandomNode).second->key());

   new_object(cpArc(agGraph,agGraph.getNewArcKey(),agArcData,
                    lcSourceNode->key(),(*lcRandomNode).second->key()));
  }
  else {
   while (lcCurrentNode!=lcLastNode) {
    new_object(cpArc(agGraph,agGraph.getNewArcKey(),agArcData,
                     lcSourceNode->key(),(*lcCurrentNode)->key()));

    lcCurrentNode++;
   }
  }

  return (lcSourceNode->key());
 }
 //------------------------------------------------------------------------------------AddTargetNode
 /*FUNCTION*/
 /* Adds a node to a graph. This node becomes the successor of all the nodes that had not one. */
 template <tdGraph> tyNodeKey addTargetNode(clGraph<tuGraph> & agGraph,
                                            const prArcData & agArcData,
                                            const prNodeData & agNodeData) {
  typedef clArc<tuGraph>       cpArc;
  typedef clNode<tuGraph>      cpNode;
  typedef std_vector(cpNode *) cpNodeS;

  typedef typename cpNodeS::const_iterator                    cpNodeIterator1;
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator  cpNodeIterator2;
  typedef typename clGraph<tuGraph>::cpNodeX::difference_type cpNodeDistance;

  cpNodeIterator1 lcCurrentNode;
  cpNodeIterator1 lcLastNode;
  cpNodeS         lcNodeS;
  cpNodeIterator2 lcRandomNode;
  cpNode *        lcTargetNode;

  findLastNodes(agGraph,lcNodeS);
  lcCurrentNode=lcNodeS.begin();
  lcLastNode=lcNodeS.end();
  if (lcNodeS.size()==1) return ((*lcCurrentNode)->key());
  lcTargetNode=new_object(cpNode(agGraph,agGraph.getNewNodeKey(),agNodeData));

  if (lcNodeS.size()==0) {
   do {
    lcRandomNode=agGraph.nodes().begin();
    std_advance(lcRandomNode,cpNodeDistance(randomCardinal(agGraph.nodes().size())));
   }
   while ((*lcRandomNode).second->key()==lcTargetNode->key());

   new_object(cpArc(agGraph,agGraph.getNewArcKey(),agArcData,
                    (*lcRandomNode).second->key(),lcTargetNode->key()));
  }
  else {
   while (lcCurrentNode!=lcLastNode) {
    new_object(cpArc(agGraph,agGraph.getNewArcKey(),agArcData,
                     (*lcCurrentNode)->key(),lcTargetNode->key()));

    lcCurrentNode++;
   }
  }

  return (lcTargetNode->key());
 }
 //-----------------------------------------------------------------------------------FindMintyCycle
 /*FUNCTION*/
 /* Finds a cycle or a cocycle according to a Minty coloration. It searchs a cycle that contains a
    given arc <I>x</I>. Moreover any other arc in the cycle must be green, blue or black. Green
    arcs can be in the same direction as <I>x</I> or in the opposite direction, blue arcs must be
    in the opposite direction and black ones in the same direction. If no such cycle exists, there
    must be a cocycle containing <I>x</I> that have only red, blue and black arcs. Red arcs can be
    in the same direction as <I>x</I> or in the opposite direction, blue arcs must be in the
    opposite direction and black ones in the same direction. The result is a list containing the
    arc keys with their direction. */
 template <tdGraph,class prMintyColor>
 tyBoolean findMintyCycle(clGraph<tuGraph> & agGraph,tyArcKey agKey,const prMintyColor & agTest,
                          clCycle & agCycle,clCocycle & agCocycle) {
  typedef std_vector(clArc<tuGraph> *)  cpArcS;
  typedef std_vector(clNode<tuGraph> *) cpNodeS;
  typedef std_vector(tyCardinal)        cpIndexS;

  cpArcS     lcArcS(agGraph.nodes().size());
  tyCardinal lcNbMark;
  cpNodeS    lcNodeS(agGraph.nodes().size());
  cpIndexS   lcPreviousS(agGraph.nodes().size());

  clCocycle::iterator lcCurrentArc;
  tyCardinal          lcIndex;
  clCocycle::iterator lcLastArc;

  agCycle.erase(agCycle.begin(),agCycle.end());
  agCocycle.erase(agCocycle.begin(),agCocycle.end());

  // Cycle Construction //
  if (private_area::findMintyCycle(agGraph.arc(agKey),agTest,lcNodeS,
                                   lcArcS,lcPreviousS,lcNbMark)) {
   if (lcNbMark>0) {
    lcIndex=lcNbMark-1;

    while (lcArcS[lcIndex]!=nil) {
     if (lcArcS[lcIndex]->targetNode()==lcNodeS[lcIndex])
      agCycle.insert(clCycle::value_type(lcArcS[lcIndex]->key(),+1));
     else
      agCycle.insert(clCycle::value_type(lcArcS[lcIndex]->key(),-1));

     lcIndex=lcPreviousS[lcIndex];
    }
   }

   agCycle.insert(clCycle::value_type(agKey,+1));
   return (true);
  }

  // Cocycle Construction //
  else {
   lcNodeS.resize(lcNbMark);
   findCocycle(lcNodeS,agCocycle);
   lcCurrentArc=agCocycle.begin();
   lcLastArc=agCocycle.end();

   while (lcCurrentArc!=lcLastArc) {
    (*lcCurrentArc).second*=-1;
    lcCurrentArc++;
   }

   return (false);
  }
 }
 //-----------------------------------------------------------------------------------FindMintyCycle
 /*FUNCTION*/
 /* Finds a cycle or a cocycle according to a Minty coloration. It searchs a cycle that contains a
    given arc <I>x</I>. Moreover any other arc in the cycle must be green, blue or black. Green
    arcs can be in the same direction as <I>x</I> or in the opposite direction, blue arcs must be
    in the opposite direction and black ones in the same direction. If no such cycle exists, there
    must be a cocycle containing <I>x</I> that have only red, blue and black arcs. Red arcs can be
    in the same direction as <I>x</I> or in the opposite direction, blue arcs must be in the
    opposite direction and black ones in the same direction. The result is a list containing the
    arc memory pointers with their direction. */
 template <tdGraph,class prMintyColor>
 tyBoolean findMintyCycle(clArc<tuGraph> & agArc,const prMintyColor & agTest,
                          std_map(clArc<tuGraph> *,tyInteger) & agCycle,
                          std_map(clArc<tuGraph> *,tyInteger) & agCocycle) {
  typedef std_vector(clArc<tuGraph> *)        cpArcS;
  typedef std_map(clArc<tuGraph> *,tyInteger) cpCocycle;
  typedef std_vector(tyCardinal)              cpIndexS;
  typedef typename cpCocycle::iterator        cpIterator;
  typedef std_vector(clNode<tuGraph> *)       cpNodeS;

  clGraph<tuGraph> & lcGraph = agArc.graph();

  cpArcS     lcArcS(lcGraph.nodes().size());
  tyCardinal lcNbMark;
  cpNodeS    lcNodeS(lcGraph.nodes().size());
  cpIndexS   lcPreviousS(lcGraph.nodes().size());

  cpIterator lcCurrentArc;
  cpIterator lcLastArc;
  tyCardinal lcIndex;

  agCycle.erase(agCycle.begin(),agCycle.end());
  agCocycle.erase(agCocycle.begin(),agCocycle.end());

  // Cycle Construction //
  if (private_area::findMintyCycle(agArc,agTest,lcNodeS,lcArcS,lcPreviousS,lcNbMark)) {
   if (lcNbMark>0) {
    lcIndex=lcNbMark-1;

    while (lcArcS[lcIndex]!=nil) {
     if (lcArcS[lcIndex]->targetNode()==lcNodeS[lcIndex])
      agCycle.insert(std_make_pair(lcArcS[lcIndex],+1));
     else
      agCycle.insert(std_make_pair(lcArcS[lcIndex],-1));

     lcIndex=lcPreviousS[lcIndex];
    }
   }

   agCycle.insert(std_make_pair(&agArc,+1));
   return (true);
  }

  // Cocycle Construction //
  else {
   lcNodeS.resize(lcNbMark);
   findCocycle(lcNodeS,(std_map(clArc<tuGraph> *,tyInteger) &)agCocycle);
   lcCurrentArc=agCocycle.begin();
   lcLastArc=agCocycle.end();

   while (lcCurrentArc!=lcLastArc) {
    (*lcCurrentArc).second*=-1;
    lcCurrentArc++;
   }

   return (false);
  }
 }
 //---------------------------------------------------------------------------------FindCoveringTree
 /*FUNCTION*/ /* Finds a covering tree in a graph. */
 template <tdGraph> void findCoveringTree(clGraph<tuGraph> & agGraph,clGraph<tuGraph> & agTree) {
  method_name("findCoveringTree");

  typedef clArc<tuGraph>                          cpArc;
  typedef clNode<tuGraph>                         cpNode;
  typedef typename cpNode::cpArcX::const_iterator cpArcIterator;

  tyMark lcMark = ++(agGraph.mark());

  cpArc *              lcArc;
  cpArcIterator        lcCurrentArc;
  cpArcIterator        lcLastArc;
  cpNode *             lcNode1;
  cpNode *             lcNode2;
  std_vector(cpNode *) lcNodeS;

  agTree.clear();
  lcNode1=(*agGraph.nodes().begin()).second;
  lcNodeS.push_back(lcNode1);
  lcNode1->mark()=lcMark;
  new_object(cpNode(agTree,*lcNode1));

  while (lcNodeS.size()!=0) {
   lcNode1=lcNodeS.back();
   lcNodeS.pop_back();

   // Outgoing Arcs //
   lcCurrentArc=lcNode1->outgoingArcs().begin();
   lcLastArc=lcNode1->outgoingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=(*lcCurrentArc).second;
    lcNode2=lcArc->targetNode();

    if (lcNode2->mark()!=lcMark) {
     lcNodeS.push_back(lcNode2);
     lcNode2->mark()=lcMark;
     new_object(cpNode(agTree,*lcNode2));
     new_object(cpArc(agTree,*lcArc));
    }

    lcCurrentArc++;
   }

   // Incoming Arcs //
   lcCurrentArc=lcNode1->incomingArcs().begin();
   lcLastArc=lcNode1->incomingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=(*lcCurrentArc).second;
    lcNode2=lcArc->sourceNode();

    if (lcNode2->mark()!=lcMark) {
     lcNodeS.push_back(lcNode2);
     lcNode2->mark()=lcMark;
     new_object(cpNode(agTree,*lcNode2));
     new_object(cpArc(agTree,*lcArc));
    }

    lcCurrentArc++;
   }
  }

  if (agTree.nodes().size()!=agGraph.nodes().size()) send_error(erGraphNotConnex);
 }
 //----------------------------------------------------------------------Operator << (Cycle/Cocycle)
 /*FUNCTION*/ /* Writes a cycle or a cocycle into a stream. */
 template <tdGraph>
 clOutStream & operator << (clOutStream & agStream,
                            const std_map(clArc<tuGraph> *,tyInteger) & agCycle) {
  typedef typename std_map(clArc<tuGraph> *,tyInteger)::const_iterator cpIterator;

  clCycle lcCycle;

  cpIterator lcCurrentArc = agCycle.begin();
  cpIterator lcLastArc    = agCycle.end();

  while (lcCurrentArc!=lcLastArc) {
   lcCycle.insert(std_make_pair(lcCurrentArc->first->key(),lcCurrentArc->second));
   ++lcCurrentArc;
  }

  agStream << lcCycle;

  return (agStream);
 }
 //--------------------------------------------------------------------------FindTopologicalOrdering
 /*FUNCTION*/
 /* Finds a topological ordering of the nodes of a graph. There must be no circuit.
    Returns <CODE>true</CODE> if an ordering is found. The result is an ordered list containing
    the node memory pointers. An object with the <CODE>clArcAdmissibility</CODE> interface is
    given to indicate if an arc must be used (in the direct or indirect direction) during the
    search. Check the <CODE>clArcAdmissibility</CODE> class for more details. */
 template <tdGraph,class prArcAdmissibility>
 tyBoolean findTopologicalOrdering(clGraph<tuGraph> & agGraph,const prArcAdmissibility & agTest,
                                   std_vector(clNode<tuGraph> *) & agNodeS) {
  typedef typename clNode<tuGraph>::cpArcX::const_iterator   cpArcIterator;
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;

  clArc<tuGraph> *      lcArc;
  tyCardinal            lcCounter;
  cpArcIterator         lcCurrentArc;
  tyBoolean             lcError;
  cpArcIterator         lcLastArc;
  std_vector(tyPointer) lcWorkS;
  clNode<tuGraph> *     lcNode;
  tyCardinal *          lcNumber;

  cpNodeIterator    lcCurrentNode = agGraph.nodes().begin();
  cpNodeIterator    lcLastNode    = agGraph.nodes().end();

  // Workspace Saving & Initialization //
  while (lcCurrentNode!=lcLastNode) {
   lcNode=(*lcCurrentNode).second;
   lcWorkS.push_back(lcNode->work());
   lcNode->work()=new_object(tyCardinal);
   ++lcCurrentNode;
  }

  agNodeS.erase(agNodeS.begin(),agNodeS.end());

  // First Nodes Search //
  lcCurrentNode=agGraph.nodes().begin();
  lcLastNode=agGraph.nodes().end();

  while (lcCurrentNode!=lcLastNode) {
   lcNode=(*lcCurrentNode).second;
   lcNumber=(tyCardinal *)lcNode->work();
   *lcNumber=0;
   lcCurrentArc=lcNode->incomingArcs().begin();
   lcLastArc=lcNode->incomingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    if (agTest.direct(*((*lcCurrentArc).second))) ++(*lcNumber);
    ++lcCurrentArc;
   }

   lcCurrentArc=lcNode->outgoingArcs().begin();
   lcLastArc=lcNode->outgoingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    if (agTest.indirect(*((*lcCurrentArc).second))) ++(*lcNumber);
    ++lcCurrentArc;
   }

   if (*lcNumber==0) agNodeS.push_back(lcNode);
   ++lcCurrentNode;
  }

  // Graph Search //
  lcCounter=0;

  while (lcCounter<agNodeS.size()) {
   lcNode=agNodeS[lcCounter];
   lcCurrentArc=lcNode->outgoingArcs().begin();
   lcLastArc=lcNode->outgoingArcs().end();

   while (lcCurrentArc!=lcLastArc) {
    lcArc=(*lcCurrentArc).second;

    if (agTest.direct(*lcArc)) {
     lcNumber=(tyCardinal *)lcArc->targetNode()->work();

     if (*lcNumber==0) {
      lcError=true;
      goto lbEnd;
     }

     --(*lcNumber);
     if (*lcNumber==0) agNodeS.push_back(lcArc->targetNode());
    }

    ++lcCurrentArc;
   }

   lcCurrentArc=lcNode->incomingArcs().begin();
   lcLastArc=lcNode->incomingArcs().end();

   while (lcCurrentArc!=lcLastArc) {

    if (agTest.indirect(*((*lcCurrentArc).second))) {
     lcArc=(*lcCurrentArc).second;
     lcNumber=(tyCardinal *)lcArc->sourceNode()->work();

     if (*lcNumber==0) {
      lcError=true;
      goto lbEnd;
     }

     --(*lcNumber);
     if (*lcNumber==0) agNodeS.push_back(lcArc->sourceNode());
    }

    ++lcCurrentArc;
   }

   ++lcCounter;
  }

  lcError=(agNodeS.size()!=agGraph.nodes().size());

  // Workspace Restoring //
  lbEnd:
  lcCurrentNode=agGraph.nodes().begin();
  lcLastNode=agGraph.nodes().end();
  lcCounter=0;

  while (lcCurrentNode!=lcLastNode) {
   lcNode=(*lcCurrentNode).second;
   delete_object((tyCardinal *)lcNode->work());
   lcNode->work()=lcWorkS[lcCounter];
   ++lcCounter;
   ++lcCurrentNode;
  }

  return (not lcError);
 }
}

namespace private_area {
 //-----------------------------------------------------------------------------------FindMintyCycle
 template <tdGraph,class prMintyColor>
 tyBoolean findMintyCycle(clArc<tuGraph> & agArc,const prMintyColor & agTest,
                          std_vector(clNode<tuGraph> *) & agNodeS,
                          std_vector(clArc<tuGraph> *) & agArcS,
                          std_vector(tyCardinal) & agPreviousS,tyCardinal & agNbMark) {
  typedef clArc<tuGraph>                                   cpArc;
  typedef std_vector(tyCardinal)                           cpIndexS;
  typedef clNode<tuGraph>                                  cpNode;
  typedef std_vector(clNode<tuGraph> *)                    cpNodeS;
  typedef typename clNode<tuGraph>::cpArcX::const_iterator cpArcIterator;

  cpArc *       lcArc;
  tyCardinal    lcCounter;
  cpArcIterator lcCurrentArc;
  tyCardinal    lcCurrentCounter;
  cpArcIterator lcLastArc;
  tyCardinal    lcNextCounter;
  cpNode *      lcNode;

  clGraph<tuGraph> & lcGraph      = agArc.graph();
  tyBoolean          lcCycleFound = false;
  tyMark             lcMark       = ++(lcGraph.mark());
  cpNode *           lcSourceNode = agArc.sourceNode();
  cpNode *           lcTargetNode = agArc.targetNode();

  cpIndexS * lcCurrentIndexS = new_object(cpIndexS(lcGraph.nodes().size()));
  cpNodeS *  lcCurrentNodeS  = new_object(cpNodeS(lcGraph.nodes().size()));
  cpIndexS * lcNextIndexS    = new_object(cpIndexS(lcGraph.nodes().size()));
  cpNodeS *  lcNextNodeS     = new_object(cpNodeS(lcGraph.nodes().size()));

  lcTargetNode->mark()=lcMark;
  (*lcNextNodeS)[0]=lcTargetNode;
  (*lcNextIndexS)[0]=0;
  lcNextCounter=1;
  agNodeS[0]=lcTargetNode;
  agArcS[0]=nil;
  agPreviousS[0]=0;
  agNbMark=1;

  while ((not lcCycleFound) and lcNextCounter>0) {
   standard::swap(lcCurrentNodeS,lcNextNodeS);
   standard::swap(lcCurrentIndexS,lcNextIndexS);
   lcCurrentCounter=lcNextCounter;
   lcNextCounter=0;
   lcCounter=0;

   while ((not lcCycleFound) and lcCounter<lcCurrentCounter) {

    // Incoming Arcs //
    lcCurrentArc=(*lcCurrentNodeS)[lcCounter]->incomingArcs().begin();
    lcLastArc=(*lcCurrentNodeS)[lcCounter]->incomingArcs().end();

    while ((not lcCycleFound) and lcCurrentArc!=lcLastArc) {
     lcArc=(*lcCurrentArc).second;
     lcNode=lcArc->sourceNode();

     if (lcArc->key()!=agArc.key() and lcNode->mark()!=lcMark) {
      if (agTest.green(*lcArc) or agTest.blue(*lcArc)) {
       lcNode->mark()=lcMark;
       (*lcNextNodeS)[lcNextCounter]=lcNode;
       (*lcNextIndexS)[lcNextCounter++]=agNbMark;
       agNodeS[agNbMark]=lcNode;
       agArcS[agNbMark]=lcArc;
       agPreviousS[agNbMark++]=(*lcCurrentIndexS)[lcCounter];
       lcCycleFound=(lcNode==lcSourceNode);
      }
     }

     lcCurrentArc++;
    }

    // Outgoing Arcs //
    lcCurrentArc=(*lcCurrentNodeS)[lcCounter]->outgoingArcs().begin();
    lcLastArc=(*lcCurrentNodeS)[lcCounter]->outgoingArcs().end();

    while ((not lcCycleFound) and lcCurrentArc!=lcLastArc) {
     lcArc=(*lcCurrentArc).second;
     lcNode=lcArc->targetNode();

     if (lcArc->key()!=agArc.key() and lcNode->mark()!=lcMark) {
      if (agTest.green(*lcArc) or agTest.black(*lcArc)) {
       lcNode->mark()=lcMark;
       (*lcNextNodeS)[lcNextCounter]=lcNode;
       (*lcNextIndexS)[lcNextCounter++]=agNbMark;
       agNodeS[agNbMark]=lcNode;
       agArcS[agNbMark]=lcArc;
       agPreviousS[agNbMark++]=(*lcCurrentIndexS)[lcCounter];
       lcCycleFound=(lcNode==lcSourceNode);
      }
     }

     lcCurrentArc++;
    }

    lcCounter++;
   }
  }

  delete_object(lcCurrentIndexS);
  delete_object(lcCurrentNodeS);
  delete_object(lcNextIndexS);
  delete_object(lcNextNodeS);
  return (lcCycleFound);
 }
 //----------------------------------------------------------------------------------------MakeCycle
 template <tdGraph>
 void makeCycle(clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS,
                std_vector(clArc<tuGraph> *) & agArcS,std_vector(tyCardinal) & agPreviousS,
                clCycle & agCycle,const clArc<tuGraph> & agArc) {
  clArc<tuGraph> * lcArc;
  tyCardinal       lcCommonIndex;
  tyCardinal       lcIndex;

  tyMark     lcMark        = ++(agGraph.mark());
  tyCardinal lcSourceIndex = 0;
  tyCardinal lcTargetIndex = 0;

  while (agNodeS[lcSourceIndex]!=agArc.sourceNode()) lcSourceIndex++;
  while (agNodeS[lcTargetIndex]!=agArc.targetNode()) lcTargetIndex++;
  lcIndex=lcTargetIndex;
  agNodeS[lcIndex]->mark()=lcMark;

  while (agArcS[lcIndex]!=nil) {
   lcIndex=agPreviousS[lcIndex];
   agNodeS[lcIndex]->mark()=lcMark;
  }

  lcCommonIndex=lcSourceIndex;
  agCycle.insert(clCycle::value_type(agArc.key(),+1));

  while (agNodeS[lcCommonIndex]->mark()!=lcMark and agArcS[lcCommonIndex]!=nil) {
   lcArc=agArcS[lcCommonIndex];

   if (lcArc->sourceNode()==agNodeS[lcCommonIndex])
    agCycle.insert(clCycle::value_type(lcArc->key(),-1));
   else
    agCycle.insert(clCycle::value_type(lcArc->key(),+1));

   lcCommonIndex=agPreviousS[lcCommonIndex];
  }

  lcIndex=lcTargetIndex;

  while (lcIndex!=lcCommonIndex) {
   lcArc=agArcS[lcIndex];

   if (lcArc->sourceNode()==agNodeS[lcIndex])
    agCycle.insert(clCycle::value_type(lcArc->key(),+1));
   else
    agCycle.insert(clCycle::value_type(lcArc->key(),-1));

   lcIndex=agPreviousS[lcIndex];
  }
 }
 //----------------------------------------------------------------------------------------MakeCycle
 template <tdGraph>
 void makeCycle(clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS,
                std_vector(clArc<tuGraph> *) & agArcS,std_vector(tyCardinal) & agPreviousS,
                std_map(clArc<tuGraph> *,tyInteger) & agCycle,clArc<tuGraph> & agArc) {
  clArc<tuGraph> * lcArc;
  tyCardinal       lcCommonIndex;
  tyCardinal       lcIndex;

  tyMark     lcMark        = ++(agGraph.mark());
  tyCardinal lcSourceIndex = 0;
  tyCardinal lcTargetIndex = 0;

  while (agNodeS[lcSourceIndex]!=agArc.sourceNode()) lcSourceIndex++;
  while (agNodeS[lcTargetIndex]!=agArc.targetNode()) lcTargetIndex++;
  lcIndex=lcTargetIndex;
  agNodeS[lcIndex]->mark()=lcMark;

  while (agArcS[lcIndex]!=nil) {
   lcIndex=agPreviousS[lcIndex];
   agNodeS[lcIndex]->mark()=lcMark;
  }

  lcCommonIndex=lcSourceIndex;
  agCycle.insert(std_make_pair(&agArc,+1));

  while (agNodeS[lcCommonIndex]->mark()!=lcMark and agArcS[lcCommonIndex]!=nil) {
   lcArc=agArcS[lcCommonIndex];

   if (lcArc->sourceNode()==agNodeS[lcCommonIndex]) agCycle.insert(std_make_pair(lcArc,-1));
   else agCycle.insert(std_make_pair(lcArc,+1));

   lcCommonIndex=agPreviousS[lcCommonIndex];
  }

  lcIndex=lcTargetIndex;

  while (lcIndex!=lcCommonIndex) {
   lcArc=agArcS[lcIndex];

   if (lcArc->sourceNode()==agNodeS[lcIndex]) agCycle.insert(std_make_pair(lcArc,+1));
   else agCycle.insert(std_make_pair(lcArc,-1));

   lcIndex=agPreviousS[lcIndex];
  }
 }
 //--------------------------------------------------------------------------------MakeCycleDeepTree
 template <tdGraph>
 void makeCycleDeepTree(clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS,
                        std_vector(clArc<tuGraph> *) & agArcS,
                        std_vector(tyCardinal) & agPreviousS) {
  typedef clGraph<tuGraph>                          cpGraph;
  typedef typename cpGraph::cpArcX::const_iterator  cpArcIterator;
  typedef std_vector(tyCardinal)                    cpIndexS;
  typedef clNode<tuGraph>                           cpNode;
  typedef typename cpGraph::cpNodeX::const_iterator cpNodeIterator;
  typedef std_vector(clNode<tuGraph> *)             cpNodeS;

  cpArcIterator lcCurrentArc;
  tyCardinal    lcCurrentCounter;
  tyCardinal    lcIndex;
  cpIndexS      lcIndexS(agGraph.nodes().size());
  cpArcIterator lcLastArc;
  tyCardinal    lcNbMark;
  cpNode *      lcNextNode;
  cpNode *      lcNode;
  tyCardinal    lcNodeCounter;
  cpNodeS       lcNodeS(agGraph.nodes().size());

  cpNodeIterator lcCurrentNode = agGraph.nodes().begin();
  cpNodeIterator lcLastNode    = agGraph.nodes().end();
  tyMark         lcMark        = ++(agGraph.mark());

  lcNbMark=0;
  lcNodeCounter=0;

  while (lcCurrentNode!=lcLastNode) {
   lcNode=(*lcCurrentNode).second;

   if (lcNode->mark()!=lcMark) {
    lcNode->mark()=lcMark;
    lcNodeS[lcNodeCounter]=lcNode;
    lcIndexS[lcNodeCounter++]=lcNbMark;
    agNodeS[lcNbMark]=lcNode;
    agArcS[lcNbMark]=nil;
    agPreviousS[lcNbMark++]=0;

    while (lcNodeCounter>0) {
     lcCurrentCounter=--lcNodeCounter;
     lcNode=lcNodeS[lcCurrentCounter];
     lcIndex=lcIndexS[lcCurrentCounter];

     lcCurrentArc=lcNode->outgoingArcs().begin();
     lcLastArc=lcNode->outgoingArcs().end();

     while (lcCurrentArc!=lcLastArc) {
      lcNextNode=(*lcCurrentArc).second->targetNode();

      if (lcNextNode->mark()!=lcMark) {
       lcNextNode->mark()=lcMark;
       (*lcCurrentArc).second->mark()=lcMark;
       lcNodeS[lcNodeCounter]=lcNextNode;
       lcIndexS[lcNodeCounter++]=lcNbMark;
       agNodeS[lcNbMark]=lcNextNode;
       agArcS[lcNbMark]=(*lcCurrentArc).second;
       agPreviousS[lcNbMark++]=lcIndex;
      }

      lcCurrentArc++;
     }

     lcCurrentArc=lcNode->incomingArcs().begin();
     lcLastArc=lcNode->incomingArcs().end();

     while (lcCurrentArc!=lcLastArc) {
      lcNextNode=(*lcCurrentArc).second->sourceNode();

      if (lcNextNode->mark()!=lcMark) {
       lcNextNode->mark()=lcMark;
       (*lcCurrentArc).second->mark()=lcMark;
       lcNodeS[lcNodeCounter]=lcNextNode;
       lcIndexS[lcNodeCounter++]=lcNbMark;
       agNodeS[lcNbMark]=lcNextNode;
       agArcS[lcNbMark]=(*lcCurrentArc).second;
       agPreviousS[lcNbMark++]=lcIndex;
      }

      lcCurrentArc++;
     }
    }
   }

   lcCurrentNode++;
  }
 }
 //-------------------------------------------------------------------------------MakeCycleBroadTree
 template <tdGraph>
 void makeCycleBroadTree(clGraph<tuGraph> & agGraph,std_vector(clNode<tuGraph> *) & agNodeS,
                         std_vector(clArc<tuGraph> *) & agArcS,
                         std_vector(tyCardinal) & agPreviousS) {
  typedef clGraph<tuGraph>                          cpGraph;
  typedef typename cpGraph::cpArcX::const_iterator  cpArcIterator;
  typedef typename cpGraph::cpNodeX::const_iterator cpNodeIterator;
  typedef std_vector(tyCardinal)                    cpIndexS;
  typedef clNode<tuGraph>                           cpNode;
  typedef std_vector(clNode<tuGraph> *)             cpNodeS;
  typedef clIncreaseDegreeNodeOrder<tuGraph>        cpOrdering;

  cpArcIterator lcCurrentArc;
  tyCardinal    lcCurrentCounter;
  tyCardinal    lcIndex;
  cpArcIterator lcLastArc;
  tyCardinal    lcNbMark;
  cpNode *      lcNextNode;
  cpNode *      lcNode;
  tyCardinal    lcNodeCounter1;
  tyCardinal    lcNodeCounter2;
  cpNodeS       lcSortedNodeS;

  cpNodeIterator lcCurrentNode = agGraph.nodes().begin();
  cpIndexS *     lcIndex1S     = new_object(cpIndexS(agGraph.nodes().size()));
  cpIndexS *     lcIndex2S     = new_object(cpIndexS(agGraph.nodes().size()));
  cpNodeIterator lcLastNode    = agGraph.nodes().end();
  tyMark         lcMark        = ++(agGraph.mark());
  cpNodeS *      lcNode1S      = new_object(cpNodeS(agGraph.nodes().size()));
  cpNodeS *      lcNode2S      = new_object(cpNodeS(agGraph.nodes().size()));

  // Nodes Sorting //
  lcSortedNodeS.reserve(agGraph.nodes().size());

  while (lcCurrentNode!=lcLastNode) {
   lcSortedNodeS.push_back((*lcCurrentNode).second);
   ++lcCurrentNode;
  }

  std_sort(lcSortedNodeS.begin(),lcSortedNodeS.end(),cpOrdering());

  // Broad Parsing //
  lcNbMark=0;
  lcNodeCounter1=0;
  lcNodeCounter2=0;

  while (lcSortedNodeS.size()>0) {
   lcNode=lcSortedNodeS.back();
   lcSortedNodeS.pop_back();

   if (lcNode->mark()!=lcMark) {
    lcNode->mark()=lcMark;
    (*lcNode1S)[lcNodeCounter1]=lcNode;
    (*lcIndex1S)[lcNodeCounter1++]=lcNbMark;
    agNodeS[lcNbMark]=lcNode;
    agArcS[lcNbMark]=nil;
    agPreviousS[lcNbMark++]=0;

    while (lcNodeCounter1>0) {
     standard::swap(lcNodeCounter1,lcNodeCounter2);
     standard::swap(lcNode1S,lcNode2S);
     standard::swap(lcIndex1S,lcIndex2S);

     while (lcNodeCounter2>0) {
      lcCurrentCounter=--lcNodeCounter2;
      lcNode=(*lcNode2S)[lcCurrentCounter];
      lcIndex=(*lcIndex2S)[lcCurrentCounter];

      lcCurrentArc=lcNode->outgoingArcs().begin();
      lcLastArc=lcNode->outgoingArcs().end();

      while (lcCurrentArc!=lcLastArc) {
       lcNextNode=(*lcCurrentArc).second->targetNode();

       if (lcNextNode->mark()!=lcMark) {
        lcNextNode->mark()=lcMark;
        (*lcCurrentArc).second->mark()=lcMark;
        (*lcNode1S)[lcNodeCounter1]=lcNextNode;
        (*lcIndex1S)[lcNodeCounter1++]=lcNbMark;
        agNodeS[lcNbMark]=lcNextNode;
        agArcS[lcNbMark]=(*lcCurrentArc).second;
        agPreviousS[lcNbMark++]=lcIndex;
       }

       lcCurrentArc++;
      }

      lcCurrentArc=lcNode->incomingArcs().begin();
      lcLastArc=lcNode->incomingArcs().end();

      while (lcCurrentArc!=lcLastArc) {
       lcNextNode=(*lcCurrentArc).second->sourceNode();

       if (lcNextNode->mark()!=lcMark) {
        lcNextNode->mark()=lcMark;
        (*lcCurrentArc).second->mark()=lcMark;
        (*lcNode1S)[lcNodeCounter1]=lcNextNode;
        (*lcIndex1S)[lcNodeCounter1++]=lcNbMark;
        agNodeS[lcNbMark]=lcNextNode;
        agArcS[lcNbMark]=(*lcCurrentArc).second;
        agPreviousS[lcNbMark++]=lcIndex;
       }

       lcCurrentArc++;
      }
     }
    }
   }
  }

  delete_object(lcIndex1S);
  delete_object(lcIndex2S);
  delete_object(lcNode1S);
  delete_object(lcNode2S);
 }
}

// M i n t y C o l o r  Implementation //-----------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------------Color
 /*METHOD clMintyColor */ /* Returns a string that indicates the color of an arc. */
 template <tdGraph> tcString clMintyColor<tuGraph>::color(const cpArc & agArc) const {
  if (red(agArc)) return ("red");
  if (black(agArc)) return ("black");
  if (blue(agArc)) return ("blue");
  return ("green");
 }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#undef tdGraph
#undef tuGraph
#endif
 
//==================================================================================================
// G r a p h                                                                         Implementation
// A l g o r i t h m
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library 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 Library General Public License for more details (http://www.gnu.org).

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "graph/algorithm.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define GRAPH_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph/algorithm.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphAlgorithm
#define private_area graphAlgorithm_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Graph/Algorithm");

// Initialization //--------------------------------------------------------------------------------
#undef iniGraphAlgorithm
static_constant(private_area::clInitializer,goInitializer);

// Errors //----------------------------------------------------------------------------------------
namespace public_area { static_error erGraphNotConnex; }

// Constants & Variables //-------------------------------------------------------------------------
dynamic_constant(clString,goDataLocation);

// Static Members //--------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------Operator << (Cycle/Cocycle)
 /*FUNCTION*/ /* Writes a cycle or a cocycle into a stream. */
 function clOutStream & operator << (clOutStream & agStream,ctCycle & agCycle) {
  clCycle::const_iterator lcCurrentArc = agCycle.begin();
  clCycle::const_iterator lcLastArc    = agCycle.end();

  if (agCycle.size()==0) agStream << "empty";
  else {
   while (lcCurrentArc!=lcLastArc) {
    if ((*lcCurrentArc).second==+1) agStream << '+';
    else if ((*lcCurrentArc).second==-1) agStream << '-';
    else agStream << '?';

    agStream << (*lcCurrentArc).first;
    lcCurrentArc++;
    if (lcCurrentArc!=lcLastArc) agStream << ' ';
   }
  }

  return (agStream);
 }
}

namespace private_area {}

// X X X  Implementation //-------------------------------------------------------------------------
namespace {}

// I n i t i a l i z e r  Implementation //---------------------------------------------------------
namespace private_area {
 //--------------------------------------------------------------------------------------------Start
 property void clInitializer::start(void) {
  if (atCounter++ == 0) {
   try {
    #include <bpp/modules.hpp> /*NEED*/
    registerStop(this);
    environment::informInitialization(goModuleName);

    erGraphNotConnex.create("Graph - The graph isn't connex.");

    goDataLocation = new_object(clString(environment::dataLocation()+fileNameSeparator()+"graph"
                     +fileNameSeparator()+"algorithm"));
   }

   initializer_catch;
  }
 }
 //---------------------------------------------------------------------------------------------Stop
 property void clInitializer::stop(void) {
  try {
   environment::informTermination(goModuleName);

   delete_object(goDataLocation);
  }

  initializer_catch;
 }
}

// End //-------------------------------------------------------------------------------------------
}