//==================================================================================================
// P r o g r a m                                                                          Interface
// B u i l d _ g r a p h
// C o n s o l 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 provides facilities to execute the program in console mode. */

// File Name //-------------------------------------------------------------------------------------
#line __LINE__ "program/build_graph/console.hpp"

// Guardian //--------------------------------------------------------------------------------------
#ifndef guProgramBuildGraphConsole
#define guProgramBuildGraphConsole

// Headers //---------------------------------------------------------------------------------------
#include <bpp/calendar.hpp> /*INCLUDE*/
#include <bpp/graph_problem.hpp> /*INCLUDE*/

namespace bpp {

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

// Namespaces //------------------------------------------------------------------------------------
#define public_area  programBuildGraphConsole
#define private_area programBuildGraphConsole_private

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

extern_module_name;

// Initialization //--------------------------------------------------------------------------------
#define iniProgramBuildGraphConsole
has_initializer;

// Macrocommands //---------------------------------------------------------------------------------

// Types & Classes //-------------------------------------------------------------------------------
namespace public_area  {}
namespace private_area {}

// Functions Interface //---------------------------------------------------------------------------
namespace public_area  { function tyReturn run(tyCardinal,tcString []); }
namespace private_area {}

// Errors //----------------------------------------------------------------------------------------
namespace public_area { /*ERROR*/ extern_error erSyntax; /* Syntax error in the command line. */ }

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

// X X X  Interface //------------------------------------------------------------------------------
namespace {}

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

// X X X  Inline //---------------------------------------------------------------------------------
namespace {}

// End //-------------------------------------------------------------------------------------------
}
#undef dll_export
#undef public_area
#undef private_area
#endif
 
//==================================================================================================
// P r o g r a m                                                                     Implementation
// B u i l d _ g r a p h
// C o n s o l 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__ "program/build_graph/console.cpp"

// DLL Belonging //---------------------------------------------------------------------------------
#define PROGRAM_BUILD_GRAPH_DLL

// Headers //---------------------------------------------------------------------------------------
#include <bpp/program/build_graph/console.hpp> /*INTERFACE*/

