//==================================================================================================
// G r a p h _ p r o b l e m                                                              Interface
// M i n _ c o s t _ t e n s i o n
// C o n f o r m i n g _ p i e c e w i s e
//                                                                                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 implements the conforming algorithm to solve the minimum cost tension problem in
   graphs. The cost functions of the arcs in the graph must be piecewise linear as defined by the
   <CODE>clPiecewiseArcData</CODE> class of the <CODE>Structure</CODE> module. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "graph_problem/min_cost_tension/conforming_piecewise.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guGraphProblemMinCostTensionConformingPiecewise
#define guGraphProblemMinCostTensionConformingPiecewise

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph_problem/min_cost_tension/conforming.hpp> /*INCLUDE*/
#include <bpp/graph_problem/min_cost_tension/dual_cost_scaling.hpp> /*INCLUDE*/

namespace bpp {

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

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostTensionConformingPiecewise
#define private_area graphProblemMinCostTensionConformingPiecewise_private

namespace public_area { /*NAMESPACE*/ using namespace graphProblemMinCostTensionConforming; }

namespace private_area {
 using namespace public_area;
 using namespace graphProblemMinCostTensionConforming_private;
}

extern_module_name;

// Initialization //--------------------------------------------------------------------------------

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

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

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area {
 //------------------------------------------------------------------------------------------Classes
 template <tdGraph> class clSolveAlgo;
 template <tdGraph> class clSolveAlgoI;
 template <tdGraph> class clSolveAlgoII;
}

namespace private_area { template <tdGraph> class clConformity; }

// Functions Interface //---------------------------------------------------------------------------
namespace public_area {}

namespace private_area {
 template <tdGraph>
 void convertPiecewiseToLinearGraph(clGraph<tuGraph> &,public_area::clLinearGraph &);

 template <tdGraph>
 void convertLinearToPiecewiseSolution(public_area::clLinearGraph &,clGraph<tuGraph> &);
}

// Errors //----------------------------------------------------------------------------------------
namespace public_area {}

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// S o l v e A l g o  Interface //-----------------------------------------------------------------
namespace public_area {
 /*CLASS clSolveAlgo */
 /* Represents an algorithm to solve the minimum cost tension problem in a graph using the
    conforming method. It is an abstract class. */
 template <tdGraph> class clSolveAlgo : public clPiecewiseSolver<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clSolveAlgo(const clSolveAlgo &);
  private_property clSolveAlgo & operator = (const clSolveAlgo &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clSolveAlgo(void);
  public_property virtual destructor clSolveAlgo(void);

  /*AMETHOD clSolveAlgo */
  /* Solves the minimum cost tension problem of a graph. Abstract method. */
  public_property virtual tyInteger run(clGraph<tuGraph> & agGraph) const = 0;

  public_property static tyInteger defaultRun(clGraph<tuGraph> &);
 };
}

// S o l v e A l g o I  Interface //----------------------------------------------------------------
namespace public_area {
 /*CLASS clSolveAlgoI */
 /* Represents an algorithm to solve the minimum cost tension problem in a graph using the
    conforming method (version I). */
 template <tdGraph> class clSolveAlgoI : public clSolveAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clSolveAlgoI(const clSolveAlgoI &);
  private_property clSolveAlgoI & operator = (const clSolveAlgoI &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clSolveAlgoI(void);
  public_property virtual destructor clSolveAlgoI(void);

  public_property virtual tyInteger run(clGraph<tuGraph> &) const;
 };
}

// S o l v e A l g o I I  Interface //--------------------------------------------------------------
namespace public_area {
 /*CLASS clSolveAlgoII */
 /* Represents an algorithm to solve the minimum cost tension problem in a graph using the
    conforming method (version II). */
 template <tdGraph> class clSolveAlgoII : public clSolveAlgo<tuGraph> {
  //-----------------------------------------------------------------------------------------Private
  private_property constructor clSolveAlgoII(const clSolveAlgoII &);
  private_property clSolveAlgoII & operator = (const clSolveAlgoII &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clSolveAlgoII(void);
  public_property virtual destructor clSolveAlgoII(void);

  public_property virtual tyInteger run(clGraph<tuGraph> &) const;
 };
}

// C o n f o r m i t y  Interface //----------------------------------------------------------------
namespace private_area {
 template <tdGraph> class clConformity {
  //-----------------------------------------------------------------------------------------Private
  private_property clConformity(const clConformity &);
  private_property clConformity & operator = (const clConformity &);
  //------------------------------------------------------------------------------------------Public
  public_property constructor clConformity(void) {}
  public_property destructor  clConformity(void) {}

  public_property tyMintyColor arcColor(const clArc<tuGraph> &) const;
  public_property tyBoolean    conformedArc(const clArc<tuGraph> &) const;

  public_property tyReal maximumDecreaseFlow(const clArc<tuGraph> &) const;
  public_property tyReal maximumIncreaseFlow(const clArc<tuGraph> &) const;
  public_property tyReal maximumDecreaseTension(const clArc<tuGraph> &) const;
  public_property tyReal maximumIncreaseTension(const clArc<tuGraph> &) const;
 };
}

// Functions Inline //------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// S o l v e A l g o  Inline //---------------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clSolveAlgo */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph> inline clSolveAlgo<tuGraph>::clSolveAlgo(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clSolveAlgo */ /* Destructs the algorithm. */
 template <tdGraph> inline clSolveAlgo<tuGraph>::~clSolveAlgo(void) {}
 //---------------------------------------------------------------------------------------DefaultRun
 /*METHOD clSolveAlgo */
 /* Solves the minimum cost tension problem of a graph using the default version of the algorithm
    (version II). Static method. */
 template <tdGraph> inline tyInteger clSolveAlgo<tuGraph>::defaultRun(clGraph<tuGraph> & agGraph)
 { return (clSolveAlgoII<tuGraph>().run(agGraph)); }
}

// S o l v e A l g o I  Inline //-------------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clSolveAlgoI */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph> inline clSolveAlgoI<tuGraph>::clSolveAlgoI(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clSolveAlgoI */ /* Destructs the algorithm. */
 template <tdGraph> inline clSolveAlgoI<tuGraph>::~clSolveAlgoI(void) {}
}

