#include "..\Modelib.h"

using namespace std;

int main( int argc, char ** argv )
{
  //-----------------------------------------
  // Declarations et saisie des paramètres
  //-----------------------------------------
  Model modele;

  unsigned nbSommets;
  cout << "Nombre de sommets" << endl;
  cin >> nbSommets;

  unsigned origine;
  unsigned destination;
  float flux;

  cout << "Sommets de depart:" << endl;
  cin >> origine;
  origine = origine%nbSommets;
  cout << "Sommets d'arrivee:" << endl;
  cin >> destination;
  destination = destination%nbSommets;
  cout << "Flux devant circuler entre les deux" << endl;
  cin >> flux;
  if( flux < 0 )
    flux = -flux;

  list<Couple> tmpList;
  Ensemble<float> couts;

  //------------------------------------------------
  // Construction du graphe inutile
  //------------------------------------------------
  Couple tmpCouple;
  for(unsigned i = 0; i < nbSommets; ++i)
  {
  	for(unsigned j = i + 1; j < nbSommets; ++j )
    {
    	tmpCouple[0] = i;
    	tmpCouple[1] = j;
      tmpList.push_back(tmpCouple);
      couts.Add( (19.0*i+17.0*j)/36.0 );
    }
  }
  tmpCouple[0] = nbSommets-1;
  tmpCouple[1] = 0;
  tmpList.push_back(tmpCouple);
  couts.Add( 0.0 );

  //On recupere le nombre d'arcs
  unsigned nbArcs = tmpList.size();

  //on cree la NumVarFamily
  Ensemble<Couple> arcs(tmpList);
  CoupleFloatVarFamily y(modele,0,flux,arcs,"y_%_%");
  
  //On definit le nom du probleme
  modele.SetProblemName("Probleme du graphe inutile");

  //La fonction objectif est classiquement la sommme des (couts*flux sur l'arc)
  Expr objectif;
  for(unsigned i =0; i<nbArcs; ++i)
  {
     objectif+= couts.Get(i)*y.Get(i);
  }

  modele.Maximize(objectif,"objectif");

  //On contruit les contraintes de conservation de flux
  for(unsigned j=0;j<nbSommets;++j) //pour chaque sommets
  {
      //On prend la partie de l'ensemble des variables représentant la quantité
      //de flux sur les arcs sortant du sommet j
      NumVarArray t = y.GetFamilyPart( Omega<0,2,unsigned>(j) );
      //On prend la partie de l'ensemble des variables représentant la quantité
      //de flux sur les arcs entrant dans le sommet j
      NumVarArray u = y.GetFamilyPart( Omega<1,2,unsigned>(j) );
      //L'origine et la destination sont des cas particuliers
      if( j != origine && j != destination )
      {
          //Le flux est conservé, ie la quantité de flux rentrante
          //est égale à la quantité de flux sortante
          modele.Add( Sum(t) - Sum(u) == 0, Nom("c1_",j) );
      }
      else
      {
          if( j == origine )
          {
          	//La quantité de flux sortant de l'origine est la quantité de flux
          	modele.Add( Sum(t) == flux, Nom("c1_",j) );
            //La quantité de flux entrant dans l'origine dans est nulle
            modele.Add( Sum(u) == 0, Nom("c1_") << j << "_2" );
          }
          else
          {
          	modele.Add( Sum(t) == 0, Nom("c1_",j) );
            //La quantité de flux sortant de la destination est nulle
          	modele.Add( Sum(u) == flux, Nom("c1_") << j << "_2" );
            //La quantité de flux entrant dans la destination est la quantité de flux
           }
      }
  }

  cout << "---------Resolution--------" << endl;
  modele.InitSolver(GLPK); //ne pas oublier
  float solution = modele.Solve();
	
  cout << endl << "La solution est de: " << solution << endl;
  modele.ShowMe();
  
  #ifdef USE_HTML_FORMAT
    modele.SortieHTML("GrapheInutile.html");
  #endif

  return 0;
}
