예제 #1
0
void cplex_constrain(Solution solution, CPLEX cplex) {
  if (solution.n == 0) return;
  
  for (int i = 0, lim = solution.n - 1; i < lim; ++i) {
    Subtour subtour = solution.subtours[i];
    
    double rhs[1] = {subtour.n - 1};
    char senses[1] = {'L'};
    int rmatbeg[1] = {0};
    
    double *rmatval = malloc(sizeof(double) * subtour.n);
    for (int j = 0; j < subtour.n; ++j) {
      rmatval[j] = 1;
    }
    
    char str[16];
    sprintf(str, "pass(%d)", solution.i);
    char *contraints[1] = {strdup(str)};
    
    int *tour = malloc(sizeof(int) * subtour.n);
    for (int j = 0; j < subtour.n; ++j) {
      tour[j] = subtour.tour[j].id;
    }
    
    CPXaddrows(cplex.env, cplex.lp, 0, 1, subtour.n, rhs, senses,
               rmatbeg, tour, rmatval, NULL, contraints);
  }
}
예제 #2
0
Solution cplex_init(TSP tsp, CPLEX cplex) {
  int n = tsp.n;
  int cols = tsp.cols;
  double *dists = tsp.distances;
  
  int *visits = malloc(sizeof(int) * n * n - n);
  double *rmatval = malloc(sizeof(double) * n * n - n);
  
  char **headers = malloc(sizeof(char *) * cols);
  double *lb = malloc(sizeof(double) * cols);
  double *ub = malloc(sizeof(double) * cols);
  char *ctype = malloc(sizeof(char) * cols);
  
  char **contraints = malloc(sizeof(char *) * n);
  double *rhs = malloc(sizeof(double) * n);
  char *senses = malloc(sizeof(char) * n);
  int *rmatbeg = malloc(sizeof(int) * n);
  
  char str[16];
  
  for (int i = 0; i < n; ++i) {
    sprintf(str, "visit(%d)", i+1);
    contraints[i] = strdup(str);
    rhs[i] = 2;
    senses[i] = 'E';
    rmatbeg[i] = i * (n-1);
  }
  
  for (int pos = 0; pos < cols; ++pos) {
    Pair pair = tsp.pairs[pos];
    
    int first  = (pair.i.id * (n-1)) + (pair.j.id-1);
    int second = (pair.j.id * (n-1)) + pair.i.id;
    visits[first] = visits[second] = pos;
    rmatval[first] = rmatval[second] = 1;
    
    sprintf(str, "x(%d,%d)", pair.i.num, pair.j.num);
    headers[pos] = strdup(str);
    
    lb[pos] = 0;
    ub[pos] = 1;
    ctype[pos] = CPX_BINARY; // set the var to binary (value of 1 or 0)
  }
  
  CPXnewcols(cplex.env, cplex.lp, cols, dists, lb, ub, ctype, headers);
  CPXaddrows(cplex.env, cplex.lp, 0, n, n*n-n, rhs, senses, rmatbeg,
             visits, rmatval, NULL, contraints);
  
  Solution solution;
  solution.i = 0;
  solution.n = -1;
  
  return solution;
}
예제 #3
0
void CplexSolver::add(RowBuffer & buffer) {
	buffer.add_last_begin();
	if (buffer.name().empty()) {
		CPXaddrows(_env, _prob, 0, buffer.size(), buffer.nz(), buffer.rhsObj(), buffer.type(), buffer.begin(), buffer.index(), buffer.value(),
		NULL,
		NULL);
	} else {
		//		MY_PRINT(_name.size());
		//		MY_PRINT(size());
		assert((int )buffer.name().size() == buffer.size() && "you should provide a name for each element");

		std::vector<char*> cpxName(buffer.name().size());
		for (int i(0); i < buffer.name().size(); ++i) {
			cpxName[i] = const_cast<char*>(buffer.name()[i].c_str());
		}
		CPXaddrows(_env, _prob, 0, buffer.size(), buffer.nz(), buffer.rhsObj(), buffer.type(), buffer.begin(), buffer.index(), buffer.value(),
		NULL, cpxName.data());
	}
	buffer.rem_last_begin();
}
예제 #4
0
long GenModelCplex::AddCut(int* cols, double* vals, int nz, double rhs, char sense, const char* name)
{
    if(!bcreated)
        return ThrowError("AddCut() not available : Problem not created yet");
    CplexData* d = (CplexData*)solverdata;
    int rmatbeg = 0;

    CPXaddrows(d->env, d->lp, 0, 1, nz, &rhs, &sense, &rmatbeg, cols, vals, NULL, (char**)(&name));
    d->nr++;

    return 0;
}
static int
populatebyrow (CPXENVptr env, CPXLPptr lp)
{
   int      status    = 0;
   double   obj[NUMCOLS];
   double   lb[NUMCOLS];
   double   ub[NUMCOLS];
   char     *colname[NUMCOLS];
   int      rmatbeg[NUMROWS];
   int      rmatind[NUMNZ];
   double   rmatval[NUMNZ];
   double   rhs[NUMROWS];
   char     sense[NUMROWS];
   char     *rowname[NUMROWS];

   status = CPXchgobjsen (env, lp, CPX_MAX);  /* Problem is maximization */
   if ( status )  goto TERMINATE;

   /* Now create the new columns.  First, populate the arrays. */

       obj[0] = 1.0;      obj[1] = 2.0;          obj[2] = 3.0;

        lb[0] = 0.0;       lb[1] = 0.0;           lb[2] = 0.0;
        ub[0] = 40.0;      ub[1] = CPX_INFBOUND;  ub[2] = CPX_INFBOUND;

   colname[0] = "x1"; colname[1] = "x2";     colname[2] = "x3";

   status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, colname);
   if ( status )  goto TERMINATE;

   /* Now add the constraints.  */

   rmatbeg[0] = 0;     rowname[0] = "c1";

   rmatind[0] = 0;     rmatind[1] = 1;    rmatind[2] = 2;    sense[0] = 'L';
   rmatval[0] = -1.0;  rmatval[1] = 1.0;  rmatval[2] = 1.0;  rhs[0]   = 20.0;

   rmatbeg[1] = 3;     rowname[1] = "c2";
   rmatind[3] = 0;     rmatind[4] = 1;    rmatind[5] = 2;    sense[1] = 'L';
   rmatval[3] = 1.0;   rmatval[4] = -3.0; rmatval[5] = 1.0;  rhs[1]   = 30.0;

   status = CPXaddrows (env, lp, 0, NUMROWS, NUMNZ, rhs, sense, rmatbeg,
                        rmatind, rmatval, NULL, rowname);
   if ( status )  goto TERMINATE;

TERMINATE:

   return (status);

}  /* END populatebyrow */
예제 #6
0
파일: TP.cpp 프로젝트: peter3110/tp-io
void agregarRestriccionAgujero(CPXENVptr env, CPXLPptr lp, std::vector<int> indicesAgujero){

    for(int numeroColor = 0; numeroColor < P; numeroColor++) {
    // En total, son P + N*P variables ( las W[j] y las X[i][j] )
        int cantVariables = P + N*P;

        int ccnt = 0;
        int rcnt = 1; //Agrego una sola restriccion

        int nzcnt = 0;  // al ppio es cero (para cada valor q agrego, lo voy a incrementar en 1)

        char sense[rcnt]; // Sentido de la desigualdad. 'G' es mayor o igual y 'E' para igualdad, 'L' menor o igual

        double *rhs = new double[rcnt]; // Termino independiente de las restricciones.
        int *matbeg = new int[rcnt];    //Posicion en la que comienza cada restriccion en matind y matval.
        int *matind = new int[rcnt*cantVariables];       // Array con los indices de las variables con coeficientes != 0 en la desigualdad.
        double *matval = new double[rcnt*cantVariables]; // Array que en la posicion i tiene coeficiente ( != 0) 

        ///Sumatoria de xij - wj
        matbeg[0] = nzcnt;
        rhs[0]    = 0;
        sense[0]  = 'L';

        matind[nzcnt] = numeroColor;

        int k = -1 * ((indicesAgujero.size() - 1) / 2);
        matval[nzcnt] = k;
        nzcnt++;

        for(int i = 0; i < indicesAgujero.size(); i++) {
            matind[nzcnt] = xijIndice(indicesAgujero[i], numeroColor);
            matval[nzcnt] = 1;
            nzcnt++;
        }

        int status = CPXaddrows(env, lp, ccnt, rcnt, nzcnt, rhs, sense, matbeg, matind, matval, NULL, NULL);

        if (status) {
            cerr << "Problema agregando restricciones." << endl;
            exit(1);
        }

        delete[] rhs;
        delete[] matbeg;
        delete[] matind;
        delete[] matval;
    }
}
예제 #7
0
// add constraint under construction as an equal constraint
int cplex_solver::add_constraint_eq(CUDFcoefficient bound) {
	if (nb_coeffs > 0) {
		int status, begin[2];
		double rhs[1];

		begin[0] = 0;
		begin[1] = nb_coeffs;
		rhs[0] = bound;
		status = CPXaddrows(env, lp, 0, 1, nb_coeffs, rhs, "E", begin, sindex, coefficients, NULL, NULL);
		if (status) {
			fprintf(stderr, "cplex_solver: add_constraint_eq: cannot create eq constraint.\n");
			exit(-1);
		}
	}
	return 0;
}
예제 #8
0
파일: diet.c 프로젝트: annaPolytech/PRD
static int
populatebyrow (CPXENVptr env, CPXLPptr lp,
               int nfoods, double *cost, double *lb, double *ub, 
               int nnutr, double *nutrmin, double *nutrmax,
               double **nutrper)
{
   int status = 0;

   int zero = 0;
   int *ind = NULL;
   int i, j;

   ind = (int*) malloc(nfoods * sizeof(int));
   if ( ind == NULL ) {
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   }
   for (j = 0; j < nfoods; j++) {
      ind[j] = j;
   }

   status = CPXnewcols (env, lp, nfoods, cost, lb, ub, NULL, NULL);
   if ( status )  goto TERMINATE;

   for (i = 0; i < nnutr; i++) {
      double rng  = nutrmax[i] - nutrmin[i];

      status = CPXaddrows (env, lp, 0, 1, nfoods, nutrmin+i, "R",
                           &zero, ind, nutrper[i], NULL, NULL);
      if ( status )  goto TERMINATE;

      status = CPXchgrngval (env, lp, 1, &i, &rng);
      if ( status )  goto TERMINATE;
   }

TERMINATE:

   free_and_null ((char **)&ind);

   return (status);

}  /* END populatebyrow */
예제 #9
0
int cg_solver(int m, MyRow* rows)
{
   CPXENVptr     env = NULL;
   CPXLPptr      model = NULL;
   int           status = 0;
   int           error = 0;
   int           i, j;
   int           cur_numrows, cur_numcols;
   int           n_cuts, cut;

   int       solstat;
   double    objval;
   double   *x;
   double   *z;
   int      *cstat;
 
   int      n0 = rows[0].n;      
   int      n1 = rows[0].n+m-1;  /// One slack variable for constraint
   int      h = (m-1)*n0 + m-1;  /// Number of nonzeros

   double   obj[n1];

   double   rhs[m-1];    /// The first row is for the cost vector
   char     sense[m-1];

   int      jnd[h];
   int      ind[h];
   double   val[h];

   int      idx = 0;

   int*     rmatbeg;
   int*     rmatind;
   double*  rmatval;
   double*  b_bar;
   char*    gc_sense;
   double*  gc_rhs;

   /// Create environment
   env = CPXopenCPLEX (&status);
   if ( env == NULL ) {
      char  errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment. Status: %d\n", status);
      CPXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto QUIT;
   }

   /// Disable presolve
   POST_CMD( CPXsetintparam (env, CPX_PARAM_PREIND, CPX_OFF) );
   
   /// Create problem
   model = CPXcreateprob (env, &error, "gomory");
   if (error) goto QUIT;

   /// Minimization problem
   POST_CMD( CPXchgobjsen (env, model, CPX_MIN) );
   
   /// Add rows (remember first row is cost vector)
   for ( i = 0; i < m-1; ++i ) {
      sense[i]='E';
      rhs[i] = rows[i+1].rhs;
   }
   POST_CMD( CPXnewrows(env, model, m-1, rhs, sense, NULL, NULL) );
   
   /// Add problem variables 
   for ( j = 0; j < n0; ++j ) 
      obj[j] = rows[0].lhs[j];
   /// Add slack variables 
   for ( j = n0; j < n1; ++j ) 
      obj[j] = 0;
   POST_CMD( CPXnewcols(env, model, n1, obj, NULL, NULL, NULL, NULL) );

   /// Write the full matrix A into the LP (WARNING: should use only nonzeros entries)
   for ( i = 1; i < m; ++i ) {
      for ( j = 0; j < n0; ++j ) {
         jnd[idx] = i-1;
         ind[idx] = rows[i].ind[j];
         val[idx] = rows[i].lhs[j];
         idx++;
      }
      /// Add a slack variable per constraint
      jnd[idx] = i-1;
      ind[idx] = n0+i-1;
      val[idx] = 1.0;
      idx++;
   }
   POST_CMD( CPXchgcoeflist(env, model, idx, jnd, ind, val) );

   /// Optimize the problem
   POST_CMD( CPXlpopt(env, model) );

   /// Check the results
   cur_numrows = CPXgetnumrows (env, model);
   cur_numcols = CPXgetnumcols (env, model);

   x =  (double *) malloc (cur_numcols * sizeof(double));
   z =  (double *) malloc (cur_numcols * sizeof(double));
   cstat = (int *) malloc (cur_numcols * sizeof(int));

   b_bar = (double *) malloc (cur_numrows * sizeof(double));

   POST_CMD( CPXsolution (env, model, &solstat, &objval, x, NULL, NULL, NULL) );
   if ( solstat != 1 ) {
      printf("The solver did not find an optimal solution\nSolver status code: %d\n",solstat);
      exit(0);
   }

   /// Write the output to the screen 
   printf ("\nSolution status = %d\t\t", solstat);
   printf ("Solution value  = %f\n\n", objval);

   /// If the solution is integer, is the optimum -> exit the loop
   if ( isInteger(cur_numcols, x) ) {
      fprintf(stdout,"The solution is already integer!\n");
      goto QUIT;
   }

   /// Dump the problem model to 'gomory.lp' for debbuging
   POST_CMD( CPXwriteprob(env, model, "gomory.lp", NULL) );

   /// Get the base statuses
   POST_CMD( CPXgetbase(env, model, cstat, NULL) );

   print_solution(cur_numcols, x, cstat);

   printf("\nOptimal base inverted matrix:\n");
   for ( i = 0; i < cur_numrows; ++i ) {
      b_bar[i] = 0;
      POST_CMD( CPXbinvrow(env, model, i, z) );
      for ( j = 0; j < cur_numrows; ++j ) {
         printf("%.1f ", z[j]);
         b_bar[i] += z[j]*rhs[j];
      }
      printf("\n");
   }

   printf("\nOptimal solution (non basic variables are equal to zero):\n");
   idx = 0;     /// Compute the nonzeros
   n_cuts = 0;  /// Number of fractional variables (cuts to be generated)
   for ( i = 0; i < m-1; ++i ) {
      POST_CMD( CPXbinvarow(env, model, i, z) );
      for ( j = 0; j < n1; ++j ) {
         if ( z[j] >= 0 )
            printf("+");
         printf("%.1f x%d ", z[j], j+1);
         if ( floor(z[j]+0.5) != 0 )
            idx++;
      }
      printf("= %.1f\n", b_bar[i]);
      /// Count the number of cuts to be generated
      if ( floor(b_bar[i]) != b_bar[i] ) 
         n_cuts++;
   }

   /// Allocate memory for the new data structure
   gc_sense = (char*)   malloc ( n_cuts * sizeof(char) ); 
   gc_rhs   = (double*) malloc ( n_cuts * sizeof(double) ); 
   rmatbeg  = (int*)    malloc ( n_cuts * sizeof(int) ); 
   rmatind  = (int*)    malloc (    idx * sizeof(int) ); 
   rmatval  = (double*) malloc (    idx * sizeof(double) ); 

   printf("\nGenerate Gomory cuts:\n");
   idx = 0;
   cut = 0;  /// Index of cut to be added
   for ( i = 0; i < m-1; ++i ) 
      if ( floor(b_bar[i]) != b_bar[i] ) {
         printf("Row %d gives cut ->   ", i+1);
         POST_CMD( CPXbinvarow(env, model, i, z) );
         rmatbeg[cut] = idx;
         for ( j = 0; j < n1; ++j ) {
            z[j] = floor(z[j]); /// DANGER!
            if ( z[j] != 0 ) {
               rmatind[idx] = j;
               rmatval[idx] = z[j];
               idx++;
            }
            /// Print the cut
            if ( z[j] >= 0 )
               printf("+");
            printf("%.1f x%d ", z[j], j+1);
         }
         gc_rhs[cut] = floor(b_bar[i]); /// DANGER!
         gc_sense[cut] = 'L';
         printf("<= %.1f\n", gc_rhs[cut]);
         cut++;
      }

   /// Add the new cuts
   POST_CMD( CPXaddrows (env, model, 0, 
            n_cuts, idx, gc_rhs, gc_sense, 
            rmatbeg, rmatind, rmatval, 
            NULL, NULL) );

   /// Solve the new LP
   POST_CMD( CPXlpopt(env, model) );

   /// Check the results
   cur_numrows = CPXgetnumrows (env, model);
   cur_numcols = CPXgetnumcols (env, model);

   POST_CMD( CPXsolution (env, model, &solstat, &objval, x, NULL, NULL, NULL) );

   if ( solstat != 1 ) {
      printf("The solver did not find an optimal solution\nSolver status code: %d\n",solstat);
      exit(0);
   }
   /// Write the output to the screen 
   printf ("\nSolution status = %d\n", solstat);
   printf ("Solution value = %f\n\n", objval);

   POST_CMD( CPXgetbase(env, model, cstat, NULL) );

   print_solution(cur_numcols, x, cstat);

   free_and_null ((char **) &x);
   free_and_null ((char **) &z);
   free_and_null ((char **) &cstat);
   free_and_null ((char **) &rmatbeg);
   free_and_null ((char **) &rmatind);
   free_and_null ((char **) &rmatval);

QUIT:
   free_and_null ((char **) &x);
   free_and_null ((char **) &z);
   free_and_null ((char **) &cstat);

   if ( error ) {
      char  errmsg[CPXMESSAGEBUFSIZE];
      CPXgeterrorstring (env, error, errmsg);
      fprintf (stderr, "%s", errmsg);
   }

   /* Free up the problem as allocated by CPXcreateprob, if necessary */
   if ( model != NULL ) {
      status = CPXfreeprob (env, &model);
      if ( status ) {
         fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status);
      }
   }

   /* Free up the CPLEX environment, if necessary */
   if ( env != NULL ) {
      status = CPXcloseCPLEX (&env);

      if ( error ) {
         char  errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }

   return (status);
}
예제 #10
0
SolverMIP::SOLVERSTAT FacilityLocation::solveLRExtentedFormulations(MulltipleCutSetSeparation _cutSetSepFunc, double _tol)
{
	int pos = 0;
	int nbCuts = 0;
	int sentinel = 0;
	int MAX_ITER = 100;
	int tailOffCounter = 0;
	int tailOffTol = 3;
	int printInterval = 5;
	double currentLp = 0., lastLp = 0.;
	bool noViolatedCutFound = true;
	std::set<long> hashTable;
	TypeVariableHashPtr vHashPtr = &(vHash);
	std::vector<std::set<int>*> cutSets;
	SolverMIP::SOLVERSTAT ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_UNKNOWN;

	if (xSol != NULL)
		delete[] xSol;

	xSol = new double[getNCols()];
	
	clock_t start = clock();
	do
	{
		lastLp = currentLp;
		status = SolverMIP::solve(SolverMIP::METHOD::METHOD_DUAL);

		if (status == SolverMIP::SOLVERSTAT::SOLVERSTAT_MIPOPTIMAL || status == SolverMIP::SOLVERSTAT::SOLVERSTAT_LPOPTIMAL ||
			status == SolverMIP::SOLVERSTAT::SOLVERSTAT_FEASIBLE)
		{
			ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_FEASIBLE;
			currentLp = getObjVal();

			// Getting fractional node solution
			getX();

			if (sentinel % printInterval == 0)
			{
				printf("\n---- iter: %d\n", sentinel + 1);
				printf("OBJ_VAL = %lf\n", currentLp);
			}

#ifndef DEBUG
			//Printing xNode solution
			printf("\n\n---- iter: %d\n", sentinel + 1);
			for (int varType = Variable::V_X; varType != Variable::V_UNKNOWN; varType += 10)
			{
				VariableHash::iterator vit = vHashPtr->at((Variable::VARTYPE)varType).begin();
				for (; vit != vHashPtr->at((Variable::VARTYPE)varType).end(); ++vit)
				{
					int idx = vit->second;

					if (xSol[idx] > SOLVER_EPS)
						std::cout << (vit->first).toString() << "(" << idx << "); " << xSol[idx] << std::endl;
					printf("");
				}
				printf("");
			}
#endif
			// Verifying optimality conditions
			if (fabs(currentLp - lastLp) < _tol)
			{
				++tailOffCounter;
				if (tailOffCounter > tailOffTol)
				{
					ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_LPOPTIMAL;
					break;
				}
			}
			else
				tailOffCounter = 0;

			// Calling the separation routine
			pos = cutSets.size();
			int cutSize = _cutSetSepFunc(g, vHashPtr, xSol, cutSets, true);

			// If a fractional cycle is found...
			if (cutSets.size() - pos > 0)
			{
				noViolatedCutFound = false;

				for (int i = pos; i < cutSets.size(); ++i)
				{
					std::set<int>* sPtr = cutSets[i];
					// Check whether the cut has already been generated
					unsigned long hashVal = hashFunc(*sPtr);
					std::set<long>::iterator it = hashTable.find(hashVal);
					if (it != hashTable.end())
					{
#ifdef DEBUG
						int warnCode = 990;
						std::string aux = convertSetToString(s);
						std::string msg = "The identified cut set was already separated " + convertSetToString(s);
						warningMsg(NULL, __func__, msg.data(), warnCode);
#endif
					}
					else
						hashTable.insert(hashVal);

					// ... we must find the cut set ...
					std::vector<Variable> cutSet;
					for (VariableHash::iterator vit = vHashPtr->at(Variable::V_Z).begin(); vit != vHashPtr->at(Variable::V_Z).end(); ++vit)
					{
						Variable z = vit->first;
						int head = z.getArc().getHead().getCode();
						int tail = z.getArc().getTail().getCode();

						std::set<int>::iterator hIt = sPtr->find(head);
						std::set<int>::iterator tIt = sPtr->find(tail);

						// ... which is composed by those arcs with one endpoint in S
						bool isHeadInS = hIt != sPtr->end();
						bool isTailInS = tIt != sPtr->end();
						if (!(isHeadInS && isTailInS) && (isHeadInS || isTailInS))
						{
							cutSet.push_back(z);
						}
					}

					// Identifying the y-variables involved in cut set constraints
					// And split them into two sets
					std::vector<Variable> sVec;
					std::vector<Variable> sCompVec;
					for (VariableHash::iterator vit = vHashPtr->at(Variable::V_Y).begin(); vit != vHashPtr->at(Variable::V_Y).end(); ++vit)
					{
						Variable v = vit->first;
						int nodeIdx = v.getVertex1().getCode();

						if (sPtr->find(nodeIdx) != sPtr->end())
						{
							sVec.push_back(v);
						}
						else
						{
							sCompVec.push_back(v);
						}
					}

					// Translating valid inequalities found into cplex/matrix representation
					int nzcnt = cutSet.size() + 2;
					std::vector<int> idx(nzcnt);
					std::vector<double> val(nzcnt);
					for (int i = 0; i < sVec.size(); ++i)
					{
						idx[0] = sVec[i].getColIdx();
						val[0] = -1.0;
						for (int j = 0; j < sCompVec.size(); ++j)
						{
							idx[1] = sCompVec[j].getColIdx();
							val[1] = -1.0;

							for (int k = 0; k < cutSet.size(); ++k)
							{
								idx[k + 2] = cutSet[k].getColIdx();
								val[k + 2] = 1.0;
							}

							// Adding user generated cut
							int nRows = 1;
							double rhs = -1;
							char sense = 'G';
							int rmatbeg = 0;
							int newColsAdded = 0;
							status = CPXaddrows(env, lp, newColsAdded, nRows, nzcnt, &rhs, &sense, &rmatbeg, &idx[0], &val[0], NULL, NULL);
							//status = CPXcutcallbackadd(_env, _cbdata, _wherefrom, nzcnt, -1, 'G', &idx[0], &val[0], CPX_USECUT_FORCE);
							if (status)
							{
								int warnCode = 999;
								std::string msg = "Failed to add integer cut.";
								warningMsg(NULL, __func__, msg.data(), warnCode);
							}
							else
								nbCuts++;

							printf("");
						}
					}
				}
#ifdef DEBUG
					// salva um arquivo .lp com o LP atual
					writeProbLP(".\\lpRelax");
#endif
			}
			else
			{
				// No violated cut was found
				noViolatedCutFound = true;
			}
		
			// If no violated cut was found
			if (noViolatedCutFound)
			{
				ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_LPOPTIMAL;
				break;
			}
		}
		else
		{
			int warnCode = 201;
			std::string msg = "Model is infeasible";
			warningMsg(typeid(*this).name(), __func__, msg.data(), warnCode);

			// salva um arquivo .lp com o LP atual
			writeProbLP(".\\infeasible");

			ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_INFEASIBLE;
			break;
		}

	} while (++sentinel < MAX_ITER);

	// Deallocating memory
	for (int i = 0; i < cutSets.size(); ++i)
	{
		if (cutSets[i] != NULL)
		{
			delete cutSets[i];
			cutSets[i] = NULL;
		}
	}

	clock_t end = clock();
	printf("\n-----");
	printf("\n----- iter: %d", sentinel + 1);
	printf("\n----- OBJ_VAL = %lf", currentLp);
	printf("\n----- Exectution time: %.4f", (end - start) / (double)CLOCKS_PER_SEC);

	return ret;
}
예제 #11
0
int CPLEXAddConstraint(LinEquation* InEquation) {
	int Status = 0;
	
	if (InEquation->ConstraintType != QUADRATIC && InEquation->ConstraintType != LINEAR) {
		FErrorFile() << "This constraint type is not supported in CPLEX: " << InEquation->ConstraintType << endl;
		FlushErrorFile();
		return FAIL;
	}

	//First I check the number of rows. If it's larger than the index, then this constraint already exists and is only being changed
	int NumberRows = CPXgetnumrows (CPLEXenv, CPLEXModel);
	if (NumberRows <= InEquation->Index) {
		char* Sense = new char[1];
		if (InEquation->EqualityType == EQUAL) {
			if (InEquation->QuadOne.size() > 0) {
				delete [] Sense;
				FErrorFile() << "Quadratic constraints cannot be equivalent constraints in CPLEX." << endl;
				FlushErrorFile();
				return FAIL;
			} else {
				Sense[0] = 'E';
			}
		} else if (InEquation->EqualityType == LESS) {
			Sense[0] = 'L';
		} else if (InEquation->EqualityType == GREATER) {
			Sense[0] = 'G';
		} else {
			delete [] Sense;
			FErrorFile() << "Unrecognized constraint type: " << InEquation->ConstraintType << endl;
			FlushErrorFile();
			return FAIL;
		}

		double* Rhs = new double[1];
		Rhs[0] = InEquation->RightHandSide;
		
		int* ColInd = NULL;
		int* RowInd = NULL;
		double* Coeff = NULL;
		if (InEquation->Variables.size() > 0) {
			ColInd = new int[int(InEquation->Variables.size())];
			RowInd = new int[int(InEquation->Variables.size())];
			Coeff = new double[int(InEquation->Variables.size())];
			for (int i=0; i < int(InEquation->Variables.size()); i++) {
				Coeff[i] = InEquation->Coefficient[i];
				RowInd[i] = 0;
				ColInd[i] = InEquation->Variables[i]->Index;
			}
		}
		
		if (InEquation->QuadOne.size() > 0) {
			if (CPXgetprobtype(CPLEXenv, CPLEXModel) == CPXPROB_LP) {
				Status = CPXchgprobtype(CPLEXenv, CPLEXModel, CPXPROB_QP);
			}
			else if (CPXgetprobtype(CPLEXenv, CPLEXModel) == CPXPROB_MILP) {
				Status = CPXchgprobtype(CPLEXenv, CPLEXModel, CPXPROB_MIQP);
			}
	
			int *QuadCol = new int[int(InEquation->QuadOne.size())];
			int *QuadRow = new int[int(InEquation->QuadTwo.size())];
			double *QuadCoeff = new double[int(InEquation->QuadCoeff.size())];
			for (int i=0; i < int(InEquation->QuadOne.size()); i++) {
				QuadCol[i] = InEquation->QuadOne[i]->Index;
				QuadRow[i] = InEquation->QuadTwo[i]->Index;
				QuadCoeff[i] = InEquation->QuadCoeff[i];
			}

			Status = CPXaddqconstr(CPLEXenv, CPLEXModel, int(InEquation->Variables.size()), int(InEquation->QuadOne.size()), Rhs[0], int(Sense[0]), ColInd, Coeff, QuadRow, QuadCol, QuadCoeff, NULL);

			delete [] QuadCol;
			delete [] QuadRow;
			delete [] QuadCoeff;
		} else if (InEquation->Variables.size() > 0) {	
			string StrName = GetConstraintName(InEquation);
			char** Name = new char*;
			Name[0] = new char[StrName.length()+1];
			strcpy(Name[0],StrName.data());

			if ((InEquation->ConstraintMeaning.compare("chemical potential constraint") == 0) && (InEquation->Loaded == false) && (GetParameter("Check potential constraints feasibility").compare("1") == 0)) {
				Rhs[0] = InEquation->LoadedRightHandSide;
				Sense[0] = 'L';
			} else if ((InEquation->ConstraintMeaning.compare("chemical potential constraint") == 0) && (InEquation->Loaded == false) && (InEquation->RightHandSide > 0.9*FLAG)){
				Rhs[0] = FLAG;
				Sense[0] = 'L';
			}

			Status = CPXaddrows(CPLEXenv, CPLEXModel, 0, 1, int(InEquation->Variables.size()), Rhs, Sense, RowInd, ColInd, Coeff, NULL, Name);
			delete [] Name[0];
			delete [] Name;
			delete [] ColInd;
			delete [] RowInd;
			delete [] Coeff;	
		}
		delete [] Rhs;
		delete [] Sense;

		if (Status) {
			FErrorFile() << "Failed to add constraint: " << InEquation->Index << endl;
			FlushErrorFile();
			return FAIL;
		}
	} else {
		if (InEquation->QuadOne.size() > 0) {
			FErrorFile() << "Cannot change a quadratic constraint." << endl;
			FlushErrorFile();
			return FAIL;
		} else {
			int NumberOfColumns = CPXgetnumcols(CPLEXenv, CPLEXModel);
			//First I reset all of the coefficients to zero
			for (int i=0; i < NumberOfColumns; i++) {
				Status = CPXchgcoef (CPLEXenv, CPLEXModel, InEquation->Index, i, 0);
				if (Status) {
					FErrorFile() << "Failed to change constraint: " << InEquation->Index << endl;
					FlushErrorFile();
					return FAIL;
				}
			}
			//Next I set all of the nonzero coefficients according to the input equation
			for (int i=0; i < int(InEquation->Variables.size()); i++) {
				Status = CPXchgcoef (CPLEXenv, CPLEXModel, InEquation->Index, InEquation->Variables[i]->Index, InEquation->Coefficient[i]);
				if (Status) {
					FErrorFile() << "Failed to change constraint: " << InEquation->Index << endl;
					FlushErrorFile();
					return FAIL;
				}
			}
			
			char* Sense = new char[1];
			
			if (InEquation->ConstraintMeaning.compare("chemical potential constraint") == 0 && InEquation->Loaded == false) {
				Sense[0] = 'L';
				
				Status = CPXchgcoef (CPLEXenv, CPLEXModel, InEquation->Index, -1, InEquation->LoadedRightHandSide);
				Status = CPXchgsense (CPLEXenv, CPLEXModel, 1, &(InEquation->Index), Sense);
				
			} else {
			
				//Now I change the RHS of the constraint
				Status = CPXchgcoef (CPLEXenv, CPLEXModel, InEquation->Index, -1, InEquation->RightHandSide);
	
				//Also change the sense of the constraint if nec
				
				if (InEquation->EqualityType == EQUAL) {
					if (InEquation->QuadOne.size() > 0) {
						delete [] Sense;
						FErrorFile() << "Quadratic constraints cannot be equivalent constraints in CPLEX." << endl;
						FlushErrorFile();
						return FAIL;
					} else {
						Sense[0] = 'E';
					}
				} else if (InEquation->EqualityType == LESS) {
					Sense[0] = 'L';
				} else if (InEquation->EqualityType == GREATER) {
					Sense[0] = 'G';
				} else {
					delete [] Sense;
					FErrorFile() << "Unrecognized constraint type: " << InEquation->ConstraintType << endl;
					FlushErrorFile();
					return FAIL;
				}
	
				Status = CPXchgsense (CPLEXenv, CPLEXModel, 1, &(InEquation->Index), Sense);
				if (Status) {
					FErrorFile() << "Failed to change constraint: " << InEquation->Index << endl;
					FlushErrorFile();
					return FAIL;
				}
			}
		}
	}
	return SUCCESS;
}
예제 #12
0
void PartitionedColoringModel::addRestrictions() {
	int status;
	int amountOfNewColumns = 0;
	
	int amountOfPartitionRestrictions = this->graph->amountOfPartitions();
	int amountOfAdjacentColorRestrictions = this->graph->amountOfNodes() * this->graph->amountOfEdges();
	int amountOfWChecksColorUsedRestrictions = this->graph->amountOfNodes() * this->graph->amountOfNodes();
	int amountOfNewRestrictions = amountOfPartitionRestrictions + amountOfAdjacentColorRestrictions + amountOfWChecksColorUsedRestrictions;
	
	int amountOfNonZeroCoefficientsDueToPartitions = this->graph->amountOfNodes() * this->graph->amountOfNodes();
	int amountOfNonZeroCoefficientsDueToAdjacentColor = amountOfAdjacentColorRestrictions * 2;
	int amountOfNonZeroCoefficientsDueWChecksColorUsed = amountOfWChecksColorUsedRestrictions * 2;
	int amountOfNonZeroCoefficients = amountOfNonZeroCoefficientsDueToPartitions + amountOfNonZeroCoefficientsDueToAdjacentColor + amountOfNonZeroCoefficientsDueWChecksColorUsed;
	
	int nonZeroCoefficients = 0;
	int restrictionNumber = 0;

	char *sense = new char[amountOfNewRestrictions];
	double *independentTerm = new double[amountOfNewRestrictions];
	int *restrictionsIndex = new int[amountOfNewRestrictions];
	int *coefficientsIndex = new int[amountOfNonZeroCoefficients];
	double *coefficientsValues = new double[amountOfNonZeroCoefficients];
	
	// We add K restrictions, one for each partition.
	for(unsigned int k = 1; k <= this->graph->amountOfPartitions(); k++) {
		restrictionsIndex[restrictionNumber] = nonZeroCoefficients;
		independentTerm[restrictionNumber] = 1.0;
		sense[restrictionNumber] = 'E';
		
		//cout << " Adding restriction for partition number " << k << endl;
		
		vector<Node*> partition = this->graph->getPartition(k);
		for(unsigned int n = 0; n < partition.size(); n++) {
			for(unsigned int j = 1; j <= this->graph->amountOfNodes(); j++) {
				//cout << " Node " << partition.at(n)->getId() << " with color " << j << endl;
				coefficientsIndex[nonZeroCoefficients] = this->xVariablePositionFromModelIndex(partition.at(n)->getId(), j);
				coefficientsValues[nonZeroCoefficients] = 1.0;
				nonZeroCoefficients++;
			}
		}
		
		restrictionNumber++;
	}
	
	// Not same color in adjacent nodes.
	vector<Edge> edges = this->graph->getEdges();
	for(unsigned int e = 0; e < edges.size(); e++) {
		for(unsigned int c = 1; c <= this->graph->amountOfNodes(); c++) {
			restrictionsIndex[restrictionNumber] = nonZeroCoefficients;
			independentTerm[restrictionNumber] = 1.0;
			sense[restrictionNumber] = 'L';
			
			Node *nodeA = edges.at(e).getNodeA();
			Node *nodeB = edges.at(e).getNodeB();
			//cout << " Adding restriction for edge (" << nodeA->getId() << ", " << nodeB->getId() << ") and color " << c << endl;
			
			coefficientsIndex[nonZeroCoefficients] = this->xVariablePositionFromModelIndex(nodeA->getId(), c);
			coefficientsValues[nonZeroCoefficients] = 1.0;
			nonZeroCoefficients++;
			coefficientsIndex[nonZeroCoefficients] = this->xVariablePositionFromModelIndex(nodeB->getId(), c);
			coefficientsValues[nonZeroCoefficients] = 1.0;
			nonZeroCoefficients++;
			restrictionNumber++;
		}
	}

	// Wj actually counts if color j was used restrictions.
	for(unsigned int i = 1; i <= this->graph->amountOfNodes(); i++) {
		for(unsigned int j = 1; j <= this->graph->amountOfNodes(); j++) {
			restrictionsIndex[restrictionNumber] = nonZeroCoefficients;
			independentTerm[restrictionNumber] = 0.0;
			sense[restrictionNumber] = 'L';
			
			//cout << " Adding restriction for x_" << i << "_" << j << " <= w_" << j << endl;
			
			coefficientsIndex[nonZeroCoefficients] = this->wVariablePositionFromModelIndex(j);
			coefficientsValues[nonZeroCoefficients] = -1.0;
			nonZeroCoefficients++;
			coefficientsIndex[nonZeroCoefficients] = this->xVariablePositionFromModelIndex(i, j);
			coefficientsValues[nonZeroCoefficients] = 1.0;
			nonZeroCoefficients++;
			restrictionNumber++;
		}
	}
	
	if(nonZeroCoefficients != amountOfNonZeroCoefficients) {
		cerr << "Cantidad de coeficientes no nulos erronea." << endl;
		cerr << nonZeroCoefficients << " != " << amountOfNonZeroCoefficients << endl;
		exit(1);
	}

	status = CPXaddrows(this->cplexEnvironment,
						this->linearProblem,
						amountOfNewColumns,
						amountOfNewRestrictions,
						nonZeroCoefficients,
			  			independentTerm,
			  			sense,
			  			restrictionsIndex,
			  			coefficientsIndex,
			  			coefficientsValues,
			  			NULL,
			  			NULL);
      
	if (status) {
		cerr << "Problema agregando restricciones." << endl;
		exit(1);
	}

	delete [] sense;
	delete [] independentTerm;
	delete [] restrictionsIndex;
	delete [] coefficientsIndex;
	delete [] coefficientsValues;
}
예제 #13
0
 int main(int argc, char **argv)
 {
    int status = 0;
    CPXENVptr env = NULL;
    CPXLPptr lp = NULL;

    double obj[NUMCOLS];
    double lb[NUMCOLS];
    double ub[NUMCOLS];
    double x[NUMCOLS];
    int rmatbeg[NUMROWS];
    int rmatind[NUMNZ];
    double rmatval[NUMNZ];
    double rhs[NUMROWS];
    char sense[NUMROWS];
    char ctype[NUMCOLS];

    int solstat;
    double objval;

    env = CPXopenCPLEX (&status);


    CPXsetintparam(env, CPX_PARAM_MIPCBREDLP, CPX_OFF);
    CPXsetintparam(env, CPX_PARAM_PRELINEAR, CPX_OFF);
    /* Turn on traditional search for use with control callbacks */

    // status = CPXsetintparam (env, CPXPARAM_MIP_Strategy_Search,
    //                        CPX_MIPSEARCH_TRADITIONAL);


    lp = CPXcreateprob(env, &status, "lpex1");
    //CPXchgprobtype(env, lp, CPXPROB_MILP);

    CPXchgobjsen (env, lp, CPX_MAX);

    status = CPXsetlazyconstraintcallbackfunc (env, callback,
                                      NULL);


    lb[0] = 0.0;
    ub[0] = 40.0;

    lb[1] = 0.0;
    ub[1] = CPX_INFBOUND;

    lb[2] = 0.0;
    ub[2] = CPX_INFBOUND;

    obj[0] = 1.0;
    obj[1] = 2.0;
    obj[2] = 3.0;

    status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, NULL);

    rmatbeg[0] = 0;
    rmatind[0] = 0;     rmatind[1] = 1;     rmatind[2] = 2;
    rmatval[0] = -1.0;  rmatval[1] = 1.0;   rmatval[2] = 1.0;   sense[0] = 'L';     rhs[0] = 20.0;

    rmatbeg[1] = 3;
    rmatind[3] = 0;     rmatind[4] = 1;     rmatind[5] = 2;
    rmatval[3] = 1.0;   rmatval[4] = -3.0;  rmatval[5] = 1.0;   sense[1] = 'L';     rhs[1] = 30.0;

    ctype[0] = 'I'; ctype[1] = 'C'; ctype[2] = 'I';

    // status = CPXaddusercuts (env, lp, cutcnt, cutnzcnt, cutrhs,
    //                      cutsense, cutbeg, cutind, cutval, NULL);
    //status = CPXaddusercuts(env, lp, NUMROWS, NUMNZ, rhs, sense, rmatbeg, rmatind, rmatval, NULL );

    status = CPXaddrows (env, lp, 0, NUMROWS, NUMNZ, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL);
    status = CPXcopyctype (env, lp, ctype);

    // cuts
    int cmatbeg[1] = {0};
    int cmatind[3] = {0,1,2};
    double cmatval[3] = {1,0,0};
    char csense[1] = {'L'};
    double crhs[1] = {20};

    //CPXaddusercuts doesnt work for some f*****g reason

    //status = CPXaddlazyconstraints(env, lp, 1, 3, crhs, csense, cmatbeg, cmatind, cmatval, NULL );
    if ( status ) {
      fprintf (stderr, "Some f*****g error, status = %d.\n", status);
   }



    status = CPXmipopt (env, lp);



   /* Write the output to the screen. */
    // solstat = CPXgetstat (env, lp);
    // printf ("\nSolution status = %d\n", solstat);
    // status = CPXgetobjval (env, lp, &objval);
    // printf ("Solution value  = %f\n\n", objval);

    status = CPXsolution (env, lp, &solstat, &objval, x, NULL, NULL, NULL);
    printf ("\nSolution status = %d\n", solstat);
    printf ("Solution value = %f\n", objval);
    printf ("Solution= [%f, %f, %f]\n\n", x[0], x[1], x[2]);

    printf("This is great stuff\n");


    return 0;
 }