// S o l v e A l g o I I  Inline //-----------------------------------------------------------------
namespace public_area {
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD clSolveAlgoII */
 /* Builds an algorithm to solve the minimum cost tension problem. */
 template <tdGraph> inline clSolveAlgoII<tuGraph>::clSolveAlgoII(void) {}
 //---------------------------------------------------------------------------------------Destructor
 /*METHOD clSolveAlgoII */ /* Destructs the algorithm. */
 template <tdGraph> inline clSolveAlgoII<tuGraph>::~clSolveAlgoII(void) {}
}

// C o n f o r m i t y  Inline //-------------------------------------------------------------------
namespace private_area {
 //-----------------------------------------------------------------------------------------ArcColor
 template <tdGraph>
 inline tyMintyColor clConformity<tuGraph>::arcColor(const clArc<tuGraph> & agArc) const {
  if (agArc.data().needUpdate()) ((clArc<tuGraph> & )agArc).data().update();

  if (agArc.data().tension()<agArc.data().minimum()) return (black);
  else if (agArc.data().tension()>agArc.data().maximum()) return (blue);
  else if (agArc.data().minimum()==agArc.data().maximum()) return (green);
  else {
   tyReal lcShrinkingCost  = agArc.data().nextShrinkingCost();
   tyReal lcStretchingCost = agArc.data().nextStretchingCost();

   if (-lcShrinkingCost==lcStretchingCost) {
    if (agArc.data().flow()<lcStretchingCost) {
     if (agArc.data().tension()==agArc.data().minimum()) return (green);
     else return (blue);
    }
    else if (agArc.data().flow()==lcStretchingCost) {
     if (agArc.data().tension()==agArc.data().minimum()) return (black);
     else if (agArc.data().tension()==agArc.data().maximum()) return (blue);
     else return (red);
    }
    else {
     if (agArc.data().tension()==agArc.data().maximum()) return (green);
     else return (black);
    }
   }
   else {
    if (agArc.data().flow()<=-lcShrinkingCost) {
     if (agArc.data().tension()==agArc.data().minimum()) return (green);
     else return (blue);
    }
    else if (agArc.data().flow()>=lcStretchingCost) {
     if (agArc.data().tension()==agArc.data().maximum()) return (green);
     else return (black);
    }
    else return (green);
   }
  }
 }
 //-------------------------------------------------------------------------------------ConformedArc
 template <tdGraph>
 inline tyBoolean clConformity<tuGraph>::conformedArc(const clArc<tuGraph> & agArc) const {
  if (agArc.data().needUpdate()) ((clArc<tuGraph> & )agArc).data().update();

  if (agArc.data().tension()<agArc.data().minimum()) return (false);
  else if (agArc.data().tension()>agArc.data().maximum()) return (false);
  else if (agArc.data().minimum()==agArc.data().maximum()) return (true);
  else if (agArc.data().flow()<-agArc.data().nextShrinkingCost())
   return (agArc.data().tension()==agArc.data().minimum());
  else if (agArc.data().flow()>agArc.data().nextStretchingCost())
   return (agArc.data().tension()==agArc.data().maximum());
  else return (true);
 }
 //------------------------------------------------------------------------------MaximumDecreaseFlow
 template <tdGraph> inline
 tyReal clConformity<tuGraph>::maximumDecreaseFlow(const clArc<tuGraph> & agArc) const {
  if (agArc.data().needUpdate()) ((clArc<tuGraph> & )agArc).data().update();

  if (agArc.data().tension()<agArc.data().minimum()) return (realMax());
  else if (agArc.data().flow()<=-agArc.data().nextShrinkingCost()) return (realMax());
  else return (agArc.data().flow()+agArc.data().nextShrinkingCost());
 }
 //------------------------------------------------------------------------------MaximumIncreaseFlow
 template <tdGraph> inline
 tyReal clConformity<tuGraph>::maximumIncreaseFlow(const clArc<tuGraph> & agArc) const {
  if (agArc.data().needUpdate()) ((clArc<tuGraph> & )agArc).data().update();

  if (agArc.data().tension()>agArc.data().maximum()) return (realMax());
  else if (agArc.data().flow()>=agArc.data().nextStretchingCost()) return (realMax());
  else return (agArc.data().nextStretchingCost()-agArc.data().flow());
 }
 //---------------------------------------------------------------------------MaximumDecreaseTension
 template <tdGraph> inline
 tyReal clConformity<tuGraph>::maximumDecreaseTension(const clArc<tuGraph> & agArc) const {
  if (agArc.data().needUpdate()) ((clArc<tuGraph> & )agArc).data().update();

  if (agArc.data().tension()>agArc.data().maximum())
   return (agArc.data().tension()-agArc.data().maximum());
  else return (agArc.data().tension()-agArc.data().nextShrinkingBoundary());
 }
 //---------------------------------------------------------------------------MaximumIncreaseTension
 template <tdGraph> inline
 tyReal clConformity<tuGraph>::maximumIncreaseTension(const clArc<tuGraph> & agArc) const {
  if (agArc.data().needUpdate()) ((clArc<tuGraph> & )agArc).data().update();

  if (agArc.data().tension()<agArc.data().minimum())
   return (agArc.data().minimum()-agArc.data().tension());
  else return (agArc.data().nextStretchingBoundary()-agArc.data().tension());
 }
}

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {}