namespace bpp {

// Namespaces //------------------------------------------------------------------------------------
#define public_area  programBuildGraphConsole
#define private_area programBuildGraphConsole_private
#define dll_export   DLL_EXPORT

namespace public_area  {}
namespace private_area {}

static_module_name("Program/Build_graph/Console");

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

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

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

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

// Functions Implementation //----------------------------------------------------------------------
namespace public_area {
 //----------------------------------------------------------------------------------------------Run
 /*FUNCTION*/
 /* Start function of the program. It deals with the commands the user gives through a command
    line and executes the appropriate functions. */
 function tyReturn run(tyCardinal agCounter,tcString agParameterS[]) {
  method_name("run");

  clString  lcCommand;
  tyBoolean lcError;
  clString  lcSPTreeFileName;

  tyCardinal lcCounter   = 1;
  tyBoolean  lcNoCircuit = false;
  tyBoolean  lcNoLayout  = false;
  tyBoolean  lcSPTree    = false;

  environment_private::goProgramName = "B u i l d   G r a p h";

  try {
   if (agCounter==1) send_error(erSyntax);

   while (lcCounter<agCounter) {
    lcCommand=agParameterS[lcCounter];
    lcError=true;

    //---------------------------------------------------------------------------------------Context
    if (lcCommand=="+context") {
     lcError=false;
     environment::nextLine();
     environment::outContext();
    }

    //------------------------------------------------------------------------------------------Help
    else if (lcCommand=="+help") {
     lcError=false;
     environment::nextLine();
     environment::inform("-=-=- H E L P -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
     environment::out(" This program generates a random graph structure. A layout of the graph",true,true);
     environment::out(" can be created.",true,true);
     environment::nextLine();
     environment::out(" * Syntax: [options] [commands] [output file]",true,true);
     environment::nextLine();
     environment::out(" * Options:",true,true);
     environment::out("   -nocircuit  = generates a graph with no circuit. Use it only for the",true,true);
     environment::out("                 commands that could generate graphs with circuits.",true,true);
     environment::out("   -nolayout   = generates a graph without a layout.",true,true);
     environment::out("   -sptree <f> = for serial-parallel graphs only, stores the SP-trees",true,true);
     environment::out("                 composing the generated graph in the file <f>.",true,true);
     environment::nextLine();
     environment::out(" * Commands:",true,true);
     environment::out("   +context               = shows the context of the program's running.",true,true);
     environment::out("   +help                  = shows this help.",true,true);
     environment::out("   +info                  = shows information about the program.",true,true);
     environment::out("   +license               = shows the license of the program.",true,true);
     environment::out("   +arcvalue <x> <y> <u>  = generates a connex graph with <x> nodes",true,true);
     environment::out("                            and <y> arcs, each arc with a value between",true,true);
     environment::out("                            0 and <u>.",true,true);
     environment::out("   +connex <x> <y>        = generates a connex graph with <x> nodes",true,true);
     environment::out("                            and <y> arcs.",true,true);
     environment::out("   +maxflow <x> <y>       = generates a maximum flow problem as a graph",true,true);
     environment::out("            <u>             with <x> nodes and <y> arcs (without counting",true,true);
     environment::out("                            the unique source and target nodes, and their",true,true);
     environment::out("                            arcs), and a flow capacity scale of <u> for",true,true);
     environment::out("                            the arcs.",true,true);
     environment::out("   +minflow <x> <y>       = generates a minimum cost flow problem as a",true,true);
     environment::out("            <u> <v> <w>     graph with <x> nodes and <y> arcs, an",true,true);
     environment::out("                            arc-capacity scale of <u>, an arc-capacity",true,true);
     environment::out("                            flexibility of <v> %. The cost functions of",true,true);
     environment::out("                            the arcs are defined by a value chosen between",true,true);
     environment::out("                            0 and <w>.",true,true);
     environment::out("   +mintension1 <x> <y>   = generates a minimum cost tension problem as a",true,true);
     environment::out("            <u> <v> <w>     graph with <x> nodes and <y> arcs, a",true,true);
     environment::out("                            node-potential scale of <u>, an arc-tension",true,true);
     environment::out("                            flexibility of <v> %. The cost functions of",true,true);
     environment::out("                            the arcs are defined by two values chosen",true,true);
     environment::out("                            between 0 and <w>.",true,true);
     environment::out("   +mintension1s <x> <y1> = generates a minimum cost tension problem as a",true,true);
     environment::out("         <y2> <u> <v> <w>   serial-parallel graph with <x> nodes and",true,true);
     environment::out("                            <y1>+<y2> arcs (<y1> for the serial-parallel",true,true);
     environment::out("                            structure and <y2> for the disruption), a",true,true);
     environment::out("                            node-potential scale of <u>, an arc-tension",true,true);
     environment::out("                            flexibility of <v> %. The cost functions",true,true);
     environment::out("                            of the arcs are defined by two values",true,true);
     environment::out("                            chosen between 0 and <w>.",true,true);
     environment::out("   +mintension2 <x> <y>   = generates a minimum cost tension problem as a",true,true);
     environment::out("            <u> <v> <w>     graph with <x> nodes and <y> arcs, a",true,true);
     environment::out("                            node-potential scale of <u>, an arc-tension",true,true);
     environment::out("                            flexibility of <v> %. The cost functions of",true,true);
     environment::out("                            the arcs are defined by a value chosen between",true,true);
     environment::out("                            0 and <w>.",true,true);
     environment::out("   +mintension2s <x> <y1> = generates a minimum cost tension problem as a",true,true);
     environment::out("         <y2> <u> <v> <w>   serial-parallel graph with <x> nodes and",true,true);
     environment::out("                            <y1>+<y2> arcs (<y1> for the serial-parallel",true,true);
     environment::out("                            structure and <y2> for the disruption), a",true,true);
     environment::out("                            node-potential scale of <u>, an arc-tension",true,true);
     environment::out("                            flexibility of <v> %. The cost functions",true,true);
     environment::out("                            of the arcs are defined by a value",true,true);
     environment::out("                            chosen between 0 and <w>.",true,true);
     environment::out("   +mintension3 <x> <y>   = generates a minimum cost tension problem as a",true,true);
     environment::out("                <u> <v>     graph with <x> nodes and <y> arcs, a",true,true);
     environment::out("                            node-potential scale of <u>, an arc-tension",true,true);
     environment::out("                            flexibility of <v> %.",true,true);
     environment::out("   +mintension4 <x> <y>   = generates a minimum cost tension problem as a",true,true);
     environment::out("        <u> <v> <w> <p>     graph with <x> nodes and <y> arcs, a",true,true);
     environment::out("                            node-potential scale of <u>, an arc-tension",true,true);
     environment::out("                            flexibility of <v> %. The cost functions of",true,true);
     environment::out("                            the arcs are convex piecewise linear (with",true,true);
     environment::out("                            2<p> pieces), the maximum derivative is <w>.",true,true);
     environment::out("   +mintension4s <x> <y1> = generates a minimum cost tension problem as a",true,true);
     environment::out("     <y2> <u> <v> <w> <p>   serial-parallel graph with <x> nodes and",true,true);
     environment::out("                            <y1>+<y2> arcs (<y1> for the serial-parallel",true,true);
     environment::out("                            structure and <y2> for the disruption), a",true,true);
     environment::out("                            node-potential scale of <u>, an arc-tension",true,true);
     environment::out("                            flexibility of <v> %. The cost functions of",true,true);
     environment::out("                            the arcs are convex piecewise linear (with",true,true);
     environment::out("                            2<p> pieces), the maximum derivative is <w>.",true,true);
     environment::out("   +mintension5 <x> <y>   = generates a minimum cost tension problem as a",true,true);
     environment::out("            <u> <v> <w>     graph with <x> nodes and <y> arcs, a",true,true);
     environment::out("                            node-potential scale of <u>, a minimum",true,true);
     environment::out("                            cardinality of <v> for the feasible tension",true,true);
     environment::out("                            sets. The cost functions of the arcs are",true,true);
     environment::out("                            defined by two values chosen between",true,true);
     environment::out("                            0 and <w>.",true,true);
     environment::out("   +mintension5s <x> <y1> = generates a minimum cost tension problem as a",true,true);
     environment::out("         <y2> <u> <v> <w>   serial-parallel graph with <x> nodes and",true,true);
     environment::out("                            <y1>+<y2> arcs (<y1> for the serial-parallel",true,true);
     environment::out("                            structure and <y2> for the disruption), a",true,true);
     environment::out("                            node-potential scale of <u>, a minimum",true,true);
     environment::out("                            cardinality of <v> for the feasible tension",true,true);
     environment::out("                            sets. The cost functions of the arcs are",true,true);
     environment::out("                            defined by two values chosen between",true,true);
     environment::out("                            0 and <w>.",true,true);
     environment::out("   +nonconnex <x> <y>     = generates a non necessarily connex graph with",true,true);
     environment::out("                            <x> nodes and <y> arcs.",true,true);
     environment::out("   +serial <x> <y>        = generates a connex serial-parallel graph with",true,true);
     environment::out("                            <x> nodes and <y> arcs.",true,true);
     environment::out("   +tree <x>              = generates a tree with <x> nodes.",true,true);
     environment::out("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-",true,true);
    }

    //------------------------------------------------------------------------------------------Info
    else if (lcCommand=="+info") {
     lcError=false;
     environment::nextLine();
     environment::outInformation();
    }

    //---------------------------------------------------------------------------------------License
    else if (lcCommand=="+license") {
     lcError=false;
     environment::nextLine();
     environment::outLicense();
    }

    //-------------------------------------------------------------------------------------Nocircuit
    else if (lcCommand=="-nocircuit") {
     lcError=false;
     lcNoCircuit=true;
    }

    //--------------------------------------------------------------------------------------Nolayout
    else if (lcCommand=="-nolayout") {
     lcError=false;
     lcNoLayout=true;
    }

    //----------------------------------------------------------------------------------------Sptree
    else if (lcCommand=="-sptree") {
     if (agCounter-lcCounter>1) {
      lcSPTree=true;
      lcSPTreeFileName=agParameterS[lcCounter+1];
      ++lcCounter;
      lcError=false;
     }
    }

    //--------------------------------------------------------------------------------------Arcvalue
    else if (lcCommand=="+arcvalue") {
     if (agCounter-lcCounter>4) {
      clOutFile                    lcFile;
      clGraph<clRealData,clNoData> lcGraph;
      clGraphLayout                lcLayout;

      tyInteger  lcValueScale = integer(agParameterS[lcCounter+3]);
      tyCardinal lcNbArc      = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode     = cardinal(agParameterS[lcCounter+1]);

      environment::nextLine();
      environment::inform("Generating Connex Graph With Arc Value...");
      generateConnexGraphWithArcValue(lcGraph,lcNbNode,lcNbArc,lcValueScale,lcNoCircuit);
      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+4],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=4;
      lcError=false;
     }
    }

    //----------------------------------------------------------------------------------------Connex
    else if (lcCommand=="+connex") {
     if (agCounter-lcCounter>3) {
      clOutFile                  lcFile;
      clGraph<clNoData,clNoData> lcGraph;
      clGraphLayout              lcLayout;

      tyCardinal lcNbArc  = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode = cardinal(agParameterS[lcCounter+1]);

      environment::nextLine();
      environment::inform("Generating Connex Graph...");
      generateConnexGraph(lcGraph,lcNbNode,lcNbArc,lcNoCircuit);
      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+3],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=3;
      lcError=false;
     }
    }

    //-------------------------------------------------------------------------------------Nonconnex
    else if (lcCommand=="+nonconnex") {
     if (agCounter-lcCounter>3) {
      clOutFile                  lcFile;
      clGraph<clNoData,clNoData> lcGraph;
      clGraphLayout              lcLayout;

      tyCardinal lcNbArc  = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode = cardinal(agParameterS[lcCounter+1]);

      environment::nextLine();
      environment::inform("Generating Non Connex Graph...");
      generateNonConnexGraph(lcGraph,lcNbNode,lcNbArc,lcNoCircuit);
      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+3],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=3;
      lcError=false;
     }
    }

    //----------------------------------------------------------------------------------------Serial
    else if (lcCommand=="+serial") {
     if (agCounter-lcCounter>3) {
      typedef clBinaryTree<graphProblemSerialParallel::clSerialParallelData<clNoData,clNoData> >
      clTree;

      clOutFile                  lcFile;
      clGraph<clNoData,clNoData> lcGraph;
      clGraphLayout              lcLayout;
      std_vector(clTree *)       lcTreeS;

      tyCardinal lcNbArc  = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode = cardinal(agParameterS[lcCounter+1]);

      environment::nextLine();
      environment::inform("Generating Connex Serial-Parallel Graph...");
      generateSerialParallelGraph(lcGraph,lcNbNode,lcNbArc);
      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+3],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      if (lcSPTree) {
       environment::inform("Writing SP-Tree File...");
       graphProblemSerialParallel::clDecomposeAlgo<clNoData,clNoData>::defaultRun(lcGraph,lcTreeS);
       open(lcFile,lcSPTreeFileName.data(),ios::out|ios::trunc);
       lcFile << *(lcTreeS[0]);
       delete_object(lcTreeS[0]);
       close(lcFile);
       if (lcFile.fail()) send_error(erFileWriting);
      }

      lcCounter+=3;
      lcError=false;
     }
    }