예제 #14
0
파일: main.cpp 프로젝트: germanromano/invop
bool agregar_restricciones_ciclos(const vector<vector<bool> > *adyacencias, double *sol, CPXENVptr env, CPXLPptr lp,
									int cant_colores_disp, int cant_variables){

	//vector<bool> nodos_pintados(adyacencias->size(), false);
	//for(unsigned int i = 0; i < adyacencias->size(); i++) // recorro nodos
	//	for(int j = 0; j < cant_colores_disp; j++)	// recorro colores
	//		if(sol[i*cant_colores_disp + j] > TOL){
	//			nodos_pintados[i] = true;
	//			break;
	//		}
	
	//----------------------- IDENTIFICO COLORES USADOS
	vector<bool> colores_usados(cant_colores_disp, false);
	for(int i = cant_variables - cant_colores_disp; i < cant_variables; i++)
		if(sol[i] > TOL)
			colores_usados[i - (cant_variables - cant_colores_disp)] = true;

	//----------------------- CONSTRUYO LOS CICLOS
	vector<vector<int> > odd_cycles;	
	find_odd_cycle(adyacencias, &odd_cycles, sol, cant_colores_disp, cant_variables);
	//for (int i = 0; i< odd_cycles.size(); i++){
	//	cout << "odd_cycles.size() = " << odd_cycles[i].size() << endl;
	//	for (int j = 0; j<odd_cycles[i].size(); j++){
	//		cout << "odd_cycle[" << i << "][" << j << "]: " << odd_cycles[i][j] << endl;
	//	}
	//}

	//----------------------- CHEQUEO DE RESTRICCIONES VIOLADAS
	bool res = false;
	int status, violadas = 0;
	double sum;
	
	int ccnt = 0; //numero nuevo de columnas en las restricciones.
	int rcnt = 1; //cuantas restricciones se estan agregando.
	int nzcnt = 0; //# de coeficientes != 0 a ser agregados a la matriz. Solo se pasan los valores que no son cero.
	char sense[] = {'L'}; // Sentido de la desigualdad. 'G' es mayor o igual y 'E' para igualdad.
	double rhs[] = {0}; // Termino independiente de las restricciones.
	int matbeg[] = {0}; //Posicion en la que comienza cada restriccion en matind y matval.
	int *matind = new int[cant_variables]; // Array con los indices de las variables con coeficientes != 0 en la desigualdad.
	double *matval = new double[cant_variables]; // Array que en la posicion i tiene coeficiente ( != 0) de la variable cutind[i] en la restriccion.
	
	for(unsigned int c = 0; c < odd_cycles.size(); c++){ // recorro ciclos con algun nodo pintado
		for(unsigned int j = 0; j < cant_colores_disp; j++){ // recorro colores
			if(colores_usados[j]){
				sum = 0.0;
				for(unsigned int p = 0; p < odd_cycles[c].size(); p++){ // recorro nodos de los ciclos c
					sum += sol[odd_cycles[c][p] * cant_colores_disp + j];
				}
				
				if (sum - ((odd_cycles[c].size()-1)/2)*sol[cant_variables - cant_colores_disp + j] > TOL){
					//cargo restriccion asociada al ciclo c y el color j
					nzcnt = 0;
					for(unsigned int p = 0; p < cant_variables; p++){ // reset de estructuras
						matind[p] = 0;
						matval[p] = 0;
					}
					for(unsigned int p = 0; p < odd_cycles[c].size(); p++){ // recorro nodos del ciclo c
						matind[nzcnt] = odd_cycles[c][p] * cant_colores_disp + j; // X_p_j
						matval[nzcnt] = 1;
						nzcnt++;
					}
					matind[nzcnt] = cant_variables - cant_colores_disp + j; // W_j
					matval[nzcnt] = (odd_cycles[c].size()-1)/(-2.0);
					nzcnt++; 

					status = CPXaddrows(env, lp, ccnt, rcnt, nzcnt, rhs, sense, matbeg, matind, matval, NULL, NULL);

					res = true;
					violadas++;
				}
			}
		}
	}
	cout << "Restr. ciclos violadas: \t" << violadas << endl;

	delete[] matind;
	delete[] matval;
	return res;
}
예제 #15
0
파일: socpex1.c 프로젝트: annaPolytech/PRD
/* This function creates the following model:
 *   Minimize
 *    obj: x1 + x2 + x3 + x4 + x5 + x6
 *   Subject To
 *    c1: x1 + x2      + x5      = 8
 *    c2:           x3 + x5 + x6 = 10
 *    q1: [ -x1^2 + x2^2 + x3^2 ] <= 0
 *    q2: [ -x4^2 + x5^2 ] <= 0
 *   Bounds
 *    x2 Free
 *    x3 Free
 *    x5 Free
 *   End
 * which is a second order cone program in standard form.
 * The function returns a true value on success and false on error.
 * The function also sets up *cone_p as follows:
 * (*cone_p)[j] >= 0              Column j is contained in a cone constraint
 *                                and is the cone head variable of that
 *                                constraint. The index of the respective
 *                                quadratic constraint is given by (*cone_p)[j].
 * (*cone_p)[j] = NOT_CONE_HEAD   Column j is contained in a cone constraint
 *                                but is not the cone head variable of that
 *                                constraint.
 * (*cone_p)[j] = NOT_IN_CONE     Column j is not contained in any cone
 *                                constraint.
 */