namespace private_area {
 //--------------------------------------------------------------------ConvertPiecewiseToLinearGraph
 template <tdGraph>
 void convertPiecewiseToLinearGraph(clGraph<tuGraph> & agPiecewiseGraph,
                                    public_area::clLinearGraph & agLinearGraph) {
  typedef graphProblemMinCostTensionStructure::clLinearArc     clLinearArc;
  typedef graphProblemMinCostTensionStructure::clLinearArcData clLinearArcData;
  typedef graphProblemMinCostTensionStructure::clLinearNode    clLinearNode;
  typedef graphProblemMinCostTensionStructure::clNodeData      clNodeData;

  typedef clArc<tuGraph>                                     cpPiecewiseArc;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator  cpArcIterator;
  typedef typename clGraph<tuGraph>::cpNodeX::const_iterator cpNodeIterator;

  cpPiecewiseArc * lcArc1;
  clLinearArc *    lcArc2;
  clLinearArc *    lcArc3;
  tyCardinal       lcCounter;
  tyReal           lcMaximum;
  tyReal           lcMinimum;
  clLinearNode *   lcNode1;
  clLinearNode *   lcNode2;
  clLinearNode *   lcNode3;
  tyReal           lcShrinkingCost;
  tyReal           lcStretchingCost;

  cpArcIterator  lcCurrentArc  = agPiecewiseGraph.arcs().begin();
  cpNodeIterator lcCurrentNode = agPiecewiseGraph.nodes().begin();
  cpArcIterator  lcLastArc     = agPiecewiseGraph.arcs().end();
  cpNodeIterator lcLastNode    = agPiecewiseGraph.nodes().end();

  // Nodes Copy //
  while (lcCurrentNode!=lcLastNode) {
   new_object(clLinearNode(agLinearGraph,(*lcCurrentNode).first,clNodeData()));
   ++lcCurrentNode;
  }

  // Arcs Construction //
  while (lcCurrentArc!=lcLastArc) {
   // Initialization //
   lcArc1=(*lcCurrentArc).second;
   lcNode1=&agLinearGraph.node(lcArc1->sourceNode()->key());
   lcNode2=&agLinearGraph.node(lcArc1->targetNode()->key());

   if (lcArc1->data().shrinkingCosts().size()>0) {
    lcMinimum=lcArc1->data().optimum()-lcArc1->data().shrinkingCosts().back().first;
    lcShrinkingCost=lcArc1->data().shrinkingCosts().back().second;
   }
   else {
    lcMinimum=lcArc1->data().optimum();
    lcShrinkingCost=0.0;
   }

   if (lcArc1->data().stretchingCosts().size()>0) {
    lcMaximum=lcArc1->data().optimum()+lcArc1->data().stretchingCosts().back().first;
    lcStretchingCost=lcArc1->data().stretchingCosts().back().second;
   }
   else {
    lcMaximum=lcArc1->data().optimum();
    lcStretchingCost=0.0;
   }

   // Central Arc //
   lcArc2=new_object(clLinearArc(agLinearGraph,lcArc1->key(),clLinearArcData()));
   lcArc2->data().optimum()=lcArc1->data().optimum();
   lcArc2->data().minimum()=lcMinimum;
   lcArc2->data().maximum()=lcMaximum;
   lcArc2->data().shrinkingCost()=lcShrinkingCost;
   lcArc2->data().stretchingCost()=lcStretchingCost;
   lcArc2->data().expected()=0.0;
   lcArc2->data().flow()=0.0;

   // Arcs Representing Stretching //
   lcArc3=lcArc2;
   lcCounter=lcArc1->data().stretchingCosts().size();
   if (lcCounter>0) --lcCounter;

   while (lcCounter>0) {
    --lcCounter;
    lcNode3=new_object(clLinearNode(agLinearGraph,agLinearGraph.getNewNodeKey(),clNodeData()));
    lcArc3->setTargetNode(lcNode3);

    lcArc3=new_object(clLinearArc(agLinearGraph,agLinearGraph.getNewArcKey(),clLinearArcData(),
                                  lcNode3->key()));

    lcArc3->data().optimum()=0.0;
    lcArc3->data().minimum()=0.0;
    lcArc3->data().maximum()=lcArc1->data().stretchingCosts()[lcCounter].first;
    lcArc3->data().shrinkingCost()=0.0;
    lcArc3->data().stretchingCost()=lcArc1->data().stretchingCosts()[lcCounter].second;
    lcArc3->data().expected()=0.0;
    lcArc3->data().flow()=0.0;
   }

   lcArc3->setTargetNode(lcNode2);

   // Arcs Representing Shrinking //
   lcArc3=nil;
   lcCounter=lcArc1->data().shrinkingCosts().size();
   if (lcCounter>0) --lcCounter;

   while (lcCounter>0) {
    --lcCounter;
    lcNode3=new_object(clLinearNode(agLinearGraph,agLinearGraph.getNewNodeKey(),clNodeData()));

    if (lcArc3==nil) lcArc2->setSourceNode(lcNode3);
    else lcArc3->setTargetNode(lcNode3);

    lcArc3=new_object(clLinearArc(agLinearGraph,agLinearGraph.getNewArcKey(),clLinearArcData(),
                                  lcNode3->key()));

    lcArc3->data().optimum()=0.0;
    lcArc3->data().minimum()=0.0;
    lcArc3->data().maximum()=lcArc1->data().shrinkingCosts()[lcCounter].first;
    lcArc3->data().shrinkingCost()=0.0;
    lcArc3->data().stretchingCost()=lcArc1->data().shrinkingCosts()[lcCounter].second;
    lcArc3->data().expected()=0.0;
    lcArc3->data().flow()=0.0;
   }

   if (lcArc3==nil) lcArc2->setSourceNode(lcNode1);
   else lcArc3->setTargetNode(lcNode1);

   ++lcCurrentArc;
  }
 }
 //-----------------------------------------------------------------ConvertLinearToPiecewiseSolution
 template <tdGraph>
 void convertLinearToPiecewiseSolution(public_area::clLinearGraph & agLinearGraph,
                                       clGraph<tuGraph> & agPiecewiseGraph) {
  typedef graphProblemMinCostTensionStructure::clLinearArc  clLinearArc;
  typedef graphProblemMinCostTensionStructure::clLinearNode clLinearNode;

  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpArcIterator;
  typedef clLinearNode::cpArcX::const_iterator              clArcIterator;

  clArc<tuGraph> * lcArc1;
  clLinearArc *    lcArc2;
  clLinearArc *    lcArc3;
  clArcIterator    lcArcIterator;
  tyReal           lcTension;

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

  while (lcCurrentArc!=lcLastArc) {
   lcArc1=(*lcCurrentArc).second;
   lcArc2=&agLinearGraph.arc(lcArc1->key());
   lcTension=lcArc2->data().tension();
   lcArc3=lcArc2;

   while (lcArc3->targetNode()->key()!=lcArc1->targetNode()->key()) {
    lcArc3=(*(lcArc3->targetNode()->outgoingArcs().begin())).second;
    lcTension+=lcArc3->data().tension();
   }

   if (lcArc2->sourceNode()->key()!=lcArc1->sourceNode()->key()) {
    lcArcIterator=lcArc2->sourceNode()->outgoingArcs().begin();
    if (lcArc2==(*lcArcIterator).second) ++lcArcIterator;
    lcArc3=(*lcArcIterator).second;
    lcTension-=lcArc3->data().tension();

    while (lcArc3->targetNode()->key()!=lcArc1->sourceNode()->key()) {
     lcArc3=(*(lcArc3->targetNode()->outgoingArcs().begin())).second;
     lcTension-=lcArc3->data().tension();
    }
   }

   lcArc1->data().tension()=lcTension;
   ++lcCurrentArc;
  }
 }
}

