/**************************************************************
Programme exemple d'optimisation  par la Cplex Callable Librairy 
du petit programme linéaire suivant
  Programme PL :
Maximize
 obj: - 5 x1 - 7 x2 + 8 x3
Subject To
 c1: 3 x1 + 2 x2 <= 9
 c2: 10 x1 + 2 x3 >= -11
Bounds
 -Inf <= x1 <= 0
 1 <= x2 <= 4
 0 <= x3 <= 3
End
***************************************************************/
 
/* compilation
g++-4.1 -o exe TpPL26_cplex11_incomplet.cpp -I/LOCAL/cplex-11.1/cplex111/include/ -L/LOCAL/cplex-11.1/cplex111/lib/x86_debian4.0_4.1/static_pic/ -lcplex -lm -lpthread
*/

#include "/LOCAL/cplex-11.1/cplex111/include/ilcplex/cplex.h"
#include <iostream>
#include <cstring>

using namespace std;
 
int main(){

   /**********************/
   /****** Variables *****/
   /**********************/

   int i;

   /***** Parametres de gestion de Cplex *****/

   CPXENVptr env=NULL;    // Pointeur sur l'environnement Cplex
   CPXLPptr  lp=NULL;     // Pointeur sur la structure contenant PL

   int status;            // Récupère le code d'une éventuelle erreur Cplex


   /**** Parametres de CPXloadlp *****/

   char nomlp[20];

   int numcols;     // Nb de col de la matrice des ctes (variables)
   int numrows;     // Nb de lg de la matrice des ctes  (ctes)

   int colspace;    // Longueur de obj, matbeg, matcnt, lb, et ub
                    // bref les var (+1 pour les variables d'écart)
   int rowspace;    // Longueur de rhs, sense, ... bref nb de ctes
   int nzspace;     // Longueur de matimd et matval ... 
                    // bref les coeff non nuls dans les ctes

   int objsens;     // Sense de l'optimisation : min 1  ou  max -1
   double *obj;     // Tableaux des coeff de la fct objective
   double *rhs;     // Tableau des termes de droite des contraintes
   char *sense;     // Tableau des sens des ctes L pour <=, E= et G>=

   int *matbeg;     // Ces quatre tableaux définissent la matrice des ctes
   int *matcnt;     // Il suffit de stocker les coef non nuls par colonne
   int *matind;     // dans matval, d'indiquer leurs lignes dans matind.
   double *matval;  // matbeg et matcnt indiquent le début et la taille 
                    // d'une colonne dans matval.

   double *lb, *ub; // Tableaux des bornes des variables: lb[i]<=xi<=u[i] 

 

   /***** Parametres de CPXsolution *****/

   int lpstat;      // Etat de la solution
   double objval;   // Valeur de la fct objective
   double *x;       // Tableau solution primale
   double *pi;      // Tableau solution duale (pour chaque cte)
   double *slack;   // Tableau des ecarts de chaque ctres
   double *dj;      // Tableau des coûts réduits

   /*****************************/
   /***** Ouveture de Cplex *****/
   /*****************************/   

   env = CPXopenCPLEX (&status);
   if (env==NULL) {
     char errmsg[1024];
     CPXgeterrorstring (env,status,errmsg);
     cout<<"On ne peut pas ouvrir l'environnement CPLEX"<<endl;
     cout<<errmsg<<endl;
     goto FIN;
   }

   status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
   if ( status != 0 ) {
     cerr<<"Erreur dans l'affichage ecran, erreur numero "<<status<<endl;
      goto FIN;
   }

   /*******************************/
   /***** Allocations memoire *****/
   /*******************************/

   colspace=?;
   rowspace=?; 
   nzspace=?; 

   numcols=?;
   numrows=?;

   obj= new double[?];
   rhs= new double[?];
   sense= new char[?];
   matbeg= new int[?];
   matcnt= new int[?];
   matind= new int[?];
   matval= new double[?];
   lb= new double[?];
   ub= new double[?];

   x= new double[?];
   pi=new double[?];
   slack=new double[?];
   dj=new double[?];

   /*************************************/
   /***** Affectations des tableaux *****/
   /*************************************/

   strcpy (nomlp, "exemple.lp");

   objsens=?;

   obj[0]=?;
   obj[1]=?;
   obj[2]=?;

   matval[0]=?;   matind[0]=?;
   matval[1]=?;  matind[1]=?;
   matval[2]=?;   matind[2]=?;
   matval[3]=?;   matind[3]=?;
 
   matbeg[0]=?; matcnt[0]=?;
   matbeg[1]=?; matcnt[1]=?;
   matbeg[2]=?; matcnt[2]=?;

   sense[0]=?; rhs[0]=?;
   sense[1]=?; rhs[1]=?;

   lb[0]=?;  ub[0]=?;
   lb[1]=?;  ub[1]=?;
   lb[2]=?;  ub[2]=?;

   /**************************************/
   /***** Chargement et Optimisation *****/
   /**************************************/

	lp = CPXcreateprob(env, &status, "exemple");

	CPXcopylp (???); 

	/***** copie du programme lineaire dans un fichier ******/
	status = CPXlpwrite(???);
    if (status)  {
	    cout<<"Erreur dans l'ecriture sur disque"<<endl;
        goto FIN ;
    }

   status = CPXlpopt (???);
   if ( status ) {
      cerr<<"Echec lors de l'optimisation "<<endl;
      goto FIN;
   }

   
   /***************************************/
   /***** Recuperation de la solution *****/
   /***************************************/

   status = CPXsolution (env, lp, &lpstat, &objval, x, pi, slack, dj);
   if ( status ) {
      cerr<<"Erreur lors de la recuperation de la solution."<<endl;
      goto FIN;
   }

   cout<<"La solution est:"<<endl;
   for (i=0;i<numcols;i++)
	cout<<"x"<<i<<"="<<x[i]<<" ";
   cout<<endl;
   cout<<"de cout "<<objval<<endl;


  /***********************************************/
  /***** Desallocation et Fermeture de Cplex *****/
  /***********************************************/


FIN:

   /***** liberation de la memoire allouee pour CPLEX *****/
   delete obj;
   delete rhs;
   delete sense;
   delete matbeg;
   delete matcnt;
   delete matind;
   delete matval;
   delete lb;
   delete ub;
   delete x;  
   delete pi;
   delete slack;
   delete dj;

   if (lp !=NULL){
    status = CPXfreeprob (???);
    if (status)
      cout<<endl<<"CPXfreeprob a echoue, code d'erreur "<<status<<endl;
   }

   if (env !=NULL) {
    status = CPXcloseCPLEX(???);
    if (status) {
       char errmsg[1024];
       cout<<endl<<"On ne peut pas fermer l'environnement CPLEX, erreur ";
       CPXgeterrorstring (env,status,errmsg);
       cout<<errmsg<<endl;
    }
   }

  return (0);
}