static int
createmodel (CPXENVptr env, CPXLPptr lp, int **cone_p)
{
   /* Column data. */
   static double const obj[]        = {  1.0,  1.0,  1.0,  1.0,  1.0,  1.0 };
   static double const lb[]         = {  0.0, -INF, -INF,  0.0, -INF,  0.0 };
   static double const ub[]         = {  INF,  INF,  INF,  INF,  INF,  INF };
   static char const *const cname[] = { "x1", "x2", "x3", "x4", "x5", "x6" };

   /* Row data. */
   static double const rval[]       = { 1.0, 1.0, 1.0,    1.0, 1.0, 1.0 };
   static int const rind[]          = {   0,   1,   4,      2,   4,   5 };
   static int const rbeg[]          = {   0,                3           };
   static double const rhs[]        = { 8.0,             10.0           };
   static char const sense[]        = { 'E',              'E'           };
   static char const *const rname[] = { "c1",             "c2"          };

   /* Data for second order cone constraints. */
   static double const qval[]  = { -1.0, 1.0, 1.0 }; /* Same for all Q cons. */
   static double const qrhs    = 0.0;                /* Same for all Q cons. */
   static char const qsense    = 'L';                /* Same for all Q cons. */
   static int const qind1[] = { 0, 1, 2 };
   static int const qind2[] = { 3, 4 };

   int status;
   int ok = 0;
   int *cone = NULL;

   CPXCHANNELptr errc;

   /* Get the channel for printing error messages. */
   if ( (status = CPXgetchannels (env, NULL, NULL, &errc, NULL)) != 0 )
      goto TERMINATE;

   cone = malloc ((sizeof (obj) / sizeof (obj[0])) * sizeof (*cone));
   if ( cone == NULL ) {
      CPXmsg (errc, "Out of memory!\n");
      goto TERMINATE;
   }

   status = CPXchgobjsen (env, lp, CPX_MIN);
   if ( status != 0 )
      goto TERMINATE;

   status = CPXnewcols (env, lp, sizeof (obj) / sizeof (obj[0]),
                        obj, lb, ub, NULL, (char **)cname);
   if ( status != 0 )
      goto TERMINATE;

   status = CPXaddrows (env, lp, 0, sizeof (rhs) / sizeof (rhs[0]),
                        sizeof (rval) / sizeof (rval[0]), rhs, sense,
                        rbeg, rind, rval, NULL, (char **)rname);
   if ( status != 0 )
      goto TERMINATE;

   status = CPXaddqconstr (env, lp, 0, sizeof (qind1) / sizeof (qind1[0]),
                           qrhs, qsense, NULL, NULL,
                           qind1, qind1, qval, "q1");
   if ( status != 0 )
      goto TERMINATE;
   cone[0] = 0;
   cone[1] = NOT_CONE_HEAD;
   cone[2] = NOT_CONE_HEAD;
   status = CPXaddqconstr (env, lp, 0, sizeof (qind2) / sizeof (qind2[0]),
                           qrhs, qsense, NULL, NULL,
                           qind2, qind2, qval, "q2");
   if ( status != 0 )
      goto TERMINATE;
   cone[3] = 1;
   cone[4] = NOT_CONE_HEAD;

   cone[5] = NOT_IN_CONE;

   ok = 1;
 TERMINATE:
   if ( !ok )
      free (cone);

   *cone_p = cone;

   return ok;
}
예제 #16
0
EXPORT int fit(const double * X_p, const double * Yl_p, double* w, int postags, int numSamples, int numFeatures, double C, double epsilon,
        int numBoxConstraints, const double * boxValues, const int64_t * boxIndices, const double * boxMatrix)
{
  int i,j,k;
  CPXENVptr     env = NULL;
  CPXLPptr      lp = NULL;
  int status;
  char probname[] = "Testproblem";

  int numrows = postags + numSamples;
  int numcols = numFeatures + 1 + numrows;
  int nnzcol = numFeatures + 2;
  int numEntries = nnzcol * numrows;

  char *sense = (char*) malloc((numrows) * sizeof(char));
  double *lb = (double*) malloc(numcols * sizeof(double));
  double *ub = (double*) malloc(numcols * sizeof(double));
  double *obj = (double*) malloc(numcols * sizeof(double));
  double *rhs = (double*) malloc(numrows * sizeof(double));
  double *tagarray = (double*) malloc(numrows * sizeof(double));

  int      *matbeg = (int*) malloc(numcols * sizeof(int));
  int      *matcnt = (int*) malloc(numcols * sizeof(int));
  int      *matind = (int*) malloc(numEntries * sizeof(int));
  double   *matval = (double* ) malloc(numEntries * sizeof(double));
  double   *qsepvec = (double*) malloc((numcols + 2 * numBoxConstraints) * sizeof(double));

  int       numBoxSamples = 0;
  double   *dens = NULL;
  double   *boxConstraints = NULL;
  int      *boxrmatbeg = NULL;
  int      *boxrmatind = NULL;
  char     *boxSense = NULL;
  int      *hmatbeg = NULL;
  int      *hmatind = NULL;
  double   *hmatval = NULL;
  char     *hSense = NULL;
  env = CPXopenCPLEX (&status);
  lp = CPXcreateprob (env, &status, probname);
  status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_OFF);
  status = CPXsetintparam (env, CPX_PARAM_BARCOLNZ, 2);
  if ( status ) {
    fprintf (stderr,
             "Failure to create CPLEX environment, error %d.\n", status);
    goto TERMINATE;
  }

  if (sense == NULL || lb == NULL || ub == NULL || obj == NULL
      || rhs == NULL || tagarray == NULL || qsepvec == NULL) {
    status = 1;
    goto TERMINATE;
  }


  for (i = 0; i < postags; ++i) {
    tagarray[i] = 1;
    sense[i] = 'G';
  }
  for (i = postags; i < numrows; ++i) {
    tagarray[i] = -1;
    sense[i] = 'L';
  }
  for (i = 0; i < postags; ++i) {
    rhs[i] = Yl_p[i] - tagarray[i] * epsilon ;
  }
  for (i = postags; i < numrows; ++i) {
    rhs[i] = Yl_p[i - postags] - tagarray[i] * epsilon ;
  }
  for (i = 0; i < numFeatures + 1; ++i) {
    lb[i] = -CPX_INFBOUND;
    ub[i] = CPX_INFBOUND;
    matbeg[i] = i * (numrows);
    matcnt[i] = numrows;
  }
  for (i = numFeatures + 1; i < numcols; ++i) {
    lb[i] = 0;
    ub[i] = CPX_INFBOUND;
    matbeg[i] = (numFeatures + 1) * numrows + (i - numFeatures - 1);
    matcnt[i] = 1;
  }

  for (j = 0; j < numFeatures; ++j) {
    for (i = 0; i < postags; ++i) {
      matind[j * numrows + i] = i;
      matval[j * (numrows) + i] = X_p[i * numFeatures + j];
    }
    for (i = postags; i < numrows; ++i) {
      matind[j * numrows + i] = i;
      matval[j * (numrows) + i] = X_p[(i - postags) * numFeatures + j];
    }
  }

  /* printf("Status ok\n");*/
  for (i = 0; i < numrows; ++i) {
    matind[numFeatures * numrows + i] = i;
    matval[numFeatures * numrows + i] = 1;
  }

  for (i = 0; i < numrows; ++i) {
    matind[(numFeatures + 1) * numrows + i] = i;
    matval[(numFeatures + 1) * numrows + i] = tagarray[i];
  }

  for (i = 0; i < numFeatures; ++i){
    qsepvec[i] = 1;
    obj[i] = 0;
  }
  obj[numFeatures] = 0;
  qsepvec[numFeatures] = 0;
  for (i = numFeatures + 1; i < numcols; ++i){
    qsepvec[i] = 2 * C;
    obj[i] = 0;
  }

  /*printf("Status ok\n");*/
  status = CPXcopylp (env, lp, numcols, numrows, 1, obj, rhs,
                      sense, matbeg, matcnt, matind, matval,
                      lb, ub, NULL);

  status = CPXcopyqpsep (env, lp, qsepvec);
  status = CPXwriteprob (env, lp, "qpex1.lp", NULL);
  status = CPXqpopt (env, lp);
  status = CPXgetx (env, lp, w, 0, numFeatures);

  if (numBoxConstraints > 0) {
    numBoxSamples = (int) boxIndices[numBoxConstraints];

    dens = (double*) malloc(numBoxSamples * sizeof(double));
    boxConstraints = (double*) calloc(numBoxConstraints * (numFeatures + 2), sizeof(double));
    boxrmatbeg = (int*) malloc(numBoxConstraints * sizeof(int));
    boxrmatind = (int*) malloc(numBoxConstraints * (numFeatures + 2) * sizeof(int));
    boxSense = (char*) malloc(numBoxConstraints * sizeof(char));

    hmatbeg = (int*) malloc(numBoxSamples * sizeof(int));
    hmatind = (int*) malloc(numBoxSamples * (numFeatures + 1) * sizeof(int));
    hmatval = (double* ) malloc(numBoxSamples * (numFeatures + 1) * sizeof(double));
    hSense = (char* ) malloc(numBoxSamples * sizeof(char));

    if (dens == NULL || boxConstraints == NULL || boxrmatbeg == NULL || boxrmatind == NULL
        || boxSense == NULL) {
      status = 1;
      goto TERMINATE;
    }
    if (hmatbeg == NULL || hmatind == NULL || hmatval == NULL || hSense == NULL) {
      status = 1;
      goto TERMINATE;
    }

    /*for every entry in the box features, check if it's background or
    foreground
    double   *boxrmatval = (double* ) malloc( * sizeof(double));*/
    
    for (i = 0; i < numBoxSamples; ++i) {
      dens[i] = w[numFeatures];
      for (j = 0; j < numFeatures; ++j) {
        dens[i] += boxMatrix[i * numFeatures + j] * w[j];
      }
    }
    for (i = 0; i < numBoxSamples; ++i) {
      if (dens[i] > 0){
        dens[i] = 1;
      }
      else {
        dens[i] = 0;
      }
      /* printf("Density: %f\n", dens[i]); */
    }

    /*printfarray(boxConstraints, numBoxConstraints, numFeatures + 2, "boxConstraints"); */

    for (k = 0; k < numBoxConstraints; ++k) {
      boxrmatbeg[k] = k * (numFeatures + 2);
      for (i = (int) boxIndices[k]; i < boxIndices[k + 1]; ++i){
        for (j = 0; j < numFeatures; ++j){
          boxConstraints[k * (numFeatures + 2) + j]  += dens[i] * boxMatrix[i * numFeatures + j];
        }
        boxConstraints[k * (numFeatures + 2) + numFeatures] += dens[i];
      }
    }
    for (i = 0; i < numBoxConstraints; ++i) {
      for (j = 0; j < numFeatures + 1; ++j) {
        boxrmatind[i * (numFeatures + 2) + j] = j;
      }
      boxrmatind[i * (numFeatures + 2) + numFeatures + 1] = numcols + i;
    }

    for (i = 0; i < numBoxConstraints; ++i) {
      boxSense[i] = 'L';
    }
    for (i = 0; i < numBoxConstraints; ++i) {
      boxConstraints[i * (numFeatures + 2) + numFeatures+1] = - 1;
    }
    status = CPXaddrows(env, lp, numBoxConstraints, numBoxConstraints, numBoxConstraints * (numFeatures + 2), boxValues,
                        boxSense, boxrmatbeg, boxrmatind, boxConstraints, NULL, NULL);
    for (i = 0; i < numBoxConstraints; ++i) {
      boxrmatind[i * (numFeatures + 2) + numFeatures + 1] = numcols + numBoxConstraints + i;
    }

    for (i = 0; i < numBoxConstraints; ++i) {
      boxSense[i] = 'G';
    }
    for (i = 0; i < numBoxConstraints; ++i) {
      boxConstraints[i * (numFeatures + 2) + numFeatures+1] = + 1;
    }
    status = CPXaddrows(env, lp, numBoxConstraints, numBoxConstraints, numBoxConstraints * (numFeatures + 2), boxValues,
                        boxSense, boxrmatbeg, boxrmatind, boxConstraints, NULL, NULL);

    for (i = 0; i < numBoxConstraints; ++i) {
      qsepvec[numcols + i] = 2 * C / (boxIndices[i + 1] - boxIndices[i]);
      qsepvec[numcols + i + numBoxConstraints] = 2 * C / (boxIndices[i + 1] - boxIndices[i]);
    /*  printf("%d, %d\n",boxIndices[i], boxIndices[i + 1]);
      printf("%f, %f\n", qsepvec[numcols+i], qsepvec[numcols + i + numBoxConstraints]);
      */
    }

    /*adding hard constraints:*/



    for (i = 0; i < numBoxSamples; ++i) {
      hmatbeg[i] = i * (numFeatures + 1);
      for (j = 0; j < numFeatures; ++j) {
        hmatind[i * (numFeatures + 1) + j] = j;
        hmatval[i * (numFeatures + 1) + j] = boxMatrix[i * numFeatures + j];
      }
      hmatind[i * (numFeatures + 1) + numFeatures] = numFeatures;
      hmatval[i * (numFeatures + 1) + numFeatures] = 1;

      if (dens[i] == 0){
        hSense[i]  = 'L';
      }
      else {
        hSense[i] = 'G';
      }
    }
    /* printf("Density: %f\n", dens[i]);
        printf("Close, but no cigar\n");
    printiarray(hmatind, backgroundcount, numFeatures + 1, "");
        printf("Close, but no cigar\n"); */

    status = CPXaddrows(env, lp, 0, numBoxSamples, numBoxSamples* (numFeatures + 1), NULL,
                        hSense, hmatbeg, hmatind, hmatval, NULL, NULL);
    /*    printf("WHY IS NOTHING HAPPENING\n") */
    printf ("Number of Columns in Problem: %d\n", CPXgetnumcols(env, lp));
    printf("%d\n", numcols + (2 * numBoxConstraints));
    status = CPXcopyqpsep (env, lp, qsepvec);
    status = CPXwriteprob (env, lp, "qpex1.lp", NULL);
    status = CPXqpopt (env, lp);
    status = CPXgetx (env, lp, w, 0, numFeatures);

    /*for (i = 0; i < numBoxSamples; ++i) {
      density[i] = w[numFeatures];
      for (j = 0; j < numFeatures; ++j) {
      density[i] += boxMatrix[i * numFeatures + j] * w[j];
      }
      } */
  }

  /*printf("Objective value: %f\n", sol);
    double * slack = malloc((numcols + 2 * numBoxConstraints) * sizeof(double));
    status = CPXgetx (env, lp, slack, 0, numcols + 2 * numBoxConstraints - 1);
    printfarray(slack, numcols + 2 * numBoxConstraints, 1, "Slack");
    */