// S o l v e A l g o I  Implementation //-----------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clSolveAlgoI */ /* Solves the minimum cost tension problem of a graph. */
 template <tdGraph> tyInteger clSolveAlgoI<tuGraph>::run(clGraph<tuGraph> & agGraph) const {
  typedef graphProblemMinCostTensionStructure::clLinearArcData clLinearArcData;
  typedef graphProblemMinCostTensionStructure::clLinearGraph   clLinearGraph;
  typedef graphProblemMinCostTensionStructure::clNodeData      clNodeData;

  typedef graphProblemMinCostTensionDualCostScaling::clSolveAlgo<clLinearArcData,clNodeData>
  clDualCostScalingAlgo;

  clLinearGraph lcGraph;
  tyInteger     lcIteration;

  private_area::convertPiecewiseToLinearGraph(agGraph,lcGraph);
  lcIteration=clDualCostScalingAlgo().run(lcGraph);

  if (lcGraph.solved()) {
   private_area::convertLinearToPiecewiseSolution(lcGraph,agGraph);
   agGraph.solved()=true;
  }
  else agGraph.solved()=false;

  return (lcIteration);
 }
}

// S o l v e A l g o I I  Implementation //---------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------------Run
 /*METHOD clSolveAlgoII */ /* Solves the minimum cost tension problem of a graph. */
 template <tdGraph> tyInteger clSolveAlgoII<tuGraph>::run(clGraph<tuGraph> & agGraph) const {
  typedef clArc<tuGraph> *                                  cpArc;
  typedef typename clGraph<tuGraph>::cpArcX::const_iterator cpIterator;

  cpArc *    lcArc1S      = new_array(cpArc,agGraph.arcs().size());
  cpArc *    lcArc2S      = new_array(cpArc,agGraph.arcs().size());
  cpIterator lcCurrentArc = agGraph.arcs().begin();
  tyInteger  lcIteration  = 0;
  cpIterator lcLastArc    = agGraph.arcs().end();

  cpArc      lcArc;
  tyCardinal lcCounter1;
  tyCardinal lcCounter2;

  private_area::clConformity<tuGraph> lcConformity;

  graphProblemMinCostTensionConforming_private::
  clDirectMintyColor<tuGraph,private_area::clConformity<tuGraph> >
  lcDirectMintyColor(lcConformity);

  graphProblemMinCostTensionConforming_private::
  clInverseMintyColor<tuGraph,private_area::clConformity<tuGraph> >
  lcInverseMintyColor(lcConformity);

  // Compatible Tension Search //
  graphProblemTensionAlgorithm::clCompatibleTensionAlgo<tuGraph>::defaultRun(agGraph);

  if (agGraph.solved()==false) {
   delete_array(lcArc1S);
   delete_array(lcArc2S);
   return (-1);
  }

  agGraph.solved()=false;

  // Null Flow Setting //
  nullFlow(agGraph);

  // Non Conformed Arcs List //
  lcCounter1=0;

  while (lcCurrentArc!=lcLastArc) {
   lcArc1S[lcCounter1]=(*lcCurrentArc).second;
   ++lcCounter1;
   ++lcCurrentArc;
  }

  // Conforming //
  while (lcCounter1!=0) {
   standard::swap(lcArc1S,lcArc2S);
   lcCounter2=lcCounter1;
   lcCounter1=0;

   while (lcCounter2>0) {
    lcCounter2--;
    lcArc=lcArc2S[lcCounter2];

    if (not lcConformity.conformedArc(*lcArc)) {
     lcIteration++;
     private_area::improveArc(*lcArc,lcDirectMintyColor,lcInverseMintyColor,lcConformity);
     lcArc1S[lcCounter1]=lcArc;
     lcCounter1++;
    }
   }
  }

  delete_array(lcArc1S);
  delete_array(lcArc2S);
  agGraph.solved()=true;
  return (lcIteration);
 }
}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef tdGraph
#undef tuGraph
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// G r a p h _ p r o b l e m                                                         Implementation
// M i n _ c o s t _ t e n s i o n
// C o n f o r m i n g _ p i e c e w i s e
//                                                                                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_problem/min_cost_tension/conforming_piecewise.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define GRAPH_PROBLEM_MIN_COST_TENSION_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/graph_problem/min_cost_tension/conforming_piecewise.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  graphProblemMinCostTensionConformingPiecewise
#define private_area graphProblemMinCostTensionConformingPiecewise_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Graph_problem/Min_cost_tension/Conforming_piecewise");

// Initialization //--------------------------------------------------------------------------------

// Errors //----------------------------------------------------------------------------------------
namespace public_area {}

// Constants & Variables //-------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

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

// Functions Implementation //----------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

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

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