    //------------------------------------------------------------------------------------------Tree
    else if (lcCommand=="+tree") {
     if (agCounter-lcCounter>2) {
      clOutFile                  lcFile;
      clGraph<clNoData,clNoData> lcGraph;
      clGraphLayout              lcLayout;

      tyCardinal lcNbNode = cardinal(agParameterS[lcCounter+1]);

      environment::nextLine();
      environment::inform("Generating Tree...");
      generateTree(lcGraph,lcNbNode);
      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Ouput File...");
      open(lcFile,agParameterS[lcCounter+2],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=2;
      lcError=false;
     }
    }

    //---------------------------------------------------------------------------------------MaxFlow
    else if (lcCommand=="+maxflow") {
     if (agCounter-lcCounter>4) {
      clOutFile                        lcFile;
      graphProblemMaxFlow::clFlowGraph lcGraph;
      clGraphLayout                    lcLayout;

      tyInteger  lcCapacityScale = integer(agParameterS[lcCounter+3]);
      tyCardinal lcNbArc         = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode        = cardinal(agParameterS[lcCounter+1]);

      environment::nextLine();
      environment::inform("Generating Maximum Flow Problem...");
      graphProblemMaxFlow::generateFlowGraph(lcGraph,lcNbNode,lcNbArc,lcCapacityScale);
      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+4],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=4;
      lcError=false;
     }
    }