TERMINATE:;

  free_and_null ((char **) &obj);
  free_and_null ((char **) &rhs);
  free_and_null ((char **) &sense);
  free_and_null ((char **) &tagarray);
  free_and_null ((char **) &lb);
  free_and_null ((char **) &ub);
  free_and_null ((char **) &matbeg);
  free_and_null ((char **) &matcnt);
  free_and_null ((char **) &matind);
  free_and_null ((char **) &matval);
  free_and_null ((char **) &qsepvec);

  free_and_null ((char **) &dens);
  free_and_null ((char **) &boxConstraints);
  free_and_null ((char **) &boxrmatbeg);
  free_and_null ((char **) &boxrmatind);

  free_and_null ((char **) &hmatbeg);
  free_and_null ((char **) &hmatind);
  free_and_null ((char **) &hmatval);
  free_and_null ((char **) &hSense);
  /*free_and_null ((char **) &slack); */
  return (status);

}
예제 #17
0
int
main (void)
{
    /* Declare pointers for the variables and arrays that will contain
       the data which define the LP problem.  The setproblemdata() routine
       allocates space for the problem data.  */

    char     *probname = NULL;
    int      numcols;
    int      numrows;
    int      objsen;
    double   *obj = NULL;
    double   *rhs = NULL;
    char     *sense = NULL;
    int      *matbeg = NULL;
    int      *matcnt = NULL;
    int      *matind = NULL;
    double   *matval = NULL;
    double   *lb = NULL;
    double   *ub = NULL;
    int      *qmatbeg = NULL;
    int      *qmatcnt = NULL;
    int      *qmatind = NULL;
    double   *qmatval = NULL;

    /* Declare pointers for the variables that will contain the data
       for the constraint that cuts off certain local optima. */

    int      numrows_extra;
    int      numnnz_extra;
    double   *rhs_extra = NULL;
    char     *sense_extra = NULL;
    int      *rmatbeg = NULL;
    int      *rmatind = NULL;
    double   *rmatval = NULL;
    int      rowind[1];

    /* Declare and allocate space for the variables and arrays where we
       will store the optimization results including the status, objective
       value, variable values, dual values, row slacks and variable
       reduced costs. */

    int      solstat;
    double   objval;

    CPXENVptr     env = NULL;
    CPXLPptr      lp = NULL;
    int           status;

    /* Initialize the CPLEX environment */

    env = CPXopenCPLEX (&status);

    /* If an error occurs, the status value indicates the reason for
       failure.  A call to CPXgeterrorstring will produce the text of
       the error message.  Note that CPXopenCPLEX produces no output,
       so the only way to see the cause of the error is to use
       CPXgeterrorstring.  For other CPLEX routines, the errors will
       be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON.  */

    if ( env == NULL ) {
        char  errmsg[CPXMESSAGEBUFSIZE];
        fprintf (stderr, "Could not open CPLEX environment.\n");
        CPXgeterrorstring (env, status, errmsg);
        fprintf (stderr, "%s", errmsg);
        goto TERMINATE;
    }

    /* Turn on output to the screen */

    status = CPXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
    if ( status ) {
        fprintf (stderr,
                 "Failure to turn on screen indicator, error %d.\n", status);
        goto TERMINATE;
    }

    /* Fill in the data for the problem.  */

    status = setproblemdata (&probname, &numcols, &numrows, &objsen, &obj,
                             &rhs, &sense, &matbeg, &matcnt, &matind,
                             &matval, &lb, &ub, &qmatbeg, &qmatcnt,
                             &qmatind, &qmatval,
                             &numrows_extra, &numnnz_extra,
                             &rhs_extra, &sense_extra,
                             &rmatbeg, &rmatind, &rmatval);
    if ( status ) {
        fprintf (stderr, "Failed to build problem data arrays.\n");
        goto TERMINATE;
    }

    /* Create the problem. */

    lp = CPXcreateprob (env, &status, probname);

    /* A returned pointer of NULL may mean that not enough memory
       was available or there was some other problem.  In the case of
       failure, an error message will have been written to the error
       channel from inside CPLEX.  In this example, the setting of
       the parameter CPXPARAM_ScreenOutput causes the error message to
       appear on stdout.  */

    if ( lp == NULL ) {
        fprintf (stderr, "Failed to create problem.\n");
        goto TERMINATE;
    }

    /* Now copy the LP part of the problem data into the lp */

    status = CPXcopylp (env, lp, numcols, numrows, objsen, obj, rhs,
                        sense, matbeg, matcnt, matind, matval,
                        lb, ub, NULL);

    if ( status ) {
        fprintf (stderr, "Failed to copy problem data.\n");
        goto TERMINATE;
    }

    status = CPXcopyquad (env, lp, qmatbeg, qmatcnt, qmatind, qmatval);
    if ( status ) {
        fprintf (stderr, "Failed to copy quadratic matrix.\n");
        goto TERMINATE;
    }


    /* When a non-convex objective function is present, CPLEX will
       return error CPXERR_Q_NOT_POS_DEF unless the parameter
       CPXPARAM_OptimalityTarget is set to accept first-order optimal
       solutions.  */
    status = CPXsetintparam (env, CPXPARAM_OptimalityTarget,
                             CPX_OPTIMALITYTARGET_FIRSTORDER);
    if ( status ) goto TERMINATE;

    /* Optimize the problem and obtain solution. */

    status = optimize_and_report(env, lp, &solstat, &objval);
    if ( status ) goto TERMINATE;


    /* Add a constraint to cut off the solution at (-1, 1) */

    status = CPXaddrows (env, lp, 0, numrows_extra, numnnz_extra,
                         rhs_extra, sense_extra,
                         rmatbeg, rmatind, rmatval,
                         NULL, NULL);
    if ( status ) goto TERMINATE;

    status = optimize_and_report(env, lp, &solstat, &objval);
    if ( status ) goto TERMINATE;


    /* Reverse the sense of the new constraint to cut off the solution at (1, 1) */

    rowind[0] = CPXgetnumrows (env, lp) - 1;
    status    = CPXchgsense (env, lp, 1, rowind, "L");
    if ( status ) goto TERMINATE;

    status = optimize_and_report(env, lp, &solstat, &objval);
    if ( status ) goto TERMINATE;

    /* Finally, write a copy of the problem to a file. */

    status = CPXwriteprob (env, lp, "indefqpex1.lp", NULL);
    if ( status ) {
        fprintf (stderr, "Failed to write LP to disk.\n");
        goto TERMINATE;
    }


TERMINATE:

    /* Free up the problem as allocated by CPXcreateprob, if necessary */

    if ( lp != NULL ) {
        status = CPXfreeprob (env, &lp);
        if ( status ) {
            fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status);
        }
    }

    /* Free up the CPLEX environment, if necessary */

    if ( env != NULL ) {
        status = CPXcloseCPLEX (&env);

        /* Note that CPXcloseCPLEX produces no output,
           so the only way to see the cause of the error is to use
           CPXgeterrorstring.  For other CPLEX routines, the errors will
           be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON. */

        if ( status ) {
            char  errmsg[CPXMESSAGEBUFSIZE];
            fprintf (stderr, "Could not close CPLEX environment.\n");
            CPXgeterrorstring (env, status, errmsg);
            fprintf (stderr, "%s", errmsg);
        }
    }

    /* Free up the problem data arrays, if necessary. */

    free_and_null ((char **) &probname);
    free_and_null ((char **) &obj);
    free_and_null ((char **) &rhs);
    free_and_null ((char **) &sense);
    free_and_null ((char **) &matbeg);
    free_and_null ((char **) &matcnt);
    free_and_null ((char **) &matind);
    free_and_null ((char **) &matval);
    free_and_null ((char **) &lb);
    free_and_null ((char **) &ub);
    free_and_null ((char **) &qmatbeg);
    free_and_null ((char **) &qmatcnt);
    free_and_null ((char **) &qmatind);
    free_and_null ((char **) &qmatval);
    free_and_null ((char **) &rhs_extra);
    free_and_null ((char **) &sense_extra);
    free_and_null ((char **) &rmatbeg);
    free_and_null ((char **) &rmatind);
    free_and_null ((char **) &rmatval);

    return (status);

}  /* END main */
예제 #18
0
void mexFunction(
    int nlhs, mxArray *plhs[],
    int nrhs, const mxArray *prhs[]
)
{
    int i, j;
    double *b=NULL, *A=NULL,
            *l=NULL, *u=NULL, *x=NULL, *lambda=NULL ;
    int *iA=NULL, *kA=NULL, nnz=0, neq=0, m=0, n=0, display=0;
    long *lpenv=NULL, *p_lp=NULL;
    char *Sense=NULL ;
    CPXENVptr     env = NULL;
    CPXLPptr      lp = NULL;
    int           status, lpstat;
    double        objval;
#ifndef MX_COMPAT_32
    long *iA_=NULL, *kA_=NULL ;
#endif

    if (nrhs > 6 || nrhs < 1) {
        mexErrMsgTxt("Usage: [how] "
                     "= lp_addrows(env,lp,A,b,neq,disp)");
        return;
    }
    switch (nrhs) {
    case 6:
        if (mxGetM(prhs[5]) != 0 || mxGetN(prhs[5]) != 0) {
            if (!mxIsNumeric(prhs[5]) || mxIsComplex(prhs[5])
                    ||  mxIsSparse(prhs[5])
                    || !(mxGetM(prhs[5])==1 && mxGetN(prhs[5])==1)) {
                mexErrMsgTxt("6th argument (display) must be "
                             "an integer scalar.");
                return;
            }
            display = *mxGetPr(prhs[5]);
        }
    case 5:
        if (mxGetM(prhs[4]) != 0 || mxGetN(prhs[4]) != 0) {
            if (!mxIsNumeric(prhs[4]) || mxIsComplex(prhs[4])
                    ||  mxIsSparse(prhs[4])
                    || !(mxGetM(prhs[4])==1 && mxGetN(prhs[4])==1)) {
                mexErrMsgTxt("5th argument (neq) must be "
                             "an integer scalar.");
                return;
            }
            neq = *mxGetPr(prhs[4]);
        }
    case 4:
        if (mxGetM(prhs[3]) != 0 || mxGetN(prhs[3]) != 0) {
            if (!mxIsNumeric(prhs[3]) || mxIsComplex(prhs[3])
                    ||  mxIsSparse(prhs[3])
                    || !mxIsDouble(prhs[3])
                    ||  mxGetN(prhs[3])!=1 ) {
                mexErrMsgTxt("4rd argument (b) must be "
                             "a column vector.");
                return;
            }
            if (m != 0 && m != mxGetM(prhs[3])) {
                mexErrMsgTxt("Dimension error (arg 4 and later).");
                return;
            }
            b = mxGetPr(prhs[3]);
            m = mxGetM(prhs[3]);
        }
    case 3:
        if (mxGetM(prhs[2]) != 0 || mxGetN(prhs[2]) != 0) {
            if (!mxIsNumeric(prhs[2]) || mxIsComplex(prhs[2])
                    || !mxIsSparse(prhs[2]) ) {
                mexErrMsgTxt("3n argument (A) must be "
                             "a sparse matrix.");
                return;
            }
            if (m != 0 && m != mxGetN(prhs[2])) {
                mexErrMsgTxt("Dimension error (arg 3 and later).");
                return;
            }
            if (n != 0 && n != mxGetM(prhs[2])) {
                mexErrMsgTxt("Dimension error (arg 3 and later).");
                return;
            }
            m = mxGetN(prhs[2]);
            n = mxGetM(prhs[2]);

            A = mxGetPr(prhs[2]);
#ifdef MX_COMPAT_32
            iA = mxGetIr(prhs[2]);
            kA = mxGetJc(prhs[2]);
#else
            iA_ = mxGetIr(prhs[2]);
            kA_ = mxGetJc(prhs[2]);

            iA = myMalloc(mxGetNzmax(prhs[2])*sizeof(int)) ;
            for (i=0; i<mxGetNzmax(prhs[2]); i++)
                iA[i]=iA_[i] ;

            kA = myMalloc((n+1)*sizeof(int)) ;
            for (i=0; i<n+1; i++)
                kA[i]=kA_[i] ;
#endif
            /*{
            int k=0 ;
            mxArray* a = mxCreateDoubleMatrix(1, 1, mxREAL);
            for (; k<28; k++)
              printf("%i,", iA[k]) ;
            printf("\n") ;
            for (k=0; k<28; k++)
              printf("%i,", kA[k]) ;
            printf("\n") ;
            for (k=0; k<28; k++)
              printf("%f,", A[k]) ;
            printf("\n") ;
            }*/
            /*nnz=mxGetNzmax(prhs[2]); */
            nnz=kA[m] ;
            if (display>3)
                fprintf(STD_OUT, "nnz=%i\n", nnz) ;

            Sense=myMalloc((m+1)*sizeof(char)) ;
            for (i=0; i<m; i++)
                if (i<neq) Sense[i]='E' ;
                else Sense[i]='L' ;
            Sense[m]=0 ;
            if (display>3)
                fprintf(STD_OUT, "Sense=%s\n", Sense) ;
        }
    case 2:
        if (mxGetM(prhs[1]) != 0 || mxGetN(prhs[1]) != 0) {
            if (!mxIsNumeric(prhs[1]) || mxIsComplex(prhs[1])
                    ||  mxIsSparse(prhs[1])
                    || !mxIsDouble(prhs[1])
                    ||  mxGetN(prhs[1])!=1 ) {
                mexErrMsgTxt("2nd argument (p_lp) must be "
                             "a column vector.");
                return;
            }
            if (1 != mxGetM(prhs[1])) {
                mexErrMsgTxt("Dimension error (arg 2).");
                return;
            }
            p_lp = (long*) mxGetPr(prhs[1]);
        }
    case 1:
        if (mxGetM(prhs[0]) != 0 || mxGetN(prhs[0]) != 0) {
            if (!mxIsNumeric(prhs[0]) || mxIsComplex(prhs[0])
                    ||  mxIsSparse(prhs[0])
                    || !mxIsDouble(prhs[0])
                    ||  mxGetN(prhs[0])!=1 ) {
                mexErrMsgTxt("1st argument (lpenv) must be "
                             "a column vector.");
                return;
            }
            if (1 != mxGetM(prhs[0])) {
                mexErrMsgTxt("Dimension error (arg 1).");
                return;
            }
            lpenv = (long*) mxGetPr(prhs[0]);
        }
    }

    if (nlhs > 1 || nlhs < 1) {
        mexErrMsgTxt("Usage: [how] "
                     "= lp_gen(lpenv,p_lp,A,b,neq,disp)");
        return;
    }
    if (display>3) fprintf(STD_OUT, "(m=%i, n=%i, neq=%i, nnz=%i) \n", m, n, neq, nnz) ;

    /* Initialize the CPLEX environment */
    env = (CPXENVptr) lpenv[0] ;
    lp=(CPXLPptr)p_lp[0] ;

    if (display>2)
        fprintf(STD_OUT, "calling CPXaddrows \n") ;
    status = CPXaddrows (env, lp, 0, m, nnz, b, Sense, kA, iA, A, NULL, NULL);
    if ( status ) {
        fprintf (STD_OUT,"CPXaddrows failed.\n");
        goto TERMINATE;
    }

TERMINATE:
    if (status) {
        char  errmsg[1024];
        CPXgeterrorstring (env, status, errmsg);
        fprintf (STD_OUT, "%s", errmsg);
        if (nlhs >= 1)
            plhs[0] = mxCreateString(errmsg) ;
    } else if (nlhs >= 1)
        plhs[0] = mxCreateString("OK") ;
    ;
    /*  if (Sense) myFree(Sense) ;*/
#ifndef MX_COMPAT_32
    if (iA) myFree(iA) ;
    if (kA) myFree(kA) ;
#endif

    return ;
}
int
main (void)
{
   int status, solstat;
   CPXENVptr env;
   CPXLPptr lp;
   int i;
   double x[NUMCOLS];
   double cpi[NUMCOLS];
   double rpi[NUMROWS];
   double qpi[NUMQS];
   double slack[NUMROWS], qslack[NUMQS];
   double kktsum[NUMCOLS];

   /* ********************************************************************** *
    *                                                                        *
    *    S E T U P   P R O B L E M                                           *
    *                                                                        *
    * ********************************************************************** */

   /* Create CPLEX environment and enable screen output.
    */
   env = CPXopenCPLEX (&status);
   if ( status != 0 )
      goto TERMINATE;
   status = CPXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status != 0 )
      goto TERMINATE;

   /* Create the problem object and populate it.
    */
   lp = CPXcreateprob (env, &status, "qcpdual");
   if ( status != 0 )
      goto TERMINATE;
   status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, cname);
   if ( status != 0 )
      goto TERMINATE;
   status = CPXaddrows (env, lp, 0, NUMROWS, NUMNZS, rhs, sense,
                        rmatbeg, rmatind, rmatval, NULL, rname);
   if ( status != 0 )
      goto TERMINATE;
   for (i = 0; i < NUMQS; ++i) {
      int const linend = (i == NUMQS - 1) ? NUMLINNZ : linbeg[i + 1];
      int const quadend = (i == NUMQS - 1) ? NUMQUADNZ : quadbeg[i + 1];

      status = CPXaddqconstr (env, lp, linend - linbeg[i],
                              quadend - quadbeg[i], qrhs[i], qsense[i],
                              &linind[linbeg[i]], &linval[linbeg[i]],
                              &quadrow[quadbeg[i]], &quadcol[quadbeg[i]],
                              &quadval[quadbeg[i]], qname[i]);
      if ( status != 0 )
         goto TERMINATE;
   }

   /* ********************************************************************** *
    *                                                                        *
    *    O P T I M I Z E   P R O B L E M                                     *
    *                                                                        *
    * ********************************************************************** */
   status = CPXsetdblparam (env, CPXPARAM_Barrier_QCPConvergeTol, 1e-10);
   if ( status != 0 )
      goto TERMINATE;

   /* Solve the problem.
    */
   status = CPXbaropt (env, lp);
   if ( status != 0 )
      goto TERMINATE;

   solstat = CPXgetstat (env, lp);

   if ( solstat != CPX_STAT_OPTIMAL ) {
      fprintf (stderr, "No optimal solution found!\n");
      goto TERMINATE;
   }

   /* ********************************************************************** *
    *                                                                        *
    *    Q U E R Y   S O L U T I O N                                         *
    *                                                                        *
    * ********************************************************************** */

   /* Optimal solution and slacks for linear and quadratic constraints. */
   status = CPXgetx (env, lp, x, 0, NUMCOLS - 1);
   if ( status != 0 )
      goto TERMINATE;
   status = CPXgetslack (env, lp, slack, 0, NUMROWS - 1);
   if ( status != 0 )
      goto TERMINATE;
   status = CPXgetqconstrslack (env, lp, qslack, 0, NUMQS - 1);
   if ( status != 0 )
      goto TERMINATE;
   /* Dual multipliers for linear constraints and bound constraints. */
   status = CPXgetdj (env, lp, cpi, 0, NUMCOLS - 1);
   if ( status != 0 )
      goto TERMINATE;
   status = CPXgetpi (env, lp, rpi, 0, NUMROWS - 1);
   if ( status != 0 )
      goto TERMINATE;
   status = getqconstrmultipliers (env, lp, x, qpi, ZEROTOL);
   if ( status != 0 )
      goto TERMINATE;

   /* ********************************************************************** *
    *                                                                        *
    *    C H E C K   K K T   C O N D I T I O N S                             *
    *                                                                        *
    *    Here we verify that the optimal solution computed by CPLEX (and     *
    *    the qpi[] values computed above) satisfy the KKT conditions.        *
    *                                                                        *
    * ********************************************************************** */

   /* Primal feasibility: This example is about duals so we skip this test. */

   /* Dual feasibility: We must verify
    * - for <= constraints (linear or quadratic) the dual
    *   multiplier is non-positive.
    * - for >= constraints (linear or quadratic) the dual
    *   multiplier is non-negative.
    */
   for (i = 0; i < NUMROWS; ++i) {
      switch (sense[i]) {
      case 'E': /* nothing */ break;
      case 'R': /* nothing */ break;
      case 'L':
         if ( rpi[i] > ZEROTOL ) {
            fprintf (stderr,
                     "Dual feasibility test failed for <= row %d: %f\n",
                     i, rpi[i]);
            status = -1;
            goto TERMINATE;
         }
         break;
      case 'G':
         if ( rpi[i] < -ZEROTOL ) {
            fprintf (stderr,
                     "Dual feasibility test failed for >= row %d: %f\n",
                     i, rpi[i]);
            status = -1;
            goto TERMINATE;
         }
         break;
      }
   }
   for (i = 0; i < NUMQS; ++i) {
      switch (qsense[i]) {
      case 'E': /* nothing */ break;
      case 'L':
         if ( qpi[i] > ZEROTOL ) {
            fprintf (stderr,
                     "Dual feasibility test failed for <= quad %d: %f\n",
                     i, qpi[i]);
            status = -1;
            goto TERMINATE;
         }
         break;
      case 'G':
         if ( qpi[i] < -ZEROTOL ) {
            fprintf (stderr,
                     "Dual feasibility test failed for >= quad %d: %f\n",
                     i, qpi[i]);
            status = -1;
            goto TERMINATE;
         }
         break;
      }
   }

   /* Complementary slackness.
    * For any constraint the product of primal slack and dual multiplier
    * must be 0.
    */
   for (i = 0; i < NUMROWS; ++i) {
      if ( sense[i] != 'E' && fabs (slack[i] * rpi[i]) > ZEROTOL ) {
         fprintf (stderr,
                  "Complementary slackness test failed for row %d: %f\n",
                  i, fabs (slack[i] * rpi[i]));
         status = -1;
         goto TERMINATE;
      }
   }
   for (i = 0; i < NUMQS; ++i) {
      if ( qsense[i] != 'E' && fabs (qslack[i] * qpi[i]) > ZEROTOL ) {
         fprintf (stderr,
                  "Complementary slackness test failed for quad %d: %f\n",
                  i, fabs (qslack[i] * qpi[i]));
         status = -1;
         goto TERMINATE;
      }
   }
   for (i = 0; i < NUMCOLS; ++i) {
      if ( ub[i] < CPX_INFBOUND ) {
         double const slk = ub[i] - x[i];
         double const dual = cpi[i] < -ZEROTOL ? cpi[i] : 0.0;
         if ( fabs (slk * dual) > ZEROTOL ) {
            fprintf (stderr,
                     "Complementary slackness test failed for ub %d: %f\n",
                     i, fabs (slk * dual));
            status = -1;
            goto TERMINATE;
         }
      }
      if ( lb[i] > -CPX_INFBOUND ) {
         double const slk = x[i] - lb[i];
         double const dual = cpi[i] > ZEROTOL ? cpi[i] : 0.0;
         if ( fabs (slk * dual) > ZEROTOL ) {
            printf ("lb=%f, x=%f, cpi=%f\n", lb[i], x[i], cpi[i]);
            fprintf (stderr,
                     "Complementary slackness test failed for lb %d: %f\n",
                     i, fabs (slk * dual));
            status = -1;
            goto TERMINATE;
         }
      }
   }

   /* Stationarity.
    * The difference between objective function and gradient at optimal
    * solution multiplied by dual multipliers must be 0, i.e., for the
    * optimal solution x
    * 0 == c
    *      - sum(r in rows)  r'(x)*rpi[r]
    *      - sum(q in quads) q'(x)*qpi[q]
    *      - sum(c in cols)  b'(x)*cpi[c]
    * where r' and q' are the derivatives of a row or quadratic constraint,
    * x is the optimal solution and rpi[r] and qpi[q] are the dual
    * multipliers for row r and quadratic constraint q.
    * b' is the derivative of a bound constraint and cpi[c] the dual bound
    * multiplier for column c.
    */

   /* Objective function. */
   for (i = 0; i < NUMCOLS; ++i)
      kktsum[i] = obj[i];

   /* Linear constraints.
    * The derivative of a linear constraint ax - b (<)= 0 is just a.
    */
   for (i = 0; i < NUMROWS; ++i) {
      int const end = (i == NUMROWS - 1) ? NUMNZS : rmatbeg[i + 1];
      int k;

      for (k = rmatbeg[i]; k < end; ++k)
         kktsum[rmatind[k]] -= rpi[i] * rmatval[k];
   }

   /* Quadratic constraints.
    * The derivative of a constraint xQx + ax - b <= 0 is
    * Qx + Q'x + a.
    */
   for (i = 0; i < NUMQS; ++i) {
      int j;
      int k;

      for (j = linbeg[i]; j < linbeg[i] + linnzcnt[i]; ++j)
         kktsum[linind[j]] -= qpi[i] * linval[j];
      for (k = quadbeg[i]; k < quadbeg[i] + quadnzcnt[i]; ++k) {
         kktsum[quadrow[k]] -= qpi[i] * x[quadcol[k]] * quadval[k];
         kktsum[quadcol[k]] -= qpi[i] * x[quadrow[k]] * quadval[k];
      }
   }

   /* Bounds.
    * The derivative for lower bounds is -1 and that for upper bounds
    * is 1.
    * CPLEX already returns dj with the appropriate sign so there is
    * no need to distinguish between different bound types here.
    */
   for (i = 0; i < NUMCOLS; ++i) {
      kktsum[i] -= cpi[i];
   }

   for (i = 0; i < NUMCOLS; ++i) {
      if ( fabs (kktsum[i]) > ZEROTOL ) {
         fprintf (stderr, "Stationarity test failed at index %d: %f\n",
                  i, kktsum[i]);
         status = -1;
         goto TERMINATE;
      }
   }

   /* KKT conditions satisfied. Dump out the optimal solutions and
    * the dual values.
    */

   printf ("Optimal solution satisfies KKT conditions.\n");
   printf ("  x[] =");
   for (i = 0; i < NUMCOLS; ++i)
      printf (" %7.3f", x[i]);
   printf ("\n");
   printf ("cpi[] =");
   for (i = 0; i < NUMCOLS; ++i)
      printf (" %7.3f", cpi[i]);
   printf ("\n");
   printf ("rpi[] =");
   for (i = 0; i < NUMROWS; ++i)
      printf (" %7.3f", rpi[i]);
   printf ("\n");
   printf ("qpi[] =");
   for (i = 0; i < NUMQS; ++i)
      printf (" %7.3f", qpi[i]);
   printf ("\n");
   
 TERMINATE:
   /* ********************************************************************** *
    *                                                                        *
    *    C L E A N U P                                                       *
    *                                                                        *
    * ********************************************************************** */

   status = CPXfreeprob (env, &lp);
   if ( status != 0 ) {
      fprintf (stderr, "WARNING: Failed to free problem: %d\n", status);
   }
   status = CPXcloseCPLEX (&env);
   if ( status != 0 ) {
      fprintf (stderr, "WARNING: Failed to close CPLEX: %d\n", status);
   }

   return status;
}
예제 #20
0
SSCplex::SSCplex( string InstanceFile )
{
 num_vm = 0; // number of virtual machines
 num_vf = 0; // number of virtual function
 int offset;
 
 ifstream in;
 in.open(InstanceFile.c_str());
 if( !in.is_open() )
 {
  cout<<"Cannot open instance file.\n";
  exit(1);
 }
	
 //leggo da file il numero di macchine e di funzioni virtuali
 in >> num_vm;
 in >> num_vf;

 cout << "Num VM " << num_vm << " Num VF " << num_vf << endl;

 lev_card = num_vm; // the number of nodes in each level
 h_len = num_vf;

 int lev_card_arcs = lev_card*lev_card;

 //number of nodes and arcs 
 NNodes = lev_card * h_len + 2;
 NArcs = lev_card * lev_card * (h_len-1) + 2*lev_card;
 
 // array used to store the solution
 Y = array(NArcs);

 tempi_lat = new double *[num_vm];

 for (int i=0; i<num_vm; i++)
   tempi_lat[i] = new double[num_vm];

 cap = new int[ num_vm ];
 
 // fill the distance matrix 
 for (int i=0; i<num_vm; i++)
  for (int j=0; j<num_vm; j++)
    //   if( j >= i )
    in >> tempi_lat[i][j];
 //   else  (in input is supposed to be symmetric)
 //    tempi_lat[i][j] = tempi_lat[j][i];

 // fill the capacity array
 for (int i=0; i<num_vm; i++)
  in >> cap[ i ];

 incom = new int *[num_vf];
 for (int i=0; i<num_vf; i++)
  incom[i] = new int[num_vm+1];

 proc_time = new double *[num_vf];
 for (int i=0; i<num_vf; i++)
  proc_time[i] = new double[num_vm];

 for( int i = 0; i < num_vf; i++ )
 {
   string dummy;
   int cnt;
   in >> dummy >> incom[i][0];
   cnt = incom[i][0];
   for( int j = 1; j <= cnt; j++ )
     in >> incom[i][j];

   for( int j = 0; j < num_vm; j++ )
     in >> proc_time[i][j];
 }

 source_dist = new double[ num_vm ];
 dest_dist = new double[ num_vm ];

 for( int j = 0; j < num_vm; j++ )
   in >> source_dist[j];
 for( int j = 0; j < num_vm; j++ )
   in >> dest_dist[j];


 in.close();

 /* Initialize the CPLEX environment */
 env = CPXopenCPLEX (&status);
 if ( env == NULL ) {
   stop("Could not open CPLEX environment.\n", status);
 }

 /* Create the problem */
 lp = CPXcreateprob( env , &status , "HCP" );
 if ( lp == NULL ) {
   stop("Failed to create LP.\n", status);
 }
 if( DEBUG ) {
   CPXout.open("DEBUG.txt", ios::out); 	
 }

 // Turn on debugging routines
 status = CPXsetintparam (env, CPX_PARAM_DATACHECK, CPX_ON);
 if ( status ) {
    stop("Failure to turn on debugging, error %d.\n", status);
 }
  
 // Turn on output to the screen     
 status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
 if ( status ) {
   stop("Failure to turn on screen indicator, error %d.\n", status);
 }

  double  *obj = NULL;
  double  *ub = NULL;
  double  *lb = NULL;
  char	*ctype = NULL;
	
  int nzcnt;
  double *rhs = NULL;
  char *sense = NULL;
  int *matbeg;
  int *matind;
  double *matval;

  // variable counters
  int y_var = NArcs; // flow variables

  // creating variables
  ub = array(y_var);
  lb = array(y_var);

  for( int k = 0; k < y_var; k++ ){
    lb[k] = 0.0;
    ub[ k ] = 1.0;
  }
#if( MIP )
  ctype = arraychar(y_var);	
  for( int h = 0; h < y_var; h++)
    ctype[h] = 'B';
#endif

  obj = array(NArcs);
  for(int i = 0; i < lev_card; i++ )
    obj[i] = proc_time[0][i] + source_dist[i];

  offset = lev_card * lev_card * (h_len-1) + lev_card;
  for(int i = 0; i < lev_card; i++ )
    obj[offset+i] = dest_dist[i];

  offset = lev_card;
  for( int h = 0; h < h_len - 1; h++ )
   for( int i = 0; i < lev_card; i++ )
    for( int j = 0; j < lev_card; j++ )
    {
     int k = offset + h * (lev_card * lev_card) + i * lev_card + j;
     obj[k] = tempi_lat[i][j] + proc_time[h+1][j];
    }

  status = CPXnewcols(env, lp, y_var, obj, lb, ub, ctype, NULL);
  if ( status )
    stop("Failure to create y cols.", status);

  nzcnt = NArcs;
  matind = arrayint(nzcnt);
  matval = array(nzcnt);
  matbeg = arrayint(2);
  
  rhs = array(1);       // at most one constraint is loaded 
  sense = arraychar(1); // in one shot

  matbeg[0] = 0;
  
  // flow conservation constraint relative to source node
  rhs[0] = 1.0;
  sense[0] = 'E';

  for( int h = 0; h < lev_card; h++ )
  {
   matind[h] = h;
   matval[h] = 1.0;
  }

  matbeg[1] = lev_card;
  status = CPXaddrows(env, lp, 0, 1, lev_card, rhs, sense, 
		      matbeg, matind, matval, NULL, NULL);

  if ( status ) {
    stop("Failed to insert cons.\n", status);	
  }

  offset = lev_card + (h_len - 1) * (lev_card * lev_card);
    // flow conservation constraint relative to destination node
  for( int h = 0; h < lev_card; h++ )
  {
   matind[h] = offset + h;
   matval[h] = 1.0;
  }

  matbeg[1] = lev_card;
  status = CPXaddrows(env, lp, 0, 1, lev_card, rhs, sense, 
		      matbeg, matind, matval, NULL, NULL);
  if ( status ) {
    stop("Failed to insert cons.\n", status);	
  }
  
  // flow conservation constraints relative to intermediate nodes
  rhs[0] = 0.0;
  for( int h = 0; h < h_len; h++ )
  {
   for( int i = 0; i < lev_card; i++ )
   {
    int k = 0; // insert a constraint for each intermediate node
    // incoming flow
    if( h == 0 )
    {
     matind[k] = i;
     matval[k] = -1.0;
     k++;
    }
    else
    {
     offset = lev_card + lev_card*lev_card*(h-1);
     for( int j = 0; j < lev_card; j++ )
     {
      matind[k] = offset + j * lev_card + i;
      matval[k] = -1.0;
      k++;
     } 
    }
    // outcoming flow
    if( h == h_len - 1)
    {
     offset = lev_card + lev_card*lev_card*h;
     matind[k] = offset +  i;
     matval[k] = 1.0;
     k++;
    }
    else
    {
     offset = lev_card + lev_card*lev_card*h;
     for( int j = 0; j < lev_card; j++ )
     {
      matind[k] = offset + i*lev_card + j;
      matval[k] = 1.0;
      k++;
     } 

    }
    
    matbeg[1] = k;
    assert( k <= nzcnt );
    status = CPXaddrows(env, lp, 0, 1, k, rhs, sense, 
			matbeg, matind, matval, NULL, NULL);
    if ( status ) {
      stop("Failed to insert cons.\n", status);	
    }
   }
  }

  // VM capacity constraints 
  sense[0] = 'L';
  for( int i = 0; i < lev_card; i++ )
  {
   int k = 0; // insert a constraint for each VM
   rhs[0] = cap[i];

   for( int h = 0; h < h_len - 1; h++ )
   {
    offset = lev_card + lev_card*lev_card*h;
    for( int j = 0; j < lev_card; j++ )
    {
     matind[k] = offset + i*lev_card + j;
     matval[k] = 1.0;
     k++;
    }
   }
   offset = lev_card + lev_card*lev_card*(h_len-1);
   matind[k] = offset +  i;
   matval[k] = 1.0;
   k++;

   matbeg[1] = k;
   assert( k <= nzcnt );
   status = CPXaddrows(env, lp, 0, 1, k, rhs, sense, 
		       matbeg, matind, matval, NULL, NULL);
   if ( status ) {
     stop("Failed to insert cons.\n", status);	
   }
  }

  // incompatibilities management
  // vf_0
  int cnt = incom[0][0];
  for( int j = 0; j < cnt; j++ )
  {
   int arc_index = incom[0][j+1];
   ChgBds(arc_index, 0.0);
  }
  // other vf_h
  for( int h = 1; h < num_vf; h++ )
  {
   int cnt = incom[h][0];
   int offset = lev_card + (h-1) * (lev_card*lev_card);
   for( int j = 0; j < cnt; j++ )
    for( int i = 0; i < lev_card; i++ )
    {
     int arc_index = offset + i * lev_card + incom[h][j+1];
     ChgBds(arc_index, 0.0);
    }
  }

#if DEBUG
	status = CPXwriteprob(env, lp, "SS.lp", "LP");
	if ( status ) stop("Failed to write LP to disk.", status);
#endif

/* Set limit to emphasize feasibility */    
 status = CPXsetintparam (env, CPX_PARAM_MIPEMPHASIS, MIPEMPH);
 if ( status ) 
   stop("Failure to set parameter emphasizing feasibility.\n", status);


// Turn on output to the screen     
 status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
 if ( status ) {
   stop("Failure to turn on screen indicator, error %d.\n", status);
 }

 status = CPXsetdblparam (env, CPX_PARAM_TILIM, TIMELIMIT);

 free_arraychar(sense);
 free_array(rhs);
 free_arrayint(matbeg);
 free_array(matval);
 free_arrayint(matind);
 free_array(obj);
#if( MIP )
 free_arraychar(ctype);
#endif
 free_array(lb);
 free_array(ub);
} //END SSCplex
예제 #21
0
void IPBuild()
{
 int status;
 char *pVarType;
 double *pdLB, *pdUB, *pdObj, *pdrhs, *pdVal;
 unsigned int NbPyr=PYRGetNumbers(),TotJob=0, *puiBeg, *puiInd,uiJob,NbJobBefore;
 unsigned int uiLoop,uiLoop2,uiLoop3,uiIndice;

 // Initialize and configure the IP environment
 IPInitialize();

 // We now create the model
 //strcpy (probname, "1riLmax");
 lp = CPXcreateprob (env, &status, "");
 if ( lp == NULL ) {
      printf ("Failed to create LP.\n");
	  getch();
	  exit(-1);
 }
 // We create the variables
 printf("\t Variable creation\n");
 pVarName=(char **)malloc(sizeof(char *)*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr)));
 for (uiLoop=0;uiLoop<(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr));uiLoop++)
	 pVarName[uiLoop]=(char *)malloc(sizeof(char)*700);
 pVarType=(char *)malloc(sizeof(char )*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr)));
 pdLB=(double *)malloc(sizeof(double)*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr)));
 pdUB=(double *)malloc(sizeof(double)*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr)));
 pdObj=(double *)malloc(sizeof(double)*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr)));
 strcpy(pVarName[0],"Lmax");
 pVarType[0]='C';
 pdLB[0]=-INFTY;
 pdUB[0]=INFTY;
 pdObj[0]=1;
 for (uiLoop=0;uiLoop<NbPyr;uiLoop++)
 {
	 char cBuf[10000];
	 strcpy(pVarName[1+2*uiLoop],"R");
	 sprintf(cBuf,"%d",uiLoop);
	 strcat(pVarName[1+2*uiLoop],cBuf);
	 pVarType[1+2*uiLoop]='C';
	 pdLB[1+2*uiLoop]=(double)ri(PYRGetTopJob(uiLoop));
	 pdUB[1+2*uiLoop]=INFTY;
	 pdObj[1+2*uiLoop]=0;
	 strcpy(pVarName[1+2*uiLoop+1],"D");
	 sprintf(cBuf,"%d",uiLoop);
	 strcat(pVarName[1+2*uiLoop+1],cBuf);
	 pVarType[1+2*uiLoop+1]='C';
	 pdLB[1+2*uiLoop+1]=-INFTY;
	 pdUB[1+2*uiLoop+1]=(double)di(PYRGetTopJob(uiLoop));
	 pdObj[1+2*uiLoop+1]=0;
 }
 TotJob=0;
 for (uiLoop=0;uiLoop<NbPyr;uiLoop++)
 {
	 for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop);uiLoop2++)
     {
	    char cBuf[10000];
	    strcpy(pVarName[1+2*NbPyr+TotJob+2*uiLoop2],"xm");
	    sprintf(cBuf,"%d,%d",uiLoop,PYRGetJobsInPyr(uiLoop,uiLoop2));
	    strcat(pVarName[1+2*NbPyr+TotJob+2*uiLoop2],cBuf);
		//printf("%s \n",pVarName[1+2*NbPyr+TotJob+2*uiLoop2]);
		pVarType[1+2*NbPyr+TotJob+2*uiLoop2]='B';
		pdLB[1+2*NbPyr+TotJob+2*uiLoop2]=-INFTY;
	    pdUB[1+2*NbPyr+TotJob+2*uiLoop2]=INFTY;
	    pdObj[1+2*NbPyr+TotJob+2*uiLoop2]=0;
	    strcpy(pVarName[1+2*NbPyr+TotJob+2*uiLoop2+1],"xp");
		sprintf(cBuf,"%d,%d",uiLoop,PYRGetJobsInPyr(uiLoop,uiLoop2));
	    strcat(pVarName[1+2*NbPyr+TotJob+2*uiLoop2+1],cBuf);
		//printf("%s \n",pVarName[1+2*NbPyr+TotJob+2*uiLoop2+1]);
		pVarType[1+2*NbPyr+TotJob+2*uiLoop2+1]='B';
		pdLB[1+2*NbPyr+TotJob+2*uiLoop2+1]=-INFTY;
	    pdUB[1+2*NbPyr+TotJob+2*uiLoop2+1]=INFTY;
	    pdObj[1+2*NbPyr+TotJob+2*uiLoop2+1]=0;
     }
     TotJob+=2*PYRGetNumberJobs(uiLoop);
 }
 
 uiNbVar=1+2*NbPyr+TotJob;

 status = CPXnewcols (env, lp, uiNbVar, pdObj, pdLB, pdUB, pVarType, pVarName);

 // We now create constraints
 // First: Lmax>=Rk+ptk-Dk, forall k=1..NbPyr
 printf("\t Creating constraints 1\n");
 pdrhs=(double *)malloc(sizeof(double)*1);
 puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1);
 puiBeg[0]=0;
 puiInd=(unsigned int *)malloc(sizeof(unsigned int)*3);
 pdVal=(double *)malloc(sizeof(double)*3);
 for (uiLoop=0;uiLoop<NbPyr;uiLoop++)
 {
   puiInd[0]=0;
   pdVal[0]=-1.0;
   puiInd[1]=1+2*uiLoop;
   pdVal[1]=1.0;
   puiInd[2]=1+2*uiLoop+1;
   pdVal[2]=-1.0;
   pdrhs[0]=-1.0*(double)pi(PYRGetTopJob(uiLoop));
   status = CPXaddrows (env, lp, 0, 1, 3, pdrhs, "L", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL);
 }
 free(pdrhs);
 free(puiBeg);
 free(puiInd);
 free(pdVal);
 // Second: Rk>=ri+sum pjxpkj, forall i|k=U(i)
 printf("\t Creating constraints 2\n");
 pdrhs=(double *)malloc(sizeof(double)*1);
 puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1);
 puiBeg[0]=0;
 NbJobBefore=0;
 for(uiLoop=0;uiLoop<NbPyr;uiLoop++)
 {
  puiInd=(unsigned int *)malloc(sizeof(unsigned int)*(1+PYRGetNumberJobs(uiLoop)));
  pdVal=(double *)malloc(sizeof(double)*(1+PYRGetNumberJobs(uiLoop)));
  for (uiLoop2=0;uiLoop2<NbJobs;uiLoop2++)
	  if (U[uiLoop2]==(signed int)uiLoop)
	  { // We add the constraint
		  puiInd[0]=1+2*uiLoop;
		  pdVal[0]=-1.0;
		  pdrhs[0]=-1.0*(double)ri(uiLoop2);
		  TotJob=0;
		  for (uiLoop3=0;uiLoop3<PYRGetNumberJobs(uiLoop);uiLoop3++)
		  {
			  uiJob=PYRGetJobsInPyr(uiLoop,uiLoop3);
			  if ((ri(uiJob)>ri(uiLoop2))||(ri(uiJob)==ri(uiLoop2) && di(uiJob)>di(uiLoop2))||(ri(uiJob)==ri(uiLoop2) && di(uiJob)==di(uiLoop2) && uiLoop2<=uiJob))
			  {
				  TotJob++;
				  puiInd[TotJob]=1+2*NbPyr+2*NbJobBefore+2*uiLoop3+1;
				  pdVal[TotJob]=(double)pi(uiJob);
			  }
		  }
          status = CPXaddrows (env, lp, 0, 1, 1+TotJob, pdrhs, "L", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL);
	  }

  NbJobBefore+=PYRGetNumberJobs(uiLoop);
  free(pdVal);
  free(puiInd);
 }
 free(pdrhs);
 free(puiBeg);
  // Third: Dk<=di-sum pjxmkj, forall i|k=V(i)
 printf("\t Creating constraints 3\n");
 pdrhs=(double *)malloc(sizeof(double)*1);
 puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1);
 puiBeg[0]=0;
 NbJobBefore=0;
 for(uiLoop=0;uiLoop<NbPyr;uiLoop++)
 {
  puiInd=(unsigned int *)malloc(sizeof(unsigned int)*(1+PYRGetNumberJobs(uiLoop)));
  pdVal=(double *)malloc(sizeof(double)*(1+PYRGetNumberJobs(uiLoop)));
  for (uiLoop2=0;uiLoop2<NbJobs;uiLoop2++)
	  if (V[uiLoop2]==(signed int) uiLoop)
	  { // We add the constraint
		  puiInd[0]=1+2*uiLoop+1;
		  pdVal[0]=1.0;
		  pdrhs[0]=(double)di(uiLoop2);
		  TotJob=0;
		  for (uiLoop3=0;uiLoop3<PYRGetNumberJobs(uiLoop);uiLoop3++)
		  {
			  uiJob=PYRGetJobsInPyr(uiLoop,uiLoop3);
			  if ((di(uiJob)<di(uiLoop2))||(di(uiJob)==di(uiLoop2) && ri(uiJob)<ri(uiLoop2))||(ri(uiJob)==ri(uiLoop2) && di(uiJob)==di(uiLoop2) && uiLoop2>=uiJob))
			  {
				  TotJob++;
				  puiInd[TotJob]=1+2*NbPyr+2*NbJobBefore+2*uiLoop3;
				  pdVal[TotJob]=(double)pi(uiJob);
			  }
		  }
          status = CPXaddrows (env, lp, 0, 1, 1+TotJob, pdrhs, "L", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL);
	  }

  NbJobBefore+=PYRGetNumberJobs(uiLoop);
  free(pdVal);
  free(puiInd);
 }
 free(pdrhs);
 free(puiBeg);
 // Fourth: sum xpkj+xmkj=1, forall i
 printf("\t Creating constraints 4\n");
 pdrhs=(double *)malloc(sizeof(double)*1);
 pdrhs[0]=1;
 puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1);
 puiBeg[0]=0;
 for(uiLoop=0;uiLoop<NbJobs;uiLoop++)
 if (U[uiLoop]!=-1)
 {
  puiInd=(unsigned int *)malloc(sizeof(unsigned int)*2*(V[uiLoop]-U[uiLoop]+1));
  pdVal=(double *)malloc(sizeof(double)*2*(V[uiLoop]-U[uiLoop]+1));
  NbJobBefore=0;
  for (uiLoop2=0;uiLoop2<U[uiLoop];uiLoop2++)
	  NbJobBefore+=PYRGetNumberJobs(uiLoop2);
  uiIndice=0;
  for (uiLoop2=U[uiLoop];uiLoop2<=V[uiLoop];uiLoop2++)
  {
	  puiInd[uiIndice]=1+2*PYRGetNumbers()+2*NbJobBefore+PYRGetJobPos(uiLoop2,uiLoop)*2;
	  pdVal[uiIndice]=1.0;
	  uiIndice++;
	  puiInd[uiIndice]=1+2*PYRGetNumbers()+2*NbJobBefore+PYRGetJobPos(uiLoop2,uiLoop)*2+1;
	  pdVal[uiIndice]=1.0;
	  uiIndice++;
	  NbJobBefore+=PYRGetNumberJobs(uiLoop2);
  }
  status = CPXaddrows (env, lp, 0, 1, 2*(V[uiLoop]-U[uiLoop]+1), pdrhs, "E", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL);
  free(puiInd);
  free(pdVal);
 }
 free(puiBeg);
 free(pdrhs);
 
 // Fifth: Rk>=Rk-1 + sum pjxm(k-1)j + ptk-1 + sum pjxpkj, forall k=2...NbPyr
 printf("\t Creating constraints 5\n");
 pdrhs=(double *)malloc(sizeof(double)*1);
 puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1);
 puiBeg[0]=0;
 NbJobBefore=0;
 for(uiLoop=1;uiLoop<NbPyr;uiLoop++)
 {
  puiInd=(unsigned int *)malloc(sizeof(unsigned int)*(2+PYRGetNumberJobs(uiLoop-1)+PYRGetNumberJobs(uiLoop)));
  pdVal=(double *)malloc(sizeof(double)*(2+PYRGetNumberJobs(uiLoop-1)+PYRGetNumberJobs(uiLoop)));
  pdrhs[0]=-1.0*(double)pi(PYRGetTopJob(uiLoop-1));
  puiInd[0]=1+2*(uiLoop-1);
  pdVal[0]=1.0;
  puiInd[1]=1+2*uiLoop;
  pdVal[1]=-1.0;
  for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop-1);uiLoop2++)
	  { 
		  puiInd[2+uiLoop2]=1+2*NbPyr+2*NbJobBefore+2*uiLoop2;
		  pdVal[2+uiLoop2]=(double)pi(PYRGetJobsInPyr(uiLoop-1,uiLoop2));
	  }
  NbJobBefore+=PYRGetNumberJobs(uiLoop-1);
  for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop);uiLoop2++)
	  { 
		  puiInd[2+PYRGetNumberJobs(uiLoop-1)+uiLoop2]=1+2*NbPyr+2*NbJobBefore+2*uiLoop2+1;
		  pdVal[2+PYRGetNumberJobs(uiLoop-1)+uiLoop2]=(double)pi(PYRGetJobsInPyr(uiLoop,uiLoop2));
	  }
  status = CPXaddrows (env, lp, 0, 1, 2+PYRGetNumberJobs(uiLoop)+PYRGetNumberJobs(uiLoop-1), pdrhs, "L", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL);
  free(pdVal);
  free(puiInd);
 }
 free(pdrhs);
 free(puiBeg);
 // Sixth: Dk<=Dk+1 - sum pjxp(k+1)j - ptk+1 - sum pjxmkj, forall k=1...NbPyr-1
 printf("\t Creating constraints 6\n");
 pdrhs=(double *)malloc(sizeof(double)*1);
 puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1);
 puiBeg[0]=0;
 NbJobBefore=0;
 for(uiLoop=0;uiLoop<NbPyr-1;uiLoop++)
 {
  puiInd=(unsigned int *)malloc(sizeof(unsigned int)*(2+PYRGetNumberJobs(uiLoop)+PYRGetNumberJobs(uiLoop+1)));
  pdVal=(double *)malloc(sizeof(double)*(2+PYRGetNumberJobs(uiLoop)+PYRGetNumberJobs(uiLoop+1)));
  pdrhs[0]=(double)pi(PYRGetTopJob(uiLoop+1));
  puiInd[0]=1+2*(uiLoop+1)+1;
  pdVal[0]=1.0;
  puiInd[1]=1+2*uiLoop+1;
  pdVal[1]=-1.0;
  for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop);uiLoop2++)
	  { 
		  puiInd[2+uiLoop2]=1+2*NbPyr+2*NbJobBefore+2*uiLoop2;
		  pdVal[2+uiLoop2]=-1.0*(double)pi(PYRGetJobsInPyr(uiLoop,uiLoop2));
	  }
  NbJobBefore+=PYRGetNumberJobs(uiLoop);
  for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop+1);uiLoop2++)
	  { 
		  puiInd[2+PYRGetNumberJobs(uiLoop)+uiLoop2]=1+2*NbPyr+2*NbJobBefore+2*uiLoop2+1;
		  pdVal[2+PYRGetNumberJobs(uiLoop)+uiLoop2]=-1.0*(double)pi(PYRGetJobsInPyr(uiLoop+1,uiLoop2));
	  }
  status = CPXaddrows (env, lp, 0, 1, 2+PYRGetNumberJobs(uiLoop)+PYRGetNumberJobs(uiLoop+1), pdrhs, "G", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL);
  free(pdVal);
  free(puiInd);
 }
 free(pdrhs);
 free(puiBeg);
}
예제 #22
0
// solve the current problem
int cplex_solver::solve() {
	int nb_objectives = objectives.size();
	int mipstat, status;

	// Presolving the problem
	time_t ptime = time(NULL);
	if (CPXpresolve(env, lp, CPX_ALG_NONE)) return 0;
	time_t ctime = time(NULL);
	_timeCount += difftime(ctime, ptime);
	// Solve the objectives in a lexical order
	for (int i = first_objective; i < nb_objectives; i++) {
		ptime = ctime;
		// Solve the mip problem
		if (CPXmipopt (env, lp)) return ERROR;
		ctime = time(NULL);
		_solutionCount += CPXgetsolnpoolnumsolns(env, lp) + CPXgetsolnpoolnumreplaced(env, lp);
		_timeCount += difftime(ctime, ptime);
		_nodeCount += CPXgetnodecnt(env, lp);
		// Get solution status
		if ((mipstat = CPXgetstat(env, lp)) == CPXMIP_OPTIMAL) {
			if (i < nb_objectives - 1) {
				// Get next non empty objective
				// (must be done here to avoid conflicting method calls
				int previ = i, nexti, nexti_nb_coeffs = 0;

				for (; i < nb_objectives - 1; i++) {
					nexti = i + 1;
					nexti_nb_coeffs = objectives[nexti]->nb_coeffs;
					if (nexti_nb_coeffs > 0) break;
				}

				if (nexti_nb_coeffs > 0) { // there is one more objective to solve
					// Set objective constraint value to objval
					int index[1];
					double values[1];

					index[0] = previ;
					values[0] = objective_value();

					if (verbosity >= DEFAULT)
						printf(">>>> Objective value %d = %f\n", previ, values[0]);
					{
						int status, begin[2];
						double rhs[1];

						begin[0] = 0;
						rhs[0] = values[0]; //ub;
						int n = objectives[previ]->nb_coeffs;
						begin[1] = n - 1;
						status = CPXaddrows(env, lp, 0, 1, n, rhs, "E", begin, objectives[previ]->sindex, objectives[previ]->coefficients, NULL, NULL);
						if (status) {
							fprintf(stderr, "cplex_solver: end_objective: cannot add %d objective as constraint.\n", i);
							exit(-1);
						}
					}

					// Set the new objective value
					reset_coeffs();

					// Set previous objective coefficients to zero
					for (int k = 0; k < objectives[previ]->nb_coeffs; k++) set_coeff(objectives[previ]->sindex[k], 0);

					// Set next objective coefficients to their actual values
					for (int k = 0; k < nexti_nb_coeffs; k++) set_coeff(objectives[nexti]->sindex[k], objectives[nexti]->coefficients[k]);
					// Do set the next objective
					status = CPXchgobj(env, lp, nb_coeffs, sindex, coefficients);
					if ( status ) {
						fprintf (stderr,"Cannot change objective value.  Exiting...\n");
						exit(-1);
					}

					// Output model to file (when requested)
					if (verbosity >= VERBOSE) {
						char buffer[1024];
						sprintf(buffer, "cplexpb-%d.lp", i);
						writelp(buffer);
					}
				} else
					return OPTIMUM;
			} else
				return OPTIMUM;
		} else if( mipstat == CPXMIP_TIME_LIM_INFEAS ||
				mipstat == CPXMIP_TIME_LIM_FEAS) {
				return _solutionCount > 0 ? SAT : UNKNOWN;
		} else {
			if (verbosity >= DEFAULT)
				fprintf(stderr, "CPLEX solution status = %d\n", mipstat);
			return ERROR;
		}
	}

	return 0;
}
예제 #23
0
파일: main.cpp 프로젝트: germanromano/invop
int main(int argc, char *argv[]) {
	
	if(argc < 3){
		cerr << "Uso: input_file max_iteraciones" << endl;
		exit(1);
	}
	
	srand(time(NULL));
	string archivo_entrada(argv[1]);
	int max_iteraciones = atoi(argv[2]);

//----------------------- PARSEO DE ENTRADA	
	pair <int, pair<vector<vector<bool> >*, vector<vector<bool> >* > > grafo = parsear_entrada(archivo_entrada);
	int cant_ejes = grafo.first;
	vector<vector<bool> > *adyacencias = grafo.second.first; // matriz de adyacencia
	vector<vector<bool> > *particion = grafo.second.second;	// filas: subconjuntos de la particion. columnas: nodos.
	
	// Variables binarias:
	//		* X_n_j = nodo n pintado con el color j? (son cant_nodos * cant_colores_disp variables)
	//		* W_j	= hay algun nodo pintado con el color j? (son cant_colores_disp variables)
	//			=> TOTAL: (cant_nodos * cant_colores_disp + cant_colores_disp) variables
	//
	// Orden de las variables:
	//		X_0_0, X_0_1, ... , X_0_(cant_col_disp), X_1_0, ... , X_(cant_nodos)_(cant_col_disp), W_0, ... , W(cant_col_disp)

	int cant_nodos = adyacencias->size();
	int cant_subconj_particion = particion->size(); //cant de subconjuntos de la particion
	int cant_colores_disp = particion->size(); // cant colores usados <= cant de subconjuntos de la particion
	
	int n = cant_nodos * cant_colores_disp + cant_colores_disp; // n = cant de variables

//----------------------- CARGA DE LP
	// Genero el problema de cplex.
	int status;
	CPXENVptr env; // Puntero al entorno.
	CPXLPptr lp; // Puntero al LP
	 
	// Creo el entorno.
	env = CPXopenCPLEX(&status);
		
	if (env == NULL) {
		cerr << "Error creando el entorno" << endl;
		exit(1);
	}
		
	// Creo el LP.
	lp = CPXcreateprob(env, &status, "Coloreo Particionado");

		
	if (lp == NULL) {
		cerr << "Error creando el LP" << endl;
		exit(1);
	}
	
	//TUNNING
	//Para que haga Branch & Cut:
	CPXsetintparam(env, CPX_PARAM_MIPSEARCH, CPX_MIPSEARCH_TRADITIONAL);
	//Para que no se adicionen planos de corte: ( => Branch & Bound)
	CPXsetintparam(env,CPX_PARAM_EACHCUTLIM, 0);
	CPXsetintparam(env, CPX_PARAM_FRACCUTS, -1);
	//Para facilitar la comparación evitamos paralelismo:
	CPXsetintparam(env, CPX_PARAM_THREADS, 1);
	//Para desactivar preprocesamiento
	CPXsetintparam(env, CPX_PARAM_PRESLVND, -1);
	CPXsetintparam(env, CPX_PARAM_REPEATPRESOLVE, 0);
	CPXsetintparam(env, CPX_PARAM_RELAXPREIND, 0);
	CPXsetintparam(env, CPX_PARAM_REDUCE, 0);
	CPXsetintparam(env, CPX_PARAM_LANDPCUTS, -1);
	//Otros parámetros
	// Para desactivar la salida poner CPX_OFF. Para activar: CPX_ON.
	status = CPXsetintparam(env, CPX_PARAM_SCRIND, CPX_OFF);
		if (status) {
			cerr << "Problema seteando SCRIND" << endl;
			exit(1);
		}
	//Setea el tiempo limite de ejecucion.
	status = CPXsetdblparam(env, CPX_PARAM_TILIM, 3600);
		if (status) {
			cerr << "Problema seteando el tiempo limite" << endl;
			exit(1);
		}

	double *ub, *lb, *objfun; // Cota superior, cota inferior, coeficiente de la funcion objetivo.
	char *xctype, **colnames; // tipo de la variable (por ahora son siempre continuas), string con el nombre de la variable.
	ub = new double[n]; 
	lb = new double[n];
	objfun = new double[n];
	xctype = new char[n];
	colnames = new char*[n];
	
	// Defino las variables X_n_j
	for (int i = 0; i < n - cant_colores_disp; i++) {
		ub[i] = 1;
		lb[i] = 0;
		objfun[i] = 0; // Estas var no figuran en la funcion objetivo
		xctype[i] = 'C';
		colnames[i] = new char[10];
		sprintf(colnames[i], "X_%d_%d", i / cant_colores_disp, i % cant_colores_disp);
	}

	// Defino las variables W_j
	for (int i = n - cant_colores_disp; i < n; i++) {
		ub[i] = 1;
		lb[i] = 0;
		objfun[i] = 1;
		xctype[i] = 'C';
		colnames[i] = new char[10];
		sprintf(colnames[i], "W_%d", i - (n - cant_colores_disp));
	}
	
	// Agrego las columnas.
	status = CPXnewcols(env, lp, n, objfun, lb, ub, NULL, colnames);
	
	if (status) {
		cerr << "Problema agregando las variables CPXnewcols" << endl;
		exit(1);
	}
	
	// Libero las estructuras.
	for (int i = 0; i < n; i++) {
		delete[] colnames[i];
	}
	
	delete[] ub;
	delete[] lb;
	delete[] objfun;
	delete[] xctype;
	delete[] colnames;

	// Restricciones:
	//	(1) Nodos adyacentes tienen distinto color (cant_ejes * cant_colores_disp restricciones por <=)
	//	(2) Cada nodo tiene a lo sumo un color (cant_nodos restricciones por <=)
	//	(3) Solo un nodo de cada subconj. de la particion tiene color (cant. de subconj. de la particion restricciones por =)
	//	(4) W_j = 1 sii "X_i_j = 1 para algún i" (cant_colores_disp restricciones por >=)
	//	(5) W_j >= W_(j+1) (cant_colores_disp - 1 restricciones por >=)
	//		=> TOTAL: (cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion + cant_colores_disp + cant_colores_disp - 1) restricciones

	int ccnt = 0; //numero nuevo de columnas en las restricciones.
	int rcnt = cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion + cant_colores_disp + cant_colores_disp - 1; //cuantas restricciones se estan agregando.
	int nzcnt = 0; //# de coeficientes != 0 a ser agregados a la matriz. Solo se pasan los valores que no son cero.

	char sense[rcnt]; // Sentido de la desigualdad. 'G' es mayor o igual y 'E' para igualdad.
	for(unsigned int i = 0; i < cant_ejes * cant_colores_disp; i++)
		sense[i] = 'L';
	for(unsigned int i = cant_ejes * cant_colores_disp; i < cant_ejes * cant_colores_disp + cant_nodos; i++)
		sense[i] = 'L';
	for(unsigned int i = cant_ejes * cant_colores_disp + cant_nodos; i < cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion; i++)
		sense[i] = 'E';
	for(unsigned int i = cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion; i < rcnt; i++)
		sense[i] = 'G';

	double *rhs = new double[rcnt]; // Termino independiente de las restricciones.
	int *matbeg = new int[rcnt]; //Posicion en la que comienza cada restriccion en matind y matval.
	int *matind = new int[rcnt*n]; // Array con los indices de las variables con coeficientes != 0 en la desigualdad.
	double *matval = new double[rcnt*n]; // Array que en la posicion i tiene coeficiente ( != 0) de la variable cutind[i] en la restriccion.

	//El termino indep. de restr (1), (2) y (3) es 1
	for(unsigned int i = 0; i < cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion; i++)
		rhs[i] = 1;
		
	//El termino indep. de restr (4) y (5) es 0
	for(unsigned int i = cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion; i < rcnt; i++)
		rhs[i] = 0;
	
	unsigned int indice = 0; //numero de restriccion actual
	
	//Restricciones (1)
	for(unsigned int i = 0; i < cant_nodos; i++) //itero nodo 1
		for(unsigned int j = i+1; j < cant_nodos; j++) //itero nodo 2
			if((*adyacencias)[i][j])
				for(unsigned int p = 0; p < cant_colores_disp; p++){ //itero color
					matbeg[indice] = nzcnt;
					indice++;
					//cargo una de las variables participantes de la restr.
					matind[nzcnt] = cant_colores_disp*i + p; //var1: X_nodo1_color
					matval[nzcnt] = 1;
					nzcnt++;
					//idem con la otra variable
					matind[nzcnt] = cant_colores_disp*j + p; //var2: X_nodo2_color
					matval[nzcnt] = 1;
					nzcnt++;
				}
				
	//Restricciones (2)
	for(unsigned int i = 0; i < cant_nodos; i++){ //itero nodo
		matbeg[indice] = nzcnt;
		indice++;
		for(unsigned int p = 0; p < cant_colores_disp; p++){ //itero color
			matind[nzcnt] = cant_colores_disp*i + p; //var: X_nodo_color
			matval[nzcnt] = 1;
			nzcnt++;
		}
	}
	
	//Restricciones (3)
	for(unsigned int v = 0; v < cant_subconj_particion; v++){ //itero subconjunto de la particion
		matbeg[indice] = nzcnt;
		indice++;
		for(unsigned int i = 0; i < cant_nodos; i++) //itero nodo
			if((*particion)[v][i])
				for(unsigned int p = 0; p < cant_colores_disp; p++){ //itero color
					matind[nzcnt] = cant_colores_disp*i + p; //var: X_nodo_color
					matval[nzcnt] = 1;
					nzcnt++;
				}
	}
	
	//Restricciones (4)
	for(unsigned int p = 0; p < cant_colores_disp; p++){ //itero color
		matbeg[indice] = nzcnt;
		indice++;
		matind[nzcnt] = cant_nodos * cant_colores_disp + p; //var: W_color
		matval[nzcnt] = cant_nodos;
		nzcnt++;
		for(unsigned int i = 0; i < cant_nodos; i++){ //itero nodo
			matind[nzcnt] = cant_colores_disp*i + p; //var: X_nodo_color
			matval[nzcnt] = -1;
			nzcnt++;
		}
	}
	
	//Restricciones (5)
	for(unsigned int p = 0; p < cant_colores_disp - 1; p++){ //itero color
		matbeg[indice] = nzcnt;
		indice++;
		matind[nzcnt] = cant_nodos * cant_colores_disp + p; //var: W_color
		matval[nzcnt] = 1;
		nzcnt++;
		matind[nzcnt] = cant_nodos * cant_colores_disp + p + 1; //var: W_(color+1)
		matval[nzcnt] = -1;
		nzcnt++;
	}
	
	// Esta rutina agrega la restriccion al lp.
	status = CPXaddrows(env, lp, ccnt, rcnt, nzcnt, rhs, sense, matbeg, matind, matval, NULL, NULL);
	
	if (status) {
		cerr << "Problema agregando restricciones." << endl;
		exit(1);
	}
	
	delete[] rhs;
	delete[] matbeg;
	delete[] matind;
	delete[] matval;

	// Escribimos el problema a un archivo .lp
	status = CPXwriteprob(env, lp, "output.lp", NULL);
		
	if (status) {
		cerr << "Problema escribiendo modelo" << endl;
		exit(1);
	}
	
//----------------------- PRIMER ITERACION DE RESOLUCIÓN DEL LP
	
	// Tomamos el tiempo de resolucion utilizando CPXgettime.
	double inittime, endtime, fractpart, intpart, opt_anterior, opt_actual;
	int cant_iteraciones = 0;
	status = CPXgettime(env, &inittime);
	
	bool criterio_de_corte, todas_enteras, hubo_plano = true;
	
	status = CPXlpopt(env, lp);
	if (status) {
		cerr << "Problema optimizando CPLEX" << endl;
		exit(1);
	}
	
	status = CPXgetobjval(env, lp, &opt_actual);
	if (status) {
		cerr << "Problema obteniendo valor de mejor solucion." << endl;
		exit(1);
	}
	
	cout << "Optimo Inicial: " << opt_actual << endl << endl;
	
	double *sol = new double[n];
	status = CPXgetx(env, lp, sol, 0, n - 1);
	if (status) {
		cerr << "Problema obteniendo la solucion del LP." << endl;
		exit(1);
	}

	// Chequeo si la solución es entera
	for (int i = 0; i < n; i++){
		fractpart = modf(sol[i] , &intpart);
		if (fractpart > TOL){
			todas_enteras = false;
			break;
			}
		}
	
	criterio_de_corte = todas_enteras || max_iteraciones==0;

//----------------------- INICIO CICLO DE RESOLUCIÓN DEL LP
	while(!criterio_de_corte){
		opt_anterior = opt_actual;
		
		hubo_plano = agregar_restricciones_clique(adyacencias, sol, env, lp, cant_colores_disp, n);
		hubo_plano = agregar_restricciones_ciclos(adyacencias, sol, env, lp, cant_colores_disp, n) || hubo_plano;
		
		if(hubo_plano){
			status = CPXlpopt(env, lp);
			if (status) {
				cerr << "Problema optimizando CPLEX" << endl;
				exit(1);
			}
			
			status = CPXgetx(env, lp, sol, 0, n - 1);
			if (status) {
				cerr << "Problema obteniendo la solucion del LP." << endl;
				exit(1);
			}
			
			for (int i = 0; i < n; i++){
				fractpart = modf(sol[i] , &intpart);
				if (fractpart > TOL){
					todas_enteras = false;
					break;
				}
			}
		}
		
		status = CPXgetobjval(env, lp, &opt_actual);
		if (status) {
			cerr << "Problema obteniendo valor de mejor solucion." << endl;
			exit(1);
		}
		
		cant_iteraciones++;
		criterio_de_corte = todas_enteras || (cant_iteraciones >= max_iteraciones)
								|| !hubo_plano;// || abs(opt_actual - opt_anterior) < TOL;
	}

	status = CPXgettime(env, &endtime);
//----------------------- FIN CICLO DE RESOLUCIÓN DEL LP

	int solstat;
	char statstring[510];
	CPXCHARptr p;
	solstat = CPXgetstat(env, lp);
	p = CPXgetstatstring(env, solstat, statstring);
	string statstr(statstring);
	cout << endl << "Resultado de la optimizacion: " << statstring << endl;
	
	if(solstat!=CPX_STAT_OPTIMAL) exit(1);
	
	double objval;
	status = CPXgetobjval(env, lp, &objval);
		
	if (status) {
		cerr << "Problema obteniendo valor de mejor solucion." << endl;
		exit(1);
	}
		
	cout << "Optimo: " << objval << "\t(Time: " << (endtime - inittime) << " sec)" << endl; 

	// Tomamos los valores de la solucion y los escribimos a un archivo.
	std::string outputfile = "output.sol";
	ofstream solfile(outputfile.c_str());

	// Tomamos los valores de todas las variables. Estan numeradas de 0 a n-1.
	status = CPXgetx(env, lp, sol, 0, n - 1);

	if (status) {
		cerr << "Problema obteniendo la solucion del LP." << endl;
		exit(1);
	}

	// Solo escribimos las variables distintas de cero (tolerancia, 1E-05).
	solfile << "Status de la solucion: " << statstr << endl;
	// Imprimo var X_n_j
	for (int i = 0; i < n - cant_colores_disp; i++) {
		if (sol[i] > TOL) {
			solfile << "X_" << i / cant_colores_disp << "_" << i % cant_colores_disp << " = " << sol[i] << endl;
		}
	}
	// Imprimo var W_j
	for (int i = n - cant_colores_disp; i < n; i++) {
		if (sol[i] > TOL) {
			solfile << "W_" << i - (n - cant_colores_disp) << " = " << sol[i] << endl;
		}
	}

	solfile.close();
	delete [] sol;
	delete adyacencias;
	delete particion;
	
	return 0;
}
예제 #24
0
void
DDSIP_DetEqu ()
{
    CPXLPptr det_equ;

    int status, scen, i, j, k, nzcnt_row, ranged = 0;
    char probname[] = "sipout/det_equ.lp.gz";
    double *scaled_obj_coef = NULL;
    char *sense = NULL, *sense_sorted = NULL;
    char **scen_spec_rowname = NULL;
    char **scen_spec_colname = NULL;
    char **rowname = NULL, *rownamestore = NULL;
    char **colname = NULL, *colnamestore = NULL;
    int rowstorespace, rowsurplus;
    int colstorespace, colsurplus;
    char *string1 = NULL, *string2 = NULL;
    double *lb = NULL, *lb_sorted = NULL;
    double *ub = NULL, *ub_sorted = NULL;
    double *rng = NULL, *rng_sorted = NULL;
    char *vartype = NULL, *vartype_sorted = NULL;
    int *colindex_sorted = NULL, *colindex_revers = NULL;
    double *value = NULL;
    double *det_equ_rhs = NULL;
    double *base_rhs = NULL;
    int nzcnt=0, *rmatbeg=NULL, *rmatind=NULL, *rmatbeg_stage=NULL, *rmatind_stage=NULL, *rowindex=NULL;
    double *rmatval=NULL, *rmatval_stage=NULL;
    double time_start, time_end;
    time_start = DDSIP_GetCpuTime ();
    k = abs(DDSIP_param->riskmod);
    if (k > 2 && k != 4)
    {
        fprintf (stderr,
             "\nNot building deterministic equivalent, not available for risk model %d\n",DDSIP_param->riskmod);
        fprintf (DDSIP_outfile,
             "\nNot building deterministic equivalent, not available for risk model %d\n",DDSIP_param->riskmod);
        return;
    }
    if (DDSIP_data->seccon)
        det_equ_rhs = (double *) DDSIP_Alloc(sizeof(double),DDSIP_Imax(DDSIP_Imax(DDSIP_data->seccon, DDSIP_param->scenarios), DDSIP_data->firstcon),"det_equ_rhs(DetEqu)");
    else
    {
        fprintf (stderr,"XXX ERROR: no second stage contraints, got DDSIP_data->seccon=%d.\n",DDSIP_data->seccon);
        return;
    }

    fprintf (stderr,
             "\nBuilding deterministic equivalent.\nWorks only for expectation-based models.\n");

    colstorespace = DDSIP_data->novar * 255;
    rowstorespace = DDSIP_data->nocon * 255;
    if (!(sense = (char *) DDSIP_Alloc (sizeof (char), DDSIP_data->nocon, "sense(DetEqu)")) ||
        !(sense_sorted = (char *) DDSIP_Alloc (sizeof (char), DDSIP_Imax(DDSIP_param->scenarios, DDSIP_Imax(DDSIP_data->firstcon,DDSIP_data->seccon)), "sense_sorted(DetEqu)")) ||
        !(base_rhs = (double *) DDSIP_Alloc(sizeof(double),DDSIP_data->nocon,"base_rhs(DetEqu)")) ||
        !(scaled_obj_coef = (double *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstvar, DDSIP_data->secvar), "base_rhs(DetEqu)")) ||
        !(colname = (char **) DDSIP_Alloc (sizeof (char *), DDSIP_data->novar,"base_rhs(DetEqu)")) ||
        !(scen_spec_colname = (char **) DDSIP_Alloc (sizeof (char *), DDSIP_Imax(DDSIP_data->firstvar,DDSIP_data->secvar), "scen_spec_colname(DetEqu)")) ||
        !(colnamestore = (char *) DDSIP_Alloc (sizeof (char), colstorespace, "colnamestore(DetEqu)")) ||
        !(rowname = (char **) DDSIP_Alloc (sizeof (char *), DDSIP_data->nocon, "rowname(DetrEqu)")) ||
        !(scen_spec_rowname = (char **) DDSIP_Alloc (sizeof (char *), DDSIP_Imax(DDSIP_param->scenarios, DDSIP_Imax(DDSIP_data->firstcon,DDSIP_data->seccon)), "scen_spec_rowname(DetEqu)")) ||
        !(rownamestore = (char *) DDSIP_Alloc (sizeof (char), rowstorespace, "rownamestore(DetEqu)")) ||
        !(lb = (double *) DDSIP_Alloc (sizeof (double), DDSIP_data->novar, "lb(DetEqu)")) ||
        !(lb_sorted = (double *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstvar,DDSIP_data->secvar), "lb_sorted(DetEqu)")) ||
        !(ub = (double *) DDSIP_Alloc (sizeof (double), DDSIP_data->novar, "ub(DetEqu)")) ||
        !(ub_sorted = (double *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstvar,DDSIP_data->secvar), "ub_sorted(DetEqu)")) ||
        !(vartype = (char *) DDSIP_Alloc (sizeof (char), DDSIP_data->novar, "vartype(DetEqu)")) ||
        !(vartype_sorted = (char *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstvar,DDSIP_data->secvar), "vartype_sorted(DetEqu)")) ||
        !(colindex_sorted = (int *) DDSIP_Alloc (sizeof (int), DDSIP_data->novar, "colindex_sorted(DetEqu)")) ||
        !(rowindex = (int *) DDSIP_Alloc (sizeof (int), DDSIP_Imax(DDSIP_data->firstcon, DDSIP_data->seccon), "rowindex(DetEqu)")))
    {
        fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
        goto FREE;
    }

    // get problem data
    /*____________________________________________________________________________________*/
    if((status = CPXgetcolname (DDSIP_env, DDSIP_lp, colname, colnamestore,
                            colstorespace, &colsurplus, 0, DDSIP_data->novar - 1)) ||
       (status = CPXgetrowname (DDSIP_env, DDSIP_lp, rowname, rownamestore,
                            rowstorespace, &rowsurplus, 0, DDSIP_data->nocon - 1)) ||
       (status = CPXgetsense (DDSIP_env, DDSIP_lp, sense, 0, DDSIP_data->nocon - 1)) ||
       (status = CPXgetrhs (DDSIP_env, DDSIP_lp, base_rhs, 0, DDSIP_data->nocon - 1)) ||
       (status = CPXgetlb (DDSIP_env, DDSIP_lp, lb, 0, DDSIP_data->novar - 1)) ||
       (status = CPXgetub (DDSIP_env, DDSIP_lp, ub, 0, DDSIP_data->novar - 1)) ||
       (status = CPXgetctype (DDSIP_env, DDSIP_lp, vartype, 0, DDSIP_data->novar - 1)))
    {
        fprintf (stderr, "Coud not get problem data, returned %d\n", status);
        goto FREE;
    }
    // check whether there are ranged rows
    for (j=0; j<DDSIP_data->nocon; j++)
    {
        if (sense[j] == 'R')
        {
            ranged = 1;
	    break;
        }
    } 
    if (ranged)
    {
        if (!(rng = (double *) DDSIP_Alloc (sizeof (double), DDSIP_data->nocon, "rng(DetEqu)")) ||
            !(rng_sorted = (double *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstcon,DDSIP_data->seccon), "rng_sorted(DetEqu)")))
        {
            fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
            goto FREE;
        }
        if ((status = CPXgetrngval (DDSIP_env, DDSIP_lp, rng, 0, DDSIP_data->nocon-1)))
        {
            fprintf (stderr, "Coud not get problem ranges, returned %d\n", status);
            goto FREE;
        }
    }
    /*____________________________________________________________________________________*/

    // create empty problem
    det_equ = CPXcreateprob (DDSIP_env, &status, probname);
    if (status)
    {
        fprintf (stderr, "CPXcreateprob returned %d\n", status);
        goto FREE;
    }
    // add (original) first-stage variables
    for (j = 0; j < DDSIP_data->firstvar; j++)
    {
        vartype_sorted[j]   = vartype[DDSIP_bb->firstindex[j]];
        lb_sorted[j]        = lb[DDSIP_bb->firstindex[j]];
        ub_sorted[j]        = ub[DDSIP_bb->firstindex[j]];
        if (DDSIP_param->deteqType && DDSIP_param->riskmod >= 0)
            scaled_obj_coef[j]  = DDSIP_data->obj_coef[DDSIP_bb->firstindex[j]];
        scen_spec_colname[j]= colname[DDSIP_bb->firstindex[j]];
    }
    if ((status = CPXnewcols (DDSIP_env, det_equ, DDSIP_data->firstvar, scaled_obj_coef,
                        lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname)))
    {
        fprintf (stderr, "CPXnewcols returned %d for first-stage variables\n", status);
        goto FREE;
    }
    // add (original) second-stage variables for all scenarios
    for (j = 0; j < DDSIP_data->secvar; j++)
    {
        vartype_sorted[j] = vartype[DDSIP_bb->secondindex[j]];
        lb_sorted[j]      = lb[DDSIP_bb->secondindex[j]];
        ub_sorted[j]      = ub[DDSIP_bb->secondindex[j]];
    }
    for (scen = 0; scen < DDSIP_param->scenarios; scen++)
    {
        for (j = 0; j < DDSIP_data->secvar; j++)
        {
            if (!(string2 = (char *) calloc (1, 255 * sizeof (char))))
            {
                fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
                goto FREE;
            }
            // append scenario index to colname
            string1 = colname[DDSIP_bb->secondindex[j]];
            sprintf (string2, "%sSC%.3d", string1, scen+1);
            scen_spec_colname[j] = string2;
            if (DDSIP_param->deteqType && DDSIP_param->riskmod >= 0)
                scaled_obj_coef[j] = DDSIP_data->prob[scen] * DDSIP_data->obj_coef[DDSIP_bb->secondindex[j]];
        }
        if ((status = CPXnewcols (DDSIP_env, det_equ, DDSIP_data->secvar, scaled_obj_coef,
                        lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname)))
        {
            fprintf (stderr, "CPXnewcols returned %d for second-stage variables of scenario %d\n", status, scen+1);
            goto FREE;
        }
        for (j = 0; j < DDSIP_data->secvar; j++)
            DDSIP_Free ((void **) &(scen_spec_colname[j]));
    }
    // add second-stage variable for objective value of the scenarios
    if (!(string2 = (char *) calloc (1, 255 * sizeof (char))))
    {
        fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
        goto FREE;
    }
    scen_spec_colname[0] = string2;
    for (scen = 0; scen < DDSIP_param->scenarios; scen++)
    {
        vartype_sorted[0] = 'C';
        lb_sorted[0]      = -DDSIP_infty;
        ub_sorted[0]      =  DDSIP_infty;
        sprintf (string2, "DDSIPobj_SC%.3d", scen+1);
        if (!DDSIP_param->deteqType && DDSIP_param->riskmod >= 0)
            scaled_obj_coef[0] = DDSIP_data->prob[scen];
        else
            scaled_obj_coef[0] = 0.;
        if ((status = CPXnewcols (DDSIP_env, det_equ, 1, scaled_obj_coef,
                        lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname)))
        {
            fprintf (stderr, "CPXnewcols returned %d for second-stage variable  DDSIPobj_SC%.3d\n", status, scen+1);
            goto FREE;
        }
    }
    // add the additional variables needed for risk models ///////////////////////////////////////
    if (DDSIP_param->riskmod)
    {
        switch (abs(DDSIP_param->riskmod))
        {
          case 1:  // Expected excess
             // one continuous second-stage variable for each scenario
             for (scen = 0; scen < DDSIP_param->scenarios; scen++)
             {
                vartype_sorted[0] = 'C';
                lb_sorted[0]      = 0.;
                ub_sorted[0]      = DDSIP_infty;
                sprintf (string2, "DDSIP_expexc_SC%.3d", scen+1);
                if (DDSIP_param->riskmod > 0)
                    scaled_obj_coef[0] = DDSIP_param->riskweight*DDSIP_data->prob[scen];
                else if (DDSIP_param->riskmod < 0)
                    scaled_obj_coef[0] = DDSIP_data->prob[scen];
                else
                    scaled_obj_coef[0] = 0.;
                if ((status = CPXnewcols (DDSIP_env, det_equ, 1, scaled_obj_coef,
                                lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname)))
                {
                    fprintf (stderr, "CPXnewcols returned %d for second-stage variable  %s\n", status, string2);
                    goto FREE;
                }
             }  
             break;
          case 2:  // Excess Probability
             // one binary second-stage variable for each scenario
             for (scen = 0; scen < DDSIP_param->scenarios; scen++)
             {
                vartype_sorted[0] = 'B';
                lb_sorted[0]      = 0.;
                ub_sorted[0]      = 1.;
                sprintf (string2, "DDSIP_excprob_SC%.3d", scen+1);
                if (DDSIP_param->riskmod > 0)
                    scaled_obj_coef[0] = DDSIP_param->riskweight*DDSIP_data->prob[scen];
                else if (DDSIP_param->riskmod < 0)
                    scaled_obj_coef[0] = DDSIP_data->prob[scen];
                else
                    scaled_obj_coef[0] = 0.;
                if ((status = CPXnewcols (DDSIP_env, det_equ, 1, scaled_obj_coef,
                                lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname)))
                {
                    fprintf (stderr, "CPXnewcols returned %d for second-stage variable  %s\n", status, string2);
                    goto FREE;
                }
             }  
             break;
          case 4:  // Worst Case Costs
             // one continuous first-stage variable
                vartype_sorted[0] = 'C';
                lb_sorted[0]      = -DDSIP_infty;
                ub_sorted[0]      =  DDSIP_infty;
                if (DDSIP_param->prefix)
                {
                    if (!(strlen(DDSIP_param->prefix)))
                    {
                        fprintf (stderr," *** ERROR: The prefix for the first stage variables has to have a positive length.\n");
                        exit (1);
                    }
                    sprintf (string2, "%sDDSIP_n_aux01",DDSIP_param->prefix);
                }
                else
                {
                    if (!(strlen(DDSIP_param->postfix)))
                    {
                        fprintf (stderr," *** ERROR: The postfix for the first stage variables has to have a positive length.\n");
                        exit (1);
                    }
                    sprintf (string2, "DDSIP_worstc_%s",DDSIP_param->postfix);
                }
                if (DDSIP_param->riskmod > 0)
                    scaled_obj_coef[0] = DDSIP_param->riskweight;
                else if (DDSIP_param->riskmod < 0)
                    scaled_obj_coef[0] = 1.;
                else
                    scaled_obj_coef[0] = 0.;
                if ((status = CPXnewcols (DDSIP_env, det_equ, 1, scaled_obj_coef,
                                lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname)))
                {
                    fprintf (stderr, "CPXnewcols returned %d for second-stage variable  %s\n", status, string2);
                    goto FREE;
                }
        }
    }
    DDSIP_Free ((void **) &(scen_spec_colname[0]));
        
    ///////enter stochastic cost coefficients in case of deteqType 1 //////////////////////////////
    if (DDSIP_param->stoccost && DDSIP_param->deteqType && DDSIP_param->riskmod >= 0)
    {
        for (j = 0; j < DDSIP_param->stoccost; j++)
        {
            scaled_obj_coef[j] = 0.0;
            if ((colindex_sorted[j] = DDSIP_bb->firstindex_reverse[DDSIP_data->costind[j]]))
                 colindex_sorted[j] = DDSIP_data->firstvar + DDSIP_bb->secondindex_reverse[DDSIP_data->costind[j]];
        }
        for (scen = 0; scen < DDSIP_param->scenarios; scen++)
        {
            for (j = 0; j < DDSIP_param->stoccost; j++)
            {
                if (colindex_sorted[j] >= DDSIP_data->firstvar)
                    scaled_obj_coef[j] = DDSIP_data->prob[scen] * DDSIP_data->cost[scen * DDSIP_param->stoccost + j];
                else
                    scaled_obj_coef[j] += DDSIP_data->prob[scen] * DDSIP_data->cost[scen * DDSIP_param->stoccost + j];
            }
            status = CPXchgobj (DDSIP_env, det_equ, DDSIP_param->stoccost, colindex_sorted, scaled_obj_coef);
            if (status)
            {
                char errmsg[1024];
                CPXgeterrorstring (DDSIP_env, status, errmsg);
                fprintf (stderr, "in DetEqu: %s\n", errmsg);
            }
            for (j = 0; j < DDSIP_param->stoccost; j++)
            {
                if (colindex_sorted[j] >= DDSIP_data->firstvar)
                    colindex_sorted[j] += DDSIP_data->secvar;
            }
        }
    }
    //
    // free arrays needeed only for columns
    DDSIP_Free ((void **) &(vartype));
    DDSIP_Free ((void **) &(colname));
    DDSIP_Free ((void **) &(colnamestore));
    DDSIP_Free ((void **) &(lb));
    DDSIP_Free ((void **) &(ub));
    DDSIP_Free ((void **) &(vartype_sorted));
    DDSIP_Free ((void **) &(lb_sorted));
    DDSIP_Free ((void **) &(ub_sorted));
    DDSIP_Free ((void **) &(scaled_obj_coef));
    //
    // get problem matrix coefficients
    // query the length needed for storage of coefficients
    CPXgetrows(DDSIP_env, DDSIP_lp, &nzcnt, rmatbeg, rmatind, rmatval, 0, &rowsurplus, 0, DDSIP_data->nocon-1);
    nzcnt = -rowsurplus;
    if (!(rmatbeg = (int *) DDSIP_Alloc (sizeof (int), DDSIP_data->nocon, "rmatbeg(DetEqu)")) ||
        !(rmatind = (int *) DDSIP_Alloc (sizeof (int), DDSIP_Imax(nzcnt, DDSIP_param->stocmat), "rmatind(DetEqu)")) ||
        !(rmatval = (double *) DDSIP_Alloc (sizeof (double), nzcnt, "rmatval(DetEqu)")))
    {
        fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
        goto FREE;
    }
    CPXgetrows(DDSIP_env, DDSIP_lp, &nzcnt, rmatbeg, rmatind, rmatval, nzcnt, &rowsurplus, 0, DDSIP_data->nocon-1);

    printf(" got %d elements of the matrix\n", nzcnt);

    k = DDSIP_Imax(nzcnt + DDSIP_param->stocmat, DDSIP_param->scenarios*(DDSIP_data->novar+1));
    if (!(rmatbeg_stage = (int *) DDSIP_Alloc (sizeof (int), DDSIP_Imax(DDSIP_param->scenarios, DDSIP_Imax(DDSIP_data->firstcon, DDSIP_data->seccon)), "rmatbeg_stage(DetEqu)")) ||
        !(rmatind_stage = (int *) DDSIP_Alloc (sizeof (int), k, "rmatind_stage(DetEqu)")) ||
        !(rmatval_stage = (double *) DDSIP_Alloc (sizeof (double), k, "rmatval_stage(DetEqu)")))
    {
        fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
        goto FREE;
    }

    // add first-stage constraints
    k = 0;
    for (j = 0; j < DDSIP_data->firstcon; j++)
    {
        sense_sorted[j] = sense[DDSIP_bb->firstrowind[j]];
        det_equ_rhs[j] = base_rhs[DDSIP_bb->firstrowind[j]];
        scen_spec_rowname[j] = rowname[DDSIP_bb->firstrowind[j]];
	rmatbeg_stage[j] = k;
	if (DDSIP_bb->firstrowind[j] == DDSIP_data->nocon -1)
            nzcnt_row = nzcnt - rmatbeg[DDSIP_data->nocon -1];
        else
            nzcnt_row = rmatbeg[DDSIP_bb->firstrowind[j]+1] - rmatbeg[DDSIP_bb->firstrowind[j]];
	for (i = 0; i < nzcnt_row; i++)
        {
            rmatind_stage[k + i] = DDSIP_bb->firstindex_reverse[rmatind[rmatbeg[DDSIP_bb->firstrowind[j]] + i]];
            rmatval_stage[k + i] = rmatval[rmatbeg[DDSIP_bb->firstrowind[j]] + i];
        }
	k += nzcnt_row;
    }
    if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_data->firstcon, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname)))
    {
        fprintf (stderr, "CPXaddrows returned %d for first-stage constraints\n", status);
        goto FREE;
    }
    if (ranged)
    {
        for (j = 0; j < DDSIP_data->firstcon; j++)
        {
            rng_sorted[j] = rng[DDSIP_bb->firstrowind[j]];
            rowindex[j]   = j;
        }
        if((status = CPXchgrngval(DDSIP_env, det_equ, DDSIP_data->firstcon, rowindex, rng_sorted)))
        {
            fprintf (stderr, "CPXchgrngval returned %d for first-stage constraints\n", status);
            goto FREE;
        }
    }

    // add second-stage constraints
    for (scen = 0; scen < DDSIP_param->scenarios; scen++)
    {
        k = 0;
        for (j = 0; j < DDSIP_data->seccon; j++)
        {
            sense_sorted[j] = sense[DDSIP_bb->secondrowind[j]];
            det_equ_rhs[j] = base_rhs[DDSIP_bb->secondrowind[j]];
            if (!(string2 = (char *) calloc (1, 255 * sizeof (char))))
            {
                fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
                goto FREE;
            }
            // append scenario index to colname
            string1 = rowname[DDSIP_bb->secondrowind[j]];
            sprintf (string2, "%sSC%.3d", string1, scen+1);
            scen_spec_rowname[j] = string2;
            rmatbeg_stage[j] = k;
            if (DDSIP_bb->secondrowind[j] == DDSIP_data->nocon -1)
                nzcnt_row = nzcnt - rmatbeg[DDSIP_data->nocon -1];
            else
            {
                nzcnt_row = rmatbeg[DDSIP_bb->secondrowind[j]+1] - rmatbeg[DDSIP_bb->secondrowind[j]];

            }
            for (i = 0; i < nzcnt_row; i++)
            {
                if (DDSIP_bb->firstindex_reverse[rmatind[rmatbeg[DDSIP_bb->secondrowind[j]] + i]] < 0)
                    rmatind_stage[k + i] = DDSIP_data->firstvar + scen*DDSIP_data->secvar + DDSIP_bb->secondindex_reverse[rmatind[rmatbeg[DDSIP_bb->secondrowind[j]] + i]];
                else
                    rmatind_stage[k + i] = DDSIP_bb->firstindex_reverse[rmatind[rmatbeg[DDSIP_bb->secondrowind[j]] + i]];
                rmatval_stage[k + i] = rmatval[rmatbeg[DDSIP_bb->secondrowind[j]] + i];
            }
            k += nzcnt_row;
        }
        ///////enter stochastic rhs entries//////////////////////////////////////////////////////
        for (j=0; j< DDSIP_param->stocrhs; j++)
        {
            det_equ_rhs[DDSIP_bb->secondrowind_reverse[DDSIP_data->rhsind[j]]] = DDSIP_data->rhs[scen * DDSIP_param->stocrhs + j];
        }

        if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_data->seccon, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname)))
        {
            fprintf (stderr, "CPXaddrows returned %d for second-stage constraints scenario %d\n", status, scen+1);
            goto FREE;
        }
        for (j = 0; j < DDSIP_data->seccon; j++)
            DDSIP_Free ((void **) &(scen_spec_rowname[j]));
        if (ranged)
        {
            for (j = 0; j < DDSIP_data->seccon; j++)
            {
                rng_sorted[j] = rng[DDSIP_bb->secondrowind[j]];
                rowindex[j]   = DDSIP_data->firstcon + scen * DDSIP_data->seccon + j;
            }
            if ((status = CPXchgrngval(DDSIP_env, det_equ, DDSIP_data->seccon, rowindex, rng_sorted)))
            {
                fprintf (stderr, "CPXchgrngval returned %d for first-stage constraints\n", status);
                goto FREE;
            }
        }
    }
    ///////enter stochastic matrix entries//////////////////////////////////////////////////////
    if (DDSIP_param->stocmat)
    {

        if (!(value = (double *) calloc (DDSIP_param->stocmat, sizeof (double))))
        {
            fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
            goto FREE;
        }
        for (j = 0; j < DDSIP_param->stocmat; j++)
        {
            if ((colindex_sorted[j] = DDSIP_bb->firstindex_reverse[DDSIP_data->matcol[j]]))
                 colindex_sorted[j] = DDSIP_data->firstvar + DDSIP_bb->secondindex_reverse[DDSIP_data->matcol[j]];
            rmatind[j] = DDSIP_data->firstcon + DDSIP_bb->secondrowind_reverse[DDSIP_data->matrow[j]];
        }
        for (scen = 0; scen < DDSIP_param->scenarios; scen++)
        {
            for (j = 0; j < DDSIP_param->stocmat; j++)
            {
                value[j] = DDSIP_data->matval[scen * DDSIP_param->stocmat + j];
            }
            status = CPXchgcoeflist (DDSIP_env, det_equ, DDSIP_param->stocmat, rmatind, colindex_sorted, value);
            if (status)
            {
                char errmsg[1024];
                CPXgeterrorstring (DDSIP_env, status, errmsg);
                fprintf (stderr, "in DetEqu chgcoeflist returned %d: %s\n", status, errmsg);
            }
            for (j = 0; j < DDSIP_param->stocmat; j++)
            {
                rmatind[j] += DDSIP_data->seccon;
                if (colindex_sorted[j] >= DDSIP_data->firstvar)
                    colindex_sorted[j] += DDSIP_data->secvar;
            }
        }
        DDSIP_Free ((void **) &(value));
    }

    // add second-stage equations for the objective values of the scenarios
    k = 0;
    for (scen = 0; scen < DDSIP_param->scenarios; scen++)
    {
        sense_sorted[scen] = 'E';
        det_equ_rhs[scen] = 0.;
        if (!(string2 = (char *) calloc (1, 255 * sizeof (char))))
        {
            fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
            goto FREE;
        }
        sprintf (string2, "DDSIP_o_SC%.3d", scen+1);
        scen_spec_rowname[scen] = string2;
        rmatbeg_stage[scen] = k;
        nzcnt_row = DDSIP_data->novar + 1;
        for (i = 0; i < DDSIP_data->novar; i++)
        {
            if (DDSIP_bb->firstindex_reverse[i] < 0)
            {
                rmatind_stage[k + i] = DDSIP_data->firstvar + scen*DDSIP_data->secvar + DDSIP_bb->secondindex_reverse[i];
            }
            else
            {
                rmatind_stage[k + i] = DDSIP_bb->firstindex_reverse[i];
            }
            rmatval_stage[k + i] = DDSIP_data->obj_coef[i];
        }
        rmatind_stage[k + DDSIP_data->novar] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + scen;
        rmatval_stage[k + DDSIP_data->novar] = -1.;
        k += nzcnt_row;
    }
    if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_param->scenarios, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname)))
    {
        fprintf (stderr, "CPXaddrows returned %d for second-stage objective constraints\n", status);
        goto FREE;
    }
    for (scen = 0; scen < DDSIP_param->scenarios; scen++)
    {
        DDSIP_Free ((void **) &(scen_spec_rowname[scen]));
    }
    ///////enter stochastic cost coefficients in the objective equations //////////////////////////////
    if (DDSIP_param->stoccost)
    {
        if (!(value = (double *) calloc (DDSIP_param->stoccost, sizeof (double))))
        {
            fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
            goto FREE;
        }
        for (scen = 0; scen < DDSIP_param->scenarios; scen++)
        {
            for (j = 0; j < DDSIP_param->stoccost; j++)
            {
                if ((colindex_sorted[j] = DDSIP_bb->firstindex_reverse[DDSIP_data->costind[j]]) < 0)
                     colindex_sorted[j] = DDSIP_data->firstvar + scen * DDSIP_data->secvar +DDSIP_bb->secondindex_reverse[DDSIP_data->costind[j]];
                rmatind[j] = DDSIP_data->firstcon + DDSIP_param->scenarios*DDSIP_data->seccon + scen;
                value[j] = DDSIP_data->cost[scen * DDSIP_param->stoccost + j];
            }
            status = CPXchgcoeflist (DDSIP_env, det_equ, DDSIP_param->stoccost, rmatind, colindex_sorted, value);
            if (status)
            {
                char errmsg[1024];
                CPXgeterrorstring (DDSIP_env, status, errmsg);
                fprintf (stderr, "in DetEqu chgcoeflist returned %d: %s\n", status, errmsg);
            }
            for (j = 0; j < DDSIP_param->stocmat; j++)
            {
                rmatind[j] += DDSIP_data->seccon;
                if (colindex_sorted[j] >= DDSIP_data->firstvar)
                    colindex_sorted[j] += DDSIP_data->secvar;
            }
        }
        DDSIP_Free ((void **) &(value));
    }
    // add second-stage equations for the risk models //////////////////////////////////
    switch (abs(DDSIP_param->riskmod))
    {
      case 1:  // Expected excess
         k = 0;
         for (scen = 0; scen < DDSIP_param->scenarios; scen++)
         {
             sense_sorted[scen] = 'L';
             det_equ_rhs[scen]  = DDSIP_param->risktarget;
             if (!(string2 = (char *) calloc (1, 255 * sizeof (char))))
             {
                 fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
                 goto FREE;
             }
             sprintf (string2, "DDSIP_exp_excess_SC%.3d", scen+1);
             scen_spec_rowname[scen] = string2;
             rmatbeg_stage[scen] = k;
             nzcnt_row = 2;
             rmatind_stage[k]     = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + scen; 
             rmatval_stage[k]     = 1.;
             rmatind_stage[k + 1] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + DDSIP_param->scenarios + scen; 
             rmatval_stage[k + 1] = -1.;
             k += nzcnt_row;
         }
         if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_param->scenarios, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname)))
         {
             fprintf (stderr, "CPXaddrows returned %d for second-stage risk constraints\n", status);
             goto FREE;
         }
         break;
      case 2:  // Excess probability
         k = 0;
         for (scen = 0; scen < DDSIP_param->scenarios; scen++)
         {
             sense_sorted[scen] = 'L';
             det_equ_rhs[scen]  = DDSIP_param->risktarget;
             if (!(string2 = (char *) calloc (1, 255 * sizeof (char))))
             {
                 fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
                 goto FREE;
             }
             sprintf (string2, "DDSIP_excess_prob_SC%.3d", scen+1);
             scen_spec_rowname[scen] = string2;
             rmatbeg_stage[scen] = k;
             nzcnt_row = 2;
             rmatind_stage[k]     = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + scen; 
             rmatval_stage[k]     = 1.;
             rmatind_stage[k + 1] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + DDSIP_param->scenarios + scen; 
             rmatval_stage[k + 1] = -DDSIP_param->riskM;
             k += nzcnt_row;
         }
         if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_param->scenarios, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname)))
         {
             fprintf (stderr, "CPXaddrows returned %d for second-stage risk constraints\n", status);
             goto FREE;
         }
         break;
      case 4:  // Worst case cost
         k = 0;
         for (scen = 0; scen < DDSIP_param->scenarios; scen++)
         {
             sense_sorted[scen] = 'L';
             det_equ_rhs[scen]  = 0.;
             if (!(string2 = (char *) calloc (1, 255 * sizeof (char))))
             {
                 fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
                 goto FREE;
             }
             sprintf (string2, "DDSIP_worst_case_SC%.3d", scen+1);
             scen_spec_rowname[scen] = string2;
             rmatbeg_stage[scen] = k;
             nzcnt_row = 2;
             rmatind_stage[k]     = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + scen; 
             rmatval_stage[k]     = 1.;
             rmatind_stage[k + 1] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + DDSIP_param->scenarios; 
             rmatval_stage[k + 1] = -1.;
             k += nzcnt_row;
         }
         if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_param->scenarios, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname)))
         {
             fprintf (stderr, "CPXaddrows returned %d for second-stage risk constraints\n", status);
             goto FREE;
         }
         break;
    }
    for (j = 0; j < DDSIP_param->scenarios; j++)
        DDSIP_Free ((void **) &(scen_spec_rowname[j]));

    time_end = DDSIP_GetCpuTime ();
    fprintf (DDSIP_outfile, " %6.2f sec  for building deterministic equivalent\n",time_end-time_start);

    status = CPXwriteprob (DDSIP_env, det_equ, probname, NULL);
    if (status)
    {
        fprintf (DDSIP_outfile, " *** Deterministic equivalent not written successfully, status = %d\n", status);
        printf  (" *** Deterministic equivalent not written successfully, status = %d\n", status);
    }
    else
    {
        fprintf (DDSIP_outfile, " *** Deterministic equivalent %s written successfully\n", probname);
        printf  (" *** Deterministic equivalent %s written successfully\n", probname);
    }
    status = CPXfreeprob (DDSIP_env, &det_equ);
    time_start = DDSIP_GetCpuTime ();
    fprintf (DDSIP_outfile, " %6.2f sec  for writing deterministic equivalent\n",time_start-time_end);