    //-----------------------------------------------------------------------------------Mintension1
    else if (lcCommand=="+mintension1") {
     if (agCounter-lcCounter>6) {
      clOutFile                                 lcFile;
      graphProblemMinCostTension::clLinearGraph lcGraph;
      clGraphLayout                             lcLayout;

      tyCardinal lcFlexibility    = cardinal(agParameterS[lcCounter+4]);
      tyCardinal lcNbArc          = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode         = cardinal(agParameterS[lcCounter+1]);
      tyInteger  lcPotentialScale = integer(agParameterS[lcCounter+3]);
      tyInteger  lcUnitCostScale  = integer(agParameterS[lcCounter+5]);

      environment::nextLine();
      environment::inform("Generating Minimum Linear Cost Tension Problem...");

      graphProblemMinCostTension::generateLinearGraph
      (lcGraph,lcNbNode,lcNbArc,lcPotentialScale,lcFlexibility,lcUnitCostScale);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+6],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=6;
      lcError=false;
     }
    }

    //----------------------------------------------------------------------------------Mintension1s
    else if (lcCommand=="+mintension1s") {
     if (agCounter-lcCounter>7) {
      typedef clBinaryTree<graphProblemSerialParallel::clSerialParallelData
      <graphProblemMinCostTension::clLinearArcData,graphProblemMinCostTension::clNodeData> >
      clTree;

      clOutFile                                 lcFile;
      graphProblemMinCostTension::clLinearGraph lcGraph;
      clGraphLayout                             lcLayout;
      std_vector(clTree *) *                    lcTreeS;

      tyCardinal lcFlexibility     = cardinal(agParameterS[lcCounter+5]);
      tyCardinal lcNbDisruptingArc = cardinal(agParameterS[lcCounter+3]);
      tyCardinal lcNbOrganizingArc = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode          = cardinal(agParameterS[lcCounter+1]);
      tyInteger  lcPotentialScale  = integer(agParameterS[lcCounter+4]);
      tyInteger  lcUnitCostScale   = integer(agParameterS[lcCounter+6]);

      environment::nextLine();
      environment::inform("Generating Minimum Linear Cost Tension Problem (Serial-Parallel)...");

      if (lcSPTree) lcTreeS=new_object(std_vector(clTree *));
      else lcTreeS=nil;

      graphProblemMinCostTension::generateLinearSerialParallelGraph(lcGraph,lcNbNode,
      lcNbOrganizingArc,lcNbDisruptingArc,lcPotentialScale,lcFlexibility,lcUnitCostScale,lcTreeS);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+7],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      if (lcSPTree) {
       environment::inform("Writing SP-Tree File...");
       open(lcFile,lcSPTreeFileName.data(),ios::out|ios::trunc);
       lcFile << *lcTreeS;

       while (lcTreeS->size()>0) {
        delete_object(lcTreeS->back());
        lcTreeS->pop_back();
       }

       delete_object(lcTreeS);
       close(lcFile);
       if (lcFile.fail()) send_error(erFileWriting);
      }

      lcCounter+=7;
      lcError=false;
     }
    }

    //-----------------------------------------------------------------------------------Mintension2
    else if (lcCommand=="+mintension2") {
     if (agCounter-lcCounter>6) {
      clOutFile                                  lcFile;
      graphProblemMinCostTension::clConvexGraph1 lcGraph;
      clGraphLayout                              lcLayout;

      tyInteger  lcCostAccelerationScale = integer(agParameterS[lcCounter+5]);
      tyCardinal lcFlexibility           = cardinal(agParameterS[lcCounter+4]);
      tyCardinal lcNbArc                 = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode                = cardinal(agParameterS[lcCounter+1]);
      tyInteger  lcPotentialScale        = integer(agParameterS[lcCounter+3]);

      environment::nextLine();
      environment::inform("Generating Minimum Convex Cost Tension Problem...");

      graphProblemMinCostTension::generateConvexGraph1
      (lcGraph,lcNbNode,lcNbArc,lcPotentialScale,lcFlexibility,lcCostAccelerationScale);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+6],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=6;
      lcError=false;
     }
    }

    //----------------------------------------------------------------------------------Mintension2s
    else if (lcCommand=="+mintension2s") {
     if (agCounter-lcCounter>7) {
      typedef clBinaryTree<graphProblemSerialParallel::clSerialParallelData
      <graphProblemMinCostTension::clConvexArcData1,graphProblemMinCostTension::clNodeData> >
      clTree;

      clOutFile                                  lcFile;
      graphProblemMinCostTension::clConvexGraph1 lcGraph;
      clGraphLayout                              lcLayout;
      std_vector(clTree *) *                     lcTreeS;

      tyInteger  lcCostAccelerationScale = integer(agParameterS[lcCounter+6]);
      tyCardinal lcFlexibility           = cardinal(agParameterS[lcCounter+5]);
      tyCardinal lcNbDisruptingArc       = cardinal(agParameterS[lcCounter+3]);
      tyCardinal lcNbOrganizingArc       = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode                = cardinal(agParameterS[lcCounter+1]);
      tyInteger  lcPotentialScale        = integer(agParameterS[lcCounter+4]);

      environment::nextLine();
      environment::inform("Generating Minimum Convex Cost Tension Problem (Serial-Parallel)...");

      if (lcSPTree) lcTreeS=new_object(std_vector(clTree *));
      else lcTreeS=nil;

      graphProblemMinCostTension::generateConvexSerialParallelGraph(lcGraph,lcNbNode,
      lcNbOrganizingArc,lcNbDisruptingArc,lcPotentialScale,lcFlexibility,lcCostAccelerationScale,
      lcTreeS);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+7],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      if (lcSPTree) {
       environment::inform("Writing SP-Tree File...");
       open(lcFile,lcSPTreeFileName.data(),ios::out|ios::trunc);
       lcFile << *lcTreeS;

       while (lcTreeS->size()>0) {
        delete_object(lcTreeS->back());
        lcTreeS->pop_back();
       }

       delete_object(lcTreeS);
       close(lcFile);
       if (lcFile.fail()) send_error(erFileWriting);
      }

      lcCounter+=7;
      lcError=false;
     }
    }

    //-----------------------------------------------------------------------------------Mintension3
    else if (lcCommand=="+mintension3") {
     if (agCounter-lcCounter>5) {
      clOutFile                                  lcFile;
      graphProblemMinCostTension::clConvexGraph2 lcGraph;
      clGraphLayout                              lcLayout;

      tyCardinal lcFlexibility    = cardinal(agParameterS[lcCounter+4]);
      tyCardinal lcNbArc          = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode         = cardinal(agParameterS[lcCounter+1]);
      tyInteger  lcPotentialScale = integer(agParameterS[lcCounter+3]);

      environment::nextLine();
      environment::inform("Generating Minimum Convex Cost Tension Problem...");

      graphProblemMinCostTension::generateConvexGraph2(lcGraph,lcNbNode,lcNbArc,lcPotentialScale,
                                                       lcFlexibility);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+5],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=5;
      lcError=false;
     }
    }

    //-----------------------------------------------------------------------------------Mintension4
    else if (lcCommand=="+mintension4") {
     if (agCounter-lcCounter>7) {
      clOutFile                                    lcFile;
      graphProblemMinCostTension::clPiecewiseGraph lcGraph;
      clGraphLayout                                lcLayout;

      tyCardinal lcFlexibility    = cardinal(agParameterS[lcCounter+4]);
      tyCardinal lcNbArc          = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode         = cardinal(agParameterS[lcCounter+1]);
      tyCardinal lcNbPiece        = cardinal(agParameterS[lcCounter+6]);
      tyInteger  lcPotentialScale = integer(agParameterS[lcCounter+3]);
      tyInteger  lcUnitCostScale  = integer(agParameterS[lcCounter+5]);

      environment::nextLine();
      environment::inform("Generating Minimum Piecewise Cost Tension Problem...");

      graphProblemMinCostTension::generatePiecewiseGraph
      (lcGraph,lcNbNode,lcNbArc,lcPotentialScale,lcFlexibility,lcUnitCostScale,lcNbPiece);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+7],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=7;
      lcError=false;
     }
    }

    //----------------------------------------------------------------------------------Mintension4s
    else if (lcCommand=="+mintension4s") {
     if (agCounter-lcCounter>7) {
      typedef clBinaryTree<graphProblemSerialParallel::clSerialParallelData
      <graphProblemMinCostTension::clPiecewiseArcData,graphProblemMinCostTension::clNodeData> >
      clTree;

      clOutFile                                    lcFile;
      graphProblemMinCostTension::clPiecewiseGraph lcGraph;
      clGraphLayout                                lcLayout;
      std_vector(clTree *) *                       lcTreeS;

      tyCardinal lcFlexibility     = cardinal(agParameterS[lcCounter+5]);
      tyCardinal lcNbDisruptingArc = cardinal(agParameterS[lcCounter+3]);
      tyCardinal lcNbOrganizingArc = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode          = cardinal(agParameterS[lcCounter+1]);
      tyCardinal lcNbPiece         = cardinal(agParameterS[lcCounter+7]);
      tyInteger  lcPotentialScale  = integer(agParameterS[lcCounter+4]);
      tyInteger  lcUnitCostScale   = integer(agParameterS[lcCounter+6]);

      environment::nextLine();
      environment::inform("Generating Minimum Piecewise Cost Tension Problem (Serial-Parallel)...");

      if (lcSPTree) lcTreeS=new_object(std_vector(clTree *));
      else lcTreeS=nil;

      graphProblemMinCostTension::generatePiecewiseSerialParallelGraph(lcGraph,lcNbNode,
      lcNbOrganizingArc,lcNbDisruptingArc,lcPotentialScale,lcFlexibility,
      lcUnitCostScale,lcNbPiece,lcTreeS);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+8],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      if (lcSPTree) {
       environment::inform("Writing SP-Tree File...");
       open(lcFile,lcSPTreeFileName.data(),ios::out|ios::trunc);
       lcFile << *lcTreeS;

       while (lcTreeS->size()>0) {
        delete_object(lcTreeS->back());
        lcTreeS->pop_back();
       }

       delete_object(lcTreeS);
       close(lcFile);
       if (lcFile.fail()) send_error(erFileWriting);
      }

      lcCounter+=8;
      lcError=false;
     }
    }

    //-----------------------------------------------------------------------------------Mintension5
    else if (lcCommand=="+mintension5") {
     if (agCounter-lcCounter>6) {
      clOutFile                                   lcFile;
      graphProblemMinCostTension::clDiscreteGraph lcGraph;
      clGraphLayout                               lcLayout;

      tyCardinal lcCardinality    = cardinal(agParameterS[lcCounter+4]);
      tyCardinal lcNbArc          = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode         = cardinal(agParameterS[lcCounter+1]);
      tyInteger  lcPotentialScale = integer(agParameterS[lcCounter+3]);
      tyInteger  lcUnitCostScale  = integer(agParameterS[lcCounter+5]);

      environment::nextLine();
      environment::inform("Generating Minimum Linear Cost Discrete Tension Problem...");

      graphProblemMinCostTension::generateDiscreteGraph
      (lcGraph,lcNbNode,lcNbArc,lcPotentialScale,lcCardinality,lcUnitCostScale);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+6],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=6;
      lcError=false;
     }
    }

    //----------------------------------------------------------------------------------Mintension5s
    else if (lcCommand=="+mintension5s") {
     if (agCounter-lcCounter>6) {
      clOutFile                                   lcFile;
      graphProblemMinCostTension::clDiscreteGraph lcGraph;
      clGraphLayout                               lcLayout;

      tyCardinal lcCardinality     = cardinal(agParameterS[lcCounter+5]);
      tyCardinal lcNbDisruptingArc = cardinal(agParameterS[lcCounter+3]);
      tyCardinal lcNbOrganizingArc = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode          = cardinal(agParameterS[lcCounter+1]);
      tyInteger  lcPotentialScale  = integer(agParameterS[lcCounter+4]);
      tyInteger  lcUnitCostScale   = integer(agParameterS[lcCounter+6]);

      environment::nextLine();
      environment::inform("Generating Minimum Linear Cost Discrete Tension Problem (Serial Parallel)...");

      graphProblemMinCostTension::generateDiscreteSerialParallelGraph
      (lcGraph,lcNbNode,lcNbOrganizingArc,lcNbDisruptingArc,lcPotentialScale,lcCardinality,
       lcUnitCostScale);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+7],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=7;
      lcError=false;
     }
    }

    //---------------------------------------------------------------------------------------Minflow
    else if (lcCommand=="+minflow") {
     if (agCounter-lcCounter>6) {
      clOutFile                              lcFile;
      graphProblemMinCostFlow::clLinearGraph lcGraph;
      clGraphLayout                          lcLayout;

      tyInteger  lcUnitCostScale = integer(agParameterS[lcCounter+5]);
      tyCardinal lcFlexibility   = cardinal(agParameterS[lcCounter+4]);
      tyCardinal lcNbArc         = cardinal(agParameterS[lcCounter+2]);
      tyCardinal lcNbNode        = cardinal(agParameterS[lcCounter+1]);
      tyInteger  lcCapacityScale = integer(agParameterS[lcCounter+3]);

      environment::nextLine();
      environment::inform("Generating Minimum Linear Cost Flow Problem...");

      graphProblemMinCostFlow::generateLinearGraph
      (lcGraph,lcNbNode,lcNbArc,lcCapacityScale,lcFlexibility,lcUnitCostScale);

      lcGraph.numberKeys();

      if (not lcNoLayout) {
       environment::inform("Generating Layout...");
       generateGraphLayout(lcGraph,lcLayout);
       improveGraphLayout(lcGraph,lcLayout);
      }

      environment::inform("Writing Output File...");
      open(lcFile,agParameterS[lcCounter+6],ios::out|ios::trunc);
      lcFile << lcGraph;
      if (lcLayout.size()>0) lcFile << end_line << end_line;
      lcFile << lcLayout;
      close(lcFile);
      if (lcFile.fail()) send_error(erFileWriting);

      lcCounter+=6;
      lcError=false;
     }
    }

    if (lcError) send_error(erSyntax);
    lcCounter++;
   }
  }

  program_catch;
 }
}

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);

    erSyntax.create("Build Graph - Use the '+help' parameter to get some help.");
   }

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

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