FREE:
    DDSIP_Free ((void **) &(sense));
    DDSIP_Free ((void **) &(sense_sorted));
    DDSIP_Free ((void **) &(vartype));
    DDSIP_Free ((void **) &(rowname));
    DDSIP_Free ((void **) &(rownamestore));
    DDSIP_Free ((void **) &(colname));
    DDSIP_Free ((void **) &(colnamestore));
    DDSIP_Free ((void **) &(det_equ_rhs));
    DDSIP_Free ((void **) &(base_rhs));
    DDSIP_Free ((void **) &(lb));
    DDSIP_Free ((void **) &(ub));
    DDSIP_Free ((void **) &(vartype_sorted));
    DDSIP_Free ((void **) &(lb_sorted));
    DDSIP_Free ((void **) &(ub_sorted));
    DDSIP_Free ((void **) &(scaled_obj_coef));
    DDSIP_Free ((void **) &(colindex_sorted));
    DDSIP_Free ((void **) &(colindex_revers));
    DDSIP_Free ((void **) &(scen_spec_rowname));
    DDSIP_Free ((void **) &(scen_spec_colname));
    DDSIP_Free ((void **) &(rmatbeg));
    DDSIP_Free ((void **) &(rmatind));
    DDSIP_Free ((void **) &(rmatval));
    DDSIP_Free ((void **) &(rmatbeg_stage));
    DDSIP_Free ((void **) &(rmatind_stage));
    DDSIP_Free ((void **) &(rmatval_stage));
    DDSIP_Free ((void **) &(rowindex));
    if (ranged)
    {
        DDSIP_Free ((void **) &(rng));
        DDSIP_Free ((void **) &(rng_sorted));
    }
    return;
}
예제 #25
0
파일: main.cpp 프로젝트: germanromano/invop
bool agregar_restricciones_clique(const vector<vector<bool> > *adyacencias, double *sol, CPXENVptr env, CPXLPptr lp,
									int cant_colores_disp, int cant_variables){

//----------------------- IDENTIFICO COLORES USADOS Y NODOS PINTADOS
	vector<bool> *nodos_pintados = new vector<bool>(adyacencias->size(), false);
	for(unsigned int i = 0; i < adyacencias->size(); i++) // recorro nodos
		for(int j = 0; j < cant_colores_disp; j++)	// recorro colores
			if(sol[i*cant_colores_disp + j] > TOL){
				(*nodos_pintados)[i] = true;
				break;
			}
	
	vector<bool> *colores_usados = new vector<bool>(cant_colores_disp, false);
	for(int i = cant_variables - cant_colores_disp; i < cant_variables; i++)
		if(sol[i] > TOL)
			(*colores_usados)[i - (cant_variables - cant_colores_disp)] = true;

//----------------------- ARMADO DE CLIQUES
	vector<vector<unsigned int> > *cliques = new vector<vector<unsigned int> > (adyacencias->size(), vector<unsigned int>(0));
	
	vector<unsigned int> permutacion(adyacencias->size(), 0);
	for(unsigned int i = 0; i < permutacion.size(); i++)
		permutacion[i] = i;
	random_shuffle(permutacion.begin(), permutacion.end());
	
	// Ubico a los nodos pintados en diferentes cliques
	//~ int count, cant_nodos_pintados = cliques->size();
	int count, cant_nodos_pintados = 0;
	for(unsigned int i = 0; i < permutacion.size(); i++) // recorro nodos pintados (PERMUTADOS)
		if((*nodos_pintados)[permutacion[i]]){
			(*cliques)[cant_nodos_pintados].resize(1, permutacion[i]); // En vez de push_back(i): alloco memoria y agrego
			cant_nodos_pintados++;
		}
	
	// Ubico al resto de los nodos
	for(unsigned int i = 0; i < permutacion.size(); i++) // recorro nodos (PERMUTADOS) no pintados
		if(!(*nodos_pintados)[(permutacion[i])]){
			for(unsigned int j = 0; j < cant_nodos_pintados; j++){ // recorro cliques que contengan nodos pintados
				count = 0;
				
				for(unsigned int v = 0; v < (*cliques)[j].size(); v++) // recorro los nodos de la clique j
					if((*adyacencias)[(permutacion[i])][((*cliques)[j][v])]) count++;
					else break;
				
				if(count == (*cliques)[j].size()){
					(*cliques)[j].resize((*cliques)[j].size() + 1, permutacion[i]);
					break;
				}
			}
		}
	
//----------------------- CHEQUEO DE RESTRICCIONES VIOLADAS
	bool res = false;
	int status, violadas = 0;
	double sum;
	
	int ccnt = 0; //numero nuevo de columnas en las restricciones.
	int rcnt = 1; //cuantas restricciones se estan agregando.
	int nzcnt = 0; //# de coeficientes != 0 a ser agregados a la matriz. Solo se pasan los valores que no son cero.
	char sense[] = {'L'}; // Sentido de la desigualdad. 'G' es mayor o igual y 'E' para igualdad.
	double rhs[] = {0}; // Termino independiente de las restricciones.
	int matbeg[] = {0}; //Posicion en la que comienza cada restriccion en matind y matval.
	int *matind = new int[cant_variables]; // Array con los indices de las variables con coeficientes != 0 en la desigualdad.
	double *matval = new double[cant_variables]; // Array que en la posicion i tiene coeficiente ( != 0) de la variable cutind[i] en la restriccion.
	
	for(unsigned int c = 0; c < cant_nodos_pintados; c++){ // recorro cliques con algun nodo pintado
		for(unsigned int j = 0; j < cant_colores_disp; j++){ // recorro colores USADOS
			if((*colores_usados)[j]){
				sum = 0.0;
				for(unsigned int p = 0; p < (*cliques)[c].size(); p++){ // recorro nodos de la clique c
					sum += sol[(*cliques)[c][p] * cant_colores_disp + j];
				}
				
				if (sum - sol[cant_variables - cant_colores_disp + j] > TOL){
					//cout << endl << "Restriccion violada: ";
					//cargo restriccion asociada a la clique c y el color j
					nzcnt = 0;
					for(unsigned int p = 0; p < cant_variables; p++){ // reset de estructuras
						matind[p] = 0;
						matval[p] = 0;
					}
					for(unsigned int p = 0; p < (*cliques)[c].size(); p++){ // recorro nodos de la clique c
						matind[nzcnt] = (*cliques)[c][p] * cant_colores_disp + j; // X_p_j
						matval[nzcnt] = 1.0;
						nzcnt++;
						//cout << "X_" << (*cliques)[c][p] << "_" << j << " ";
					}
					matind[nzcnt] = cant_variables - cant_colores_disp + j; // W_j
					matval[nzcnt] = -1.0;
					nzcnt++;
					//cout << "<= W_" << j; 

					status = CPXaddrows(env, lp, ccnt, rcnt, nzcnt, rhs, sense, matbeg, matind, matval, NULL, NULL);
					/*status = CPXwriteprob(env, lp, "postoutput.lp", NULL);
					if (status) {
						cerr << "Problema agregando restricciones." << endl;
						exit(1);
					}*/

					res = true;
					violadas++;
				}
			}
		}
	}
	
	// Para imprimir la clique
	/*cout << endl << "-------------------------------------" << endl << "DESCOMPOSICION EN CLIQUES:" << endl;
	for(unsigned int i = 0; i < (*cliques).size(); i++)
		if((*cliques)[i].size() > 0){
			cout << "Clique: ";
			for(unsigned int j = 0; j < (*cliques)[i].size(); j++)
				cout << (*cliques)[i][j] << " ";
			cout << endl;
		}*/
	cout << "Restr. clique violadas: \t" << violadas << endl;
	
	delete cliques;
	delete nodos_pintados;
	delete colores_usados;
	delete[] matind;
	delete[] matval;
	return res;
}
예제 #26
0
void PartitionedColoringModel::cutAndBranch() {
	int status;
	double inittime, endtime;
	status = CPXgettime(this->cplexEnvironment, &inittime);
	
	for(int w = 0; w < 10; w++) {
		this->solve();
		this->getCurrentSolution();
		
		int amountOfNewRestrictions = this->graph->amountOfNodes() * 2; // 1 para clique, 1 para agujero
		int amountOfNonZeroCoefficients = 0;
		char *sense = new char[amountOfNewRestrictions];
		
		std::vector< std::set<Node*> > cliqueList;
		std::vector< std::vector<Node*> > cycleList;
		
		// Para cada color, obtengo los nodos que están "más pintados" de ese color.
		for(int j = 1; j <= this->graph->amountOfNodes(); j++) {
			int maxNode = -1;
			double maxColored = -1.0;
			for(int i = 1; i <= this->graph->amountOfNodes(); i++) {
				int variablePosition = this->xVariablePositionFromModelIndex(i, j);
				double howMuchIsColored = this->currentSolution[variablePosition];
				if(maxNode == -1 || howMuchIsColored > maxNode) {
					maxNode = i;
					maxColored = howMuchIsColored;
				}
			}
			
			Node *node = this->graph->getNodeWith(maxNode);

			// Para ese nodo, busco una clique y la agrego como restricción.
			FindCliqueHeuristic findCliqueHeuristic(this->graph);
			std::set<Node*> clique = findCliqueHeuristic.findCliqueContainingThis(node);
			cliqueList.push_back(clique);
			amountOfNonZeroCoefficients += (clique.size() + 1);

			// Para ese nodo, busco un ciclo y lo agrego como restricciòn.
			FindCycleHeuristic findCycleHeuristic(this->graph);
			std::vector<Node*> cycle = findCycleHeuristic.getOddCycle(node->getId());
			cycleList.push_back(cycle);
			amountOfNonZeroCoefficients += (cycle.size() + 1);
		}
		
		int *restrictionsIndex = new int[amountOfNewRestrictions];
		int *coefficientsIndex = new int[amountOfNonZeroCoefficients];
		double *coefficientsValues = new double[amountOfNonZeroCoefficients];
		
		int ci = 0, rn = 0, j;
		for(j = 0; j < cliqueList.size(); j++) {
			//clique
			restrictionsIndex[rn] = ci;
			std::set<Node*>::iterator node;
			for(node = cliqueList.at(j).begin(); node != cliqueList.at(j).end(); ++node) {
				coefficientsIndex[ci] = this->xVariablePositionFromModelIndex((*node)->getId(), j + 1);
				coefficientsValues[ci] = 1.0;
				ci++;
			}
			coefficientsIndex[ci] = this->wVariablePositionFromModelIndex(j + 1);
			coefficientsValues[ci] = -1.0;
			ci++;
			sense[rn] = 'L';
			rn++;
			//cycle
			restrictionsIndex[rn] = ci;
			std::vector<Node*>::iterator node1;
			for(node1 = cycleList.at(j).begin(); node1 != cycleList.at(j).end(); ++node1) {
				coefficientsIndex[ci] = this->xVariablePositionFromModelIndex((*node1)->getId(), j + 1);
				coefficientsValues[ci] = 1.0;
				ci++;
			}
			coefficientsIndex[ci] = this->wVariablePositionFromModelIndex(j + 1);
			coefficientsValues[ci] = -1.0 * this->graph->amountOfPartitions();
			ci++;
			sense[rn] = 'L';
			rn++;
		}
		
		status = CPXaddrows(this->cplexEnvironment,
							this->linearProblem,
							0,
							amountOfNewRestrictions,
							amountOfNonZeroCoefficients,
							NULL,
							sense,
							restrictionsIndex,
							coefficientsIndex,
							coefficientsValues,
							NULL,
							NULL);
							
		delete [] sense;
		delete [] restrictionsIndex;
		delete [] coefficientsIndex;
		delete [] coefficientsValues;
	}
	
	this->solve();
	this->getCurrentSolution();

	this->saveInitialSolution();
	this->changeToBinaryVariables();
	this->solve();
	
	status = CPXgettime(this->cplexEnvironment, &endtime);
	this->saveAmountOfNodesVisited();

	this->saveFinalSolution();
	this->cplexResult.setTime(endtime - inittime);
}
예제 #27
0
파일: foodmanu.c 프로젝트: renvieir/ioc
static int
buildmodel (CPXENVptr env, CPXLPptr lp)
{

   int    colcnt = NUMVARS*NUMMONTHS*NUMPRODUCTS;

   double *obj     = NULL;
   double *lb      = NULL;
   double *ub      = NULL;
   char   *ctype   = NULL;
   int    *rmatind = NULL;
   double *rmatval = NULL;

   int    indicator;
   int    rmatbeg[1];
   double rhs[1];
   char   sense[1];

   int    m, p;
   int    status = 0;

   status = CPXchgobjsen (env, lp, CPX_MAX); /* Maximization problem */
   if ( status ) {
      fprintf (stderr, "Could not change objective sense.\n");
      goto TERMINATE;
   }

   rmatbeg[0] = 0;

   /* Allocate colcnt-sized arrays */

   obj     = (double *) malloc (colcnt * sizeof(double));
   lb      = (double *) malloc (colcnt * sizeof(double));
   ub      = (double *) malloc (colcnt * sizeof(double));
   ctype   = (char *)   malloc (colcnt * sizeof(char));
   rmatind = (int * )   malloc (colcnt * sizeof(int));
   rmatval = (double *) malloc (colcnt * sizeof(double));

   if ( obj     == NULL ||
        lb      == NULL ||
        ub      == NULL ||
        ctype   == NULL ||
        rmatind == NULL ||
        rmatval == NULL   ) {
      fprintf (stderr, "Could not allocate colcnt arrays\n");
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   }

   /* Create variables. For each month and each product, we have 3
      variables corresponding to the quantity used (semi-continuous),
      stored (continuous) and bought (continuous) and one binary
      variable indicating whether or not the product is used during
      this month. */

   for (m = 0; m < NUMMONTHS; m++) {
      for (p = 0; p < NUMPRODUCTS; p++) {

         /* The quantity bought is a continuous variable. It has a cost */

         obj[varindex(m, p, BUY)]    = -cost[m*NUMPRODUCTS + p];
         lb[varindex (m, p, BUY)]    = 0.0;
         ub[varindex (m, p, BUY)]    = CPX_INFBOUND;
         ctype[varindex (m, p, BUY)] = 'C';

         /* When an oil is used, the quantity must be at least 20
            tons. This is modeled as a semi-continuous variable. */

         obj[varindex (m, p, USE)]   = 0.0;
         lb[varindex (m, p, USE)]    = 20.0;
         ub[varindex (m, p, USE)]    = CPX_INFBOUND;
         ctype[varindex (m, p, USE)] = 'S';

         /* It is possible to store up to 1000 tons of each
            product. There are storage costs. */

         obj[varindex (m, p, STORE)]   = -5.0;
         lb[varindex (m, p, STORE)]    = 0.0;
         ub[varindex (m, p, STORE)]    = 1000.0;
         ctype[varindex (m, p, STORE)] = 'C';

         /* At the end, we must have exactly 500 tons of each
            product in storage. */

         if ( m == NUMMONTHS - 1 ) {
            lb[varindex (m, p, STORE)] = 500.0;
            ub[varindex (m, p, STORE)] = 500.0;
         }

         /* The variable indicating whether or not a product is
            used during a month is a binary variable. */

         obj[varindex (m, p, IS_USED)]   = 0.0;
         lb[varindex (m, p, IS_USED)]    = 0.0;
         ub[varindex (m, p, IS_USED)]    = 1.0;
         ctype[varindex (m, p, IS_USED)] = 'B';
      }
   }

   status = CPXnewcols (env, lp, colcnt, obj, lb, ub, ctype, NULL);
   if ( status ) {
      fprintf (stderr, "Could not add new columns.\n");
      goto TERMINATE;
   }

   /* Constraints for each month */

   for (m = 0; m < NUMMONTHS; m++) {
      int totalindex;

      /* For each product, create an indicator constraint linking the
         quantity used and the binary variable indicating whether or
         not the product is used */

      for (p = 0; p < NUMPRODUCTS; p++) {
         indicator  = varindex (m, p, IS_USED);
         rmatind[0] = varindex (m, p, USE);
         rmatval[0] = 1.0;
         status = CPXaddindconstr (env, lp, indicator, 1, 1, 0.0, 'L',
                                   rmatind, rmatval, NULL);
         if ( status ) {
            fprintf (stderr, "Could not add new indicator constraint.\n");
            goto TERMINATE;
         }
      }

      /* Not more than 200 tons of vegetable oil can be refined */

      rmatind[0] = varindex (m, VEGOIL1, USE);
      rmatind[1] = varindex (m, VEGOIL2, USE);
      rmatval[0] = 1.0;
      rmatval[1] = 1.0;
      rhs[0]     = 200.0;
      sense[0]   = 'L';
      status = CPXaddrows (env, lp, 0, 1, 2, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);

      /* Not more than 250 tons of non-vegetable oil can be refined */

      rmatind[0] = varindex (m, OIL1, USE);
      rmatind[1] = varindex (m, OIL2, USE);
      rmatind[2] = varindex (m, OIL3, USE);
      rmatval[0] = 1.0;
      rmatval[1] = 1.0;
      rmatval[2] = 1.0;
      rhs[0]     = 250.0;
      sense[0]   = 'L';
      status = CPXaddrows (env, lp, 0, 1, 3, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* Constraint on food composition */

      /* Add a variable corresponding to total quantity produced
         in a month */

      obj[0]   = 150.0;
      lb[0]    = 0.0;
      ub[0]    = CPX_INFBOUND;
      ctype[0] = 'C';

      status = CPXnewcols (env, lp, 1, obj, lb, ub, ctype, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new columns.\n");
         goto TERMINATE;
      }
      totalindex = CPXgetnumcols (env, lp) - 1;

      /* Total quantity = sum (quantities) */

      for (p = 0; p < NUMPRODUCTS; p++) {
         rmatind[p] = varindex (m, p, USE);
         rmatval[p] = 1.0;
      }
      rmatind[NUMPRODUCTS] = totalindex;
      rmatval[NUMPRODUCTS] = -1.0;
      rhs[0]               =  0.0;
      sense[0]             = 'E';
      status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* Hardness constraints
          sum (quantity * hardness) >= 3 * total quantity
          sum (quantity * hardness) <= 6 * total quantity
      */

      for (p = 0; p < NUMPRODUCTS; p++) {
         rmatind[p] = varindex (m, p, USE);
         rmatval[p] = hardness[p];
      }
      rmatind[NUMPRODUCTS] = totalindex;
      rmatval[NUMPRODUCTS] = -3.0;
      rhs[0]               =  0.0;
      sense[0]             = 'G';
      status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      rmatval[NUMPRODUCTS] = -6.0;
      sense[0]             = 'L';
      status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* The food may never be made up of more than three oils */

      for (p = 0; p < NUMPRODUCTS; p++) {
         rmatind[p] = varindex (m, p, IS_USED);
         rmatval[p] = 1.0;
      }
      rhs[0]   = 3.0;
      sense[0] = 'L';
      status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* If product veg 1 or veg 2 is used then oil 3 must be used */

      indicator  = varindex (m, VEGOIL1, IS_USED);
      rmatind[0] = varindex (m, OIL3, USE);
      rmatval[0] = 1.0;
      status = CPXaddindconstr (env, lp, indicator, 0, 1, 20.0, 'G',
                                rmatind, rmatval, NULL);

      indicator = varindex (m, VEGOIL2, IS_USED);
      status = CPXaddindconstr (env, lp, indicator, 0, 1, 20.0, 'G',
                                rmatind, rmatval, NULL);

      if ( status ) {
         fprintf (stderr, "Could not add new indicator constraint.\n");
         goto TERMINATE;
      }

      /* We can store each product from one month to the next,
         starting with a stock of 500 tons */

      for (p = 0; p < NUMPRODUCTS; p++) {
         int n = 0;
         if ( m != 0 ) {
            rmatind[n]   = varindex (m-1, p, STORE); /* stored last month */
            rmatval[n++] = 1.0;
            rmatind[n]   = varindex (m, p, BUY);     /* bought this month */
            rmatval[n++] = 1.0;
            rmatind[n]   = varindex (m, p, USE);     /* used this month */
            rmatval[n++] = -1.0;
            rmatind[n]   = varindex (m, p, STORE);   /* stored this month */
            rmatval[n++] = -1.0;
            rhs[0]       = 0.0;
            sense[0]     = 'E';
         }
         else {
            rmatind[n]   = varindex (m, p, BUY);   /* bought this month */
            rmatval[n++] = 1.0;
            rmatind[n]   = varindex (m, p, USE);   /* used this month */
            rmatval[n++] = -1.0;
            rmatind[n]   = varindex (m, p, STORE); /* stored this month */
            rmatval[n++] = -1.0;
            rhs[0]       = -500.0;
            sense[0]     = 'E';
         }
         status = CPXaddrows (env, lp, 0, 1, n, rhs,
                              sense, rmatbeg, rmatind, rmatval,
                              NULL, NULL);
         if ( status ) {
            fprintf (stderr, "Could not add new rows.\n");
            goto TERMINATE;
         }
      }
   }

 TERMINATE:

   free_and_null ((char **)&obj);
   free_and_null ((char **)&lb);
   free_and_null ((char **)&ub);
   free_and_null ((char **)&ctype);
   free_and_null ((char **)&rmatind);
   free_and_null ((char **)&rmatval);

   return (status);

}  /* END buildmodel */
예제 #28
0
파일: TP.cpp 프로젝트: peter3110/tp-io
int main(int argc, char **argv) { 

    char ejes[100];
    char labels[100];
    char test[100];

    archivoInput          = argv[1];
    randomness            = argv[2];
    porcentajeParticiones = atof(argv[3]);
    algoritmo             = argv[4];
    epsilonClique         = atof(argv[5]);
    epsilonAgujero        = atof(argv[6]);
    numeroDeModelo        = atoi(argv[7]);
    RECORRIDO_ARBOL       = atoi(argv[8]);
    VARIABLE_CORTE        = atoi(argv[9]);
    semilla               = atoi(argv[10]);

    srand(semilla);

    if(not freopen(archivoInput.c_str(), "r", stdin)){
        cout << "No pude abrir archivo: " << archivoInput << endl;
        return 1;
    }

    sprintf(ejes, "ejes.out");
    sprintf(labels, "labels.out");
    if(randomness == "notrandom") { 
        sprintf(test, "%s%s", argv[1], argv[2]);
    }
    else if (randomness == "random") {
        sprintf(test, "%s%s", argv[1], argv[3]);
    }
    else{
        cout << "Paramtros mal introducidos" << endl;
        return 0;
    }

    read(randomness); // cada elemento de la particion conformado por un unico nodo

    // Le paso por parametro el algoritmo a implementar: bb = branch and bound, cb = cut and branch
    if(algoritmo != "bb" && algoritmo != "cb") {
        cout << "Error introduciendo parametro de algoritmo a ser aplicado " << endl;
        return 0;
    }

    // ==============================================================================================

    // Genero el problema de cplex.
    int status;
    // Creo el entorno.
    CPXENVptr env = CPXopenCPLEX(&status); // Puntero al entorno.
    CPXLPptr lp; // Puntero al LP
     
    if (env == NULL) {
        cerr << "Error creando el entorno" << endl;
        exit(1);
    }

    ///Iniciio el reloj
    CPXgettime(env, &inittime);
        
    // Creo el LP.
    lp = CPXcreateprob(env, &status, "instancia coloreo de grafo particionado");
     
    if (lp == NULL) {
        cerr << "Error creando el LP" << endl;
        exit(1);
    }

    // Definimos las variables. En total, son P + N*P variables ( las W[j] y las X[i][j] )
    int cantVariables = P + N*P;
    double *ub, *lb, *objfun; // Cota superior, cota inferior, coeficiente de la funcion objetivo.
    char *xctype, **colnames; // tipo de la variable , string con el nombre de la variable.
    ub       = new double[cantVariables]; 
    lb       = new double[cantVariables];
    objfun   = new double[cantVariables];
    xctype   = new char[cantVariables];
    colnames = new char*[cantVariables];

    for (int i = 0; i < cantVariables; i++) {
        ub[i] = 1.0; // seteo upper y lower bounds de cada variable
        lb[i] = 0.0;
        if(i < P) {  // agrego el costo en la funcion objetivo de cada variables
            objfun[i] = 1;  // busco minimizar Sum(W_j) para j=0..P (la cantidad de colores utilizados).
        }
        else {
            objfun[i] = 0;  // los X[i][j] no contribuyen a la funcion objetivo
        }
        xctype[i] = 'B';  // 'C' es continua, 'B' binaria, 'I' Entera.
        colnames[i] = new char[10];
    }

    /* Defino el tipo de variable BoolVarMatrix, que sera utilizado en la resolucion
     * recordar: X_v_j = 1 sii el color j es asignado al vertice v
     * recordar: W_j = 1 si X_v_j = 1 para al menos un vertice v
    */
    for(int j=0; j<P; j++) {
        sprintf(colnames[j], "W_%d", j);
        // cout << colnames[j] << endl;
    }
    for(int i=0; i<N; i++) {
        for(int j=0; j<P; j++) {
            sprintf(colnames[xijIndice(i,j)], "X_%d_%d", i, j);
            // cout << colnames[xijIndice(i,j)] << endl;
        }
    }


    // ========================== Agrego las columnas. =========================== //
    if(algoritmo == "cb"){
        // si quiero resolver la relajacion, agregar los cortes y despues resolver el MIP, no agrego xctype
        status = CPXnewcols(env, lp, cantVariables, objfun, lb, ub, NULL, colnames);
    }
    else if (algoritmo == "bb"){
        // si quiero hacer MIP, directamente, con brancha and bound, agrego xctype
        status = CPXnewcols(env, lp, cantVariables, objfun, lb, ub, xctype, colnames);
    }
    else {
        cout << "Error: parametro de algoritmo bb/cb mal introducido" << endl;
        return 0;
    }
    
    if (status) {
        cerr << "Problema agregando las variables CPXnewcols" << endl;
        exit(1);
    }
    
    // Libero las estructuras.
    for (int i = 0; i < cantVariables; i++) {
        delete[] colnames[i];
    }

    delete[] ub;
    delete[] lb;
    delete[] objfun;
    delete[] xctype;
    delete[] colnames;

    // CPLEX por defecto minimiza. Le cambiamos el sentido a la funcion objetivo si se quiere maximizar.
    // CPXchgobjsen(env, lp, CPX_MAX);

    // ================================================================================================ //
    // ===================================== Restricciones ============================================ //

    // i)   Asigno exactamente un color a exactamente un vertice de cada particion ( P restricciones )
    // ii)  Dos vertices adyacentes no pueden tener el mismo color ( E restricciones )
    // iii) Los W_j estan bien armados, en funcion de X_v_j ( 2*P restricciones )

    // ccnt = numero nuevo de columnas en las restricciones.
    // rcnt = cuantas restricciones se estan agregando.
    // nzcnt = # de coeficientes != 0 a ser agregados a la matriz. Solo se pasan los valores que no son cero.
 
    int ccnt = 0;
    int rcnt;
    if(numeroDeModelo == 0){
        rcnt = P + (E*P)/2 + 2*P;  // Cota maxima a la cantidad de restricciones
    }
    else{
        rcnt = P + (E*P)/2 + N*P;
    }
                                    // (E/2 porque en la entrada se supone que en la entrada me pasan 2 veces cada eje)
    int nzcnt = 0;  // al ppio es cero (para cada valor q agrego, lo voy a incrementar en 1)

    char sense[rcnt]; // Sentido de la desigualdad. 'G' es mayor o igual y 'E' para igualdad, 'L' menor o igual

    double *rhs = new double[rcnt]; // Termino independiente de las restricciones.
    int *matbeg = new int[rcnt];    //Posicion en la que comienza cada restriccion en matind y matval.
    int *matind = new int[rcnt*cantVariables];       // Array con los indices de las variables con coeficientes != 0 en la desigualdad.
    double *matval = new double[rcnt*cantVariables]; // Array que en la posicion i tiene coeficiente ( != 0) de la variable matind[i] en la restriccion.

    // CPLEX va a leer hasta la cantidad nzcnt que le pasemos.
    int cantRestricciones = 0;  // r = numero de restriccion

    // i) P restricciones - exactamente un color a cada vertice (una restriccion por cada particion)
    for(int particion = 0; particion < P; particion++) {
        matbeg[cantRestricciones] = nzcnt;
        rhs[cantRestricciones]    = 1;
        sense[cantRestricciones]  = 'E';
		for(int e = 0; e < S[particion].size(); e++) {
			for(int color = 0; color < P; color++) {
				matind[nzcnt] = xijIndice(S[particion][e], color);
				matval[nzcnt] = 1;
				nzcnt++;
			}
		}
        cantRestricciones++;
    }

	// ii) Cota superior de (E*P)/2 restricciones mas
	// Una para cada par de vecinos i j, para cada color pero solo cuando i < j, y estan en distinta particion
	for(int i = 0; i < N; i++) {
		for(int j = i + 1; j < N; j++) { 
			if(M[i][j] == 1 and dameParticion(i) != dameParticion(j)){
				for(int color = 0; color < P; color++) {
					matbeg[cantRestricciones] = nzcnt;
					rhs[cantRestricciones]    = 1;
					sense[cantRestricciones]  = 'L';

					matind[nzcnt] = xijIndice(i,color);
					matval[nzcnt] = 1;
					nzcnt++;
					matind[nzcnt] = xijIndice(j,color);
					matval[nzcnt] = 1;
					nzcnt++;
					cantRestricciones++;
				}
			}
		}
    }

    if(numeroDeModelo == 0){

        // iii) 2*P restricciones mas
		// - P * wj + sigma xij <= 0
        for(int k=0; k<P; k++) {  // para cada color
            matbeg[cantRestricciones] = nzcnt;
            rhs[cantRestricciones] = 0;
            sense[cantRestricciones] = 'L';
            matind[nzcnt] = k;
            matval[nzcnt] = -1 * P;
            nzcnt++;
            for(int i=0; i<N; i++) {
                matind[nzcnt] = xijIndice(i,k);
                matval[nzcnt] = 1;
                nzcnt++;
            }
            cantRestricciones++;
        }

		//  - wj + sigma xij >= 0
        for(int k=0; k<P; k++) {
            matbeg[cantRestricciones] = nzcnt;
            rhs[cantRestricciones] = 0;
            sense[cantRestricciones] = 'G';
            matind[nzcnt] = k;
            matval[nzcnt] = -1;
            nzcnt++;
            for(int i=0; i<N; i++) {
                matind[nzcnt] = xijIndice(i,k);
                matval[nzcnt] = 1;
                nzcnt++;
            }
            cantRestricciones++;
        }

    }
    else{
		// iii) N*P restricciones mas
		// -wj + xij <= 0
        for(int color = 0; color < P; color++) { 
            for(int i = 0; i < N; i++) {
                matbeg[cantRestricciones] = nzcnt;
                rhs[cantRestricciones] = 0;
                sense[cantRestricciones] = 'L';
                matind[nzcnt] = color;
                matval[nzcnt] = -1;
                nzcnt++;
                matind[nzcnt] = xijIndice(i, color);
                matval[nzcnt] = 1;
                nzcnt++;
                cantRestricciones++;
            }
        }
    }

    //Actualizo rcnt.
    rcnt = cantRestricciones;


    // ===================================================================================================
    
    // Agregamos las restricciones al lp.
    status = CPXaddrows(env, lp, ccnt, rcnt, nzcnt, rhs, sense, matbeg, matind, matval, NULL, NULL);

    if (status) {
        cerr << "Problema agregando restricciones." << endl;
        exit(1);
    }
            
    delete[] rhs;
    delete[] matbeg;
    delete[] matind;
    delete[] matval;


    // ============================================================================================== //
    // ================================== Optimizamos el problema. ================================== //
    // Seteo de algunos parametros.

    // Para desactivar la salida poner CPX_OFF.
    status = CPXsetintparam(env, CPX_PARAM_SCRIND, CPX_ON);
        
    if (status) {
        cerr << "Problema seteando SCRIND" << endl;
        exit(1);
    }
        
    // Setea el tiempo limite de ejecucion.
    status = CPXsetdblparam(env, CPX_PARAM_TILIM, TIEMPO_LIMITE);  // setear limite de tiempo en 3600 !!!!!!!
    
    if (status) {
        cerr << "Problema seteando el tiempo limite" << endl;
        exit(1);
    }
 
    // Escribimos el problema a un archivo .lp.
    // status = CPXwriteprob(env, lp, "test.lp", NULL);

    if (status) {
        cerr << "Problema escribiendo modelo" << endl;
        exit(1);
    }
        
    // Seteamos algunos parametros para resolver con branch and bound
    CPXsetintparam(env, CPX_PARAM_MIPSEARCH, CPX_MIPSEARCH_TRADITIONAL);

    // Para facilitar la comparación evitamos paralelismo:
    CPXsetintparam(env, CPX_PARAM_THREADS, 1);

    //Para que no se adicionen planos de corte:
    CPXsetintparam(env,CPX_PARAM_EACHCUTLIM, 0);
    CPXsetintparam(env, CPX_PARAM_FRACCUTS, -1);
    CPXsetintparam(env, CPX_PARAM_LANDPCUTS, -1);

    // Para que no haga preprocesamientos
    CPXsetintparam(env, CPX_PARAM_PRESLVND, -1);
    CPXsetintparam(env, CPX_PARAM_REPEATPRESOLVE, 0);
    CPXsetintparam(env, CPX_PARAM_RELAXPREIND, 0);
    CPXsetintparam(env, CPX_PARAM_REDUCE, 0);

    // Recorrido del arbol
    CPXsetintparam(env, CPX_PARAM_NODESEL, RECORRIDO_ARBOL);

    // Seleccion de variable
    CPXsetintparam(env, CPX_PARAM_VARSEL, VARIABLE_CORTE); 

    CPXgettime(env, &endtime);
    tiempoPreparar = endtime - inittime;
    inittime = endtime;

    // =========================================================================================================
    // resuelvo con cut and branch (con los cortes definidos por nosotros) o con branch and bound (y sin cortes)
    // =========================================================================================================
    if(algoritmo == "cb") {
        
        // while (algo) ... resolver el lp, chequear si la restr inducida por la clique actual es violada. Seguir
        //cout << "antes" << endl;
        
        for(int ciclocb=0; ciclocb<CANT_CICLOS_CB; ciclocb++) {
            status = CPXlpopt(env, lp);
        
            //cout << "despues" << endl;
            double objval;
            status = CPXgetobjval(env, lp, &objval);
            // Aca, deberia agregar los cortes requeridos, en funcion de "cliques" y "objval"

            // mostrameValores(env, lp);

            double *sol = new double[cantVariables];
            CPXgetx(env, lp, sol, 0, cantVariables - 1);

            //CPXwriteprob (env, lp, "antesDeClique.lp", "LP");
            // BUSCAR Y AGREGAR CLIQUE
            vector < vector<int> > agregados;
            for(int color=0; color<P; color++) {
                for(int i=0; i<CANT_RESTR_CLIQUES; i++) {
                    bool iteracionRandom = (i!=0);
                    vector<int> clique = dameClique(sol, color, iteracionRandom);
                    sort(clique.begin(), clique.end());
                    bool incluido = find(agregados.begin(), agregados.end(), clique) != agregados.end();

                    if (not incluido and not clique.empty()) {
                        agregados.push_back(clique);
                        agregarRestriccionClique(env, lp, clique);
                        cantidadCortesClique++;
                        // cout << "AGREGO RESTRICCION DE CLIQUE de random " << iteracionRandom << " y de color #"<< color << ": ";
                        // for(int j=0; j<clique.size(); j++) {
                        //     cout << clique[j] << " ";
                        // }
                        // cout << endl;
                    }
                }
            }

            // BUSCAR Y AGREGAR AGUJERO
            agregados.clear();
            for(int color=0; color<P; color++) {
                for(int i=0; i<CANT_RESTR_AGUJEROS; i++) {
                    vector<int> agujero = dameAgujero(sol, color);

                    bool incluido = find(agregados.begin(), agregados.end(), agujero) != agregados.end();
                    if (not incluido and not agujero.empty()) {
                        agregados.push_back(agujero);
                        agregarRestriccionAgujero(env, lp, agujero);
                        cantidadCortesAgujero++;
                        // cout << "AGREGO RESTRICCION DE AGUJERO de color #"<< color << ": ";
                        // for(int j=0; j<agujero.size(); j++) {
                        //     cout << agujero[j] << " ";
                        // }
                        // cout << endl;
                    }
                }
            }


            delete [] sol;
        }
        
        // CPXwriteprob (env, lp, "lpCB.lp", "LP");

        ///Cuando salimos, pasamos a binaria y corremos un branch and bound
        char *ctype = new char[cantVariables];
        for (int i = 0; i < cantVariables; i++) {
            ctype[i] = 'B';
        }

        // cout << "Antes cambiar tipo" << endl;
        status = CPXcopyctype (env, lp, ctype);
        // cout << "Despues cambiar tipo" << endl;
        delete[] ctype;

        CPXgettime(env, &endtime);
        tiempoCutAndBranch = endtime - inittime;
        inittime = endtime;
    }

    ///Corremos el BB, ya sea porque esto es lo que queriamos originalemente, o porque terminamos con los planos de corte

    // cout << "ANTES" << endl;
    //CPXwriteprob (env, lp, "antesDeMip.lp", "LP");
    CPXmipopt(env,lp);
    // cout << "DESPUES" << endl;

    CPXgettime(env, &endtime);
    tiempoBranchAndBound = endtime - inittime;
    // inittime = endtime;
    
    status = CPXgettime(env, &endtime);

    if (status) {
        cerr << "Problema optimizando CPLEX" << endl;
        exit(1);
    }

    // Chequeamos el estado de la solucion.
    int solstat;
    char statstring[510];
    CPXCHARptr p;
    solstat = CPXgetstat(env, lp);
    p = CPXgetstatstring(env, solstat, statstring);
    string statstr(statstring);
    cout << endl << "Resultado de la optimizacion: " << statstring << endl;
    
    if(solstat!=CPXMIP_OPTIMAL && solstat!=CPXMIP_OPTIMAL_TOL && solstat!=CPXMIP_NODE_LIM_FEAS && solstat!=CPXMIP_TIME_LIM_FEAS){
        cout << "No hay solucion" << endl;
    }
    else{
        double objval;
        status = CPXgetobjval(env, lp, &objval);
            
        if (status) {
            cerr << "Problema obteniendo valor de mejor solucion." << endl;
            exit(1);
        }

        cout << "Datos de la resolucion: " << "\t" << objval << "\t" << tiempoPreparar + tiempoCutAndBranch + tiempoBranchAndBound << endl; 

        cout << "Tiempo en preparar: " << "\t" << tiempoPreparar << endl; 
        cout << "Tiempo en CB: " << "\t" << tiempoCutAndBranch << endl; 
        cout << "Tiempo en BB: " << "\t" << tiempoBranchAndBound << endl; 

        // Tomamos los valores de todas las variables. Estan numeradas de 0 a n-1.
        double *sol = new double[cantVariables];
        status = CPXgetx(env, lp, sol, 0, cantVariables - 1);

        if (status) {
            cerr << "Problema obteniendo la solucion del LP." << endl;
            exit(1);
        }

        impresionModelo(env, lp);

            
        // Solo escribimos las variables distintas de cero (tolerancia, 1E-05).
        //solfile << "Status de la solucion: " << statstr << endl;
        // for(int j=0; j<P; j++) {
        //     if(sol[j] > TOL) {
        //         cout << "W_" << j << " = " << sol[j] << endl;
        //     }
        // }
        // for(int i=0; i<N; i++) {
        //     for(int j=0; j<P; j++) {
        //         if(sol[P + P*i + j] > TOL) {
        //             cout << "X_" << i << "_" << j << " = " << sol[P+P*i+j] << endl;
        //         }
        //     }
        // }
        
        //solfile.close();

        // ==================== Devuelvo el grafo resultante coloreado, para graficar! ====================== //
        // ofstream streamEjes, streamLabels;
        //ofstream streamParticiones;
        // Tomamos los valores de la solucion y los escribimos a un archivo.
        // streamEjes.open(ejes);
        // for(int v1=0; v1<N; v1++) {
        //     for(int v2=v1+1; v2<N; v2++) {
        //         if (M[v1][v2] == 1) { 
        //             streamEjes << v1+1 << " " << v2+1 << endl;
        //         }
        //     }
        // } streamEjes.close();
        // cout << ejes << endl;
        
        // streamLabels.open(labels);
        // bool estaColoreado;
        // for(int v=0; v<N; v++){
        //     estaColoreado = false;
        //     for(int j=0; j<P; j++){
        //         if (sol[P + P*v + j] == 1) {
        //             streamLabels << v+1 << " " << j+1 << endl;
        //             estaColoreado = true;
        //         }
        //     }
        //     if(not estaColoreado) {
        //         streamLabels << v+1 << " " << 0 << endl;
        //     }
        // }
        // streamLabels.close();

        // delete [] sol;
    }

    return 0;
}