Esempio n. 1
0
/* Set Cplex parameter */
void SSCplex::SetParameters( void ){

	/* Set limit to emphasize feasibility */    
	status = CPXsetintparam (env, CPX_PARAM_MIPEMPHASIS, MIPEMPH);
	if ( status ) 
	    stop("Failure to set parameter emphasizing feasibility.\n", status);
    
	/* Set limit on number of integer solutions */    
	 status = CPXsetintparam (env, CPX_PARAM_INTSOLLIM, NUMINTSOL);
	if ( status ) 
	    stop("Failure to set limit on number of integer solutions.\n", status);
	
	/* Set time to CPU time */
	status = CPXsetintparam (env, CPX_PARAM_CLOCKTYPE, CLOCKTYPE);
	if ( status ) 
		stop("Failure to set clock type.\n", status);

	/* Set limit on time */    
	status = CPXsetdblparam (env, CPX_PARAM_TILIM, TIMELIMIT);
	if ( status ) 
		stop("Failure to set limit on time.\n", status);
  
	/* Set limit on number of nodes */    
	status = CPXsetintparam (env, CPX_PARAM_NODELIM, NUMNODE);
	if ( status ) 
	    stop("Failure to set limit on number of nodes.\n", status);
 
	/* Set MIP node selection strategy */    
	status = CPXsetintparam (env, CPX_PARAM_NODESEL, NODESEL);
	if ( status ) 
		stop("Failure to set node selection strategy.\n", status);
  
	/* Set MIP variable selection strategy */    
	status = CPXsetintparam (env, CPX_PARAM_VARSEL, VARSEL);
	if ( status ) 
		stop("Failure to set variable selection strategy.\n", status);

	/* Set MIP branching direction */    
	status = CPXsetintparam (env, CPX_PARAM_BRDIR, BRDIR);
	if ( status ) 
		stop("Failure to set branching direction.\n", status);
  
	/* Set backtracking tolerance */    
	status = CPXsetdblparam (env, CPX_PARAM_BTTOL, BACKTRACK);
	if ( status ) 
		stop("Failure to set backtracking tolerance.\n", status);


	/* Set algorithm to be used on the initial node */    
	status = CPXsetintparam (env, CPX_PARAM_STARTALG, STARTALG);
	if ( status ) 
	    stop("Failure to set the start-algorithm.\n", status);

	/* Set algorithm to be used on subsequent nodes */    
	status = CPXsetintparam (env, CPX_PARAM_SUBALG, SUBALG);
	if ( status ) 
	    stop("Failure to set the start-algorithm.\n", status);
  
}
void PartitionedColoringModel::setParameters() {
	int status;
	
	// Seteo de algunos parametros.
	// Para desactivar la salida poern CPX_OFF.
	status = CPXsetintparam(this->cplexEnvironment, CPX_PARAM_SCRIND, CPX_OFF);

	if(status) {
		cerr << "Problema seteando SCRIND" << endl;
		exit(1);
	}

	// Por ahora no va a ser necesario, pero mas adelante si. Setea el tiempo
	// limite de ejecucion.
	if(timeout != 0) {
		status = CPXsetdblparam(this->cplexEnvironment, CPX_PARAM_TILIM, timeout);
	} else {
		status = CPXsetdblparam(this->cplexEnvironment, CPX_PARAM_TILIM, 20);
	}

	if(status) {
		cerr << "Problema seteando el tiempo limite" << endl;
		exit(1);
	}
	
	// Para que haga Branch & Bound:
	CPXsetintparam(this->cplexEnvironment, CPX_PARAM_MIPSEARCH, CPX_MIPSEARCH_TRADITIONAL);
	
	// Para facilitar la comparación evitamos paralelismo:
	CPXsetintparam(this->cplexEnvironment, CPX_PARAM_THREADS, 1);

	// Para que no se adicionen planos de corte:
	CPXsetintparam(this->cplexEnvironment, CPX_PARAM_EACHCUTLIM, 0);
	CPXsetintparam(this->cplexEnvironment, CPX_PARAM_FRACCUTS, -1);
	
	// Deshabilitamos preprocesamientos
	CPXsetintparam(this->cplexEnvironment, CPX_PARAM_PRESLVND, -1);
	CPXsetintparam(this->cplexEnvironment, CPX_PARAM_REPEATPRESOLVE, 0);
	CPXsetintparam(this->cplexEnvironment, CPX_PARAM_RELAXPREIND, 0);
	CPXsetintparam(this->cplexEnvironment, CPX_PARAM_REDUCE, 0);
	CPXsetintparam(this->cplexEnvironment, CPX_PARAM_LANDPCUTS, -1);
}
Esempio n. 3
0
long GenModelCplex::SetDirectParam(int whichparam, genmodel_param value, string type, string message)
{
    int status = 0;
    if (type == "dbl")
        status = CPXsetdblparam(static_cast<CplexData*>(solverdata)->env, whichparam, value.dblval);
    else if (type == "long")
        status = CPXsetintparam(static_cast<CplexData*>(solverdata)->env, whichparam, value.longval);
    else if (type == "str")
        status = CPXsetstrparam(static_cast<CplexData*>(solverdata)->env, whichparam, value.strval);
    if (status)
        return ThrowError(getcplexerror(static_cast<CplexData*>(solverdata)->env, status) + string(". ") + message);

    return 0;
}
Esempio n. 4
0
OptSolutionData* CPLEXRunSolver(int ProbType) {
	OptSolutionData* NewSolution = NULL;
	int Status = 0;
	if (ProbType == LP) {
		Status = CPXsetintparam (CPLEXenv, CPX_PARAM_LPMETHOD, CPX_ALG_AUTOMATIC);
		if (Status) {
			FErrorFile() << "Failed to set the optimization method." << endl;
			FlushErrorFile();
			return NULL;
		}
		Status = CPXsetintparam (CPLEXenv, CPX_PARAM_SIMDISPLAY, 0);
		if (Status) {
			FErrorFile() << "Failed to set the optimization method." << endl;
			FlushErrorFile();
			return NULL;
		}
		Status = CPXchgprobtype(CPLEXenv, CPLEXModel, CPXPROB_LP);
		Status = CPXlpopt(CPLEXenv, CPLEXModel);
	} else if(ProbType == MILP || ProbType == MIQP) {
		//Setting the bound tightening on high
		Status = CPXsetintparam (CPLEXenv, CPX_PARAM_BNDSTRENIND, 1);
		if (Status) {
			FErrorFile() << "Failed to set the optimization method." << endl;
			FlushErrorFile();
			return NULL;
		}
		//Setting tolerance to 1e-9 instead of 1e-6
		double tolerance = atof(GetParameter("Solver tolerance").data());
		Status = CPXsetdblparam(CPLEXenv,CPX_PARAM_EPRHS, tolerance);
		if (Status) {
			FErrorFile() << "Failed to set the optimization method." << endl;
			FlushErrorFile();
			return NULL;
		}
		Status = CPXsetdblparam(CPLEXenv,CPX_PARAM_EPINT, tolerance);
		if (Status) {
			FErrorFile() << "Failed to set the optimization method." << endl;
			FlushErrorFile();
			return NULL;
		}
		//Deactivates all messages from MIP solver
		Status = CPXchgprobtype(CPLEXenv, CPLEXModel, CPXPROB_MILP);
		Status = CPXmipopt (CPLEXenv, CPLEXModel);
	} else if(ProbType == QP) {
		Status = CPXqpopt (CPLEXenv, CPLEXModel);
	}
	if (Status ) {
		cout << "Failed to optimize LP." << endl;
		return NULL;
	}
	int Temp = CPXgetstat (CPLEXenv, CPLEXModel);
	NewSolution = new OptSolutionData;
	if (Temp == CPX_STAT_UNBOUNDED) {
		cout << "Model is unbounded" << endl;
		FErrorFile() << "Model is unbounded" << endl;
		FlushErrorFile();
		NewSolution->Status = UNBOUNDED;
		return NewSolution;
	} else if (Temp == CPX_STAT_INFEASIBLE) {
		cout << "Model is infeasible" << endl;
		FErrorFile() << "Model is infeasible" << endl;
		FlushErrorFile();
		NewSolution->Status = INFEASIBLE;
		return NewSolution;
	} else if (Temp == CPX_STAT_INForUNBD ) {
		cout << "Model is infeasible or unbounded" << endl;
		FErrorFile() << "Model is infeasible or unbounded" << endl;
		FlushErrorFile();
		NewSolution->Status = INFEASIBLE;
		return NewSolution;
	} else {
		NewSolution->Status = SUCCESS;
	}

	int NumberColumns = CPXgetnumcols (CPLEXenv, CPLEXModel);
	int NumberRows = CPXgetnumrows (CPLEXenv, CPLEXModel);
	NewSolution->NumVariables = NumberColumns;
	NewSolution->SolutionData.resize(NumberColumns);

	double* x = new double[NumberColumns];
	
	if (ProbType == MILP || ProbType == MIQP) {
		Status = CPXgetmipobjval (CPLEXenv, CPLEXModel, &(NewSolution->Objective));
		Status = CPXgetmipx (CPLEXenv, CPLEXModel, x, 0, NumberColumns-1);
	} else {
		Status = CPXsolution(CPLEXenv,CPLEXModel,NULL,&(NewSolution->Objective),x,NULL,NULL,NULL);
	}
	
	if ( Status ) {
		cout << "Failed to obtain objective value." << endl;
		delete [] x;
		NewSolution->Status = INFEASIBLE;
		return NewSolution;
	}

	cout << "Objective value: " << NewSolution->Objective << endl;
	/*
	string* StrNames = new string[NumberColumns];
	char** Names = new char*[NumberColumns];
	char* NameStore = new char[7*NumberColumns];
	int Surplus = 0;

	Status = CPXgetcolname(CPLEXenv, CPLEXModel, Names, NameStore, 7*NumberColumns, &Surplus, 0, NumberColumns-1);
	if (Status) {
		FErrorFile() << "Failed to get column names." << endl;
		FlushErrorFile();
		delete [] StrNames;
		delete [] Names;
		delete [] NameStore;
		delete [] x;
		delete NewSolution;
		return NULL;
	}
	*/
	for (int i=0; i < NumberColumns; i++) {
		//StrNames[i].assign(Names[i]);
		//StrNames[i] = StrNames[i].substr(1, StrNames[i].length()-1);
		//NewSolution->SolutionData[atoi(StrNames[i].data())-1] = x[i];
		NewSolution->SolutionData[i] = x[i];
	}
	/*
	delete [] StrNames;
	delete [] Names;
	delete [] NameStore;
	*/
	delete [] x;

	return NewSolution;
}
extern int solve_allocation(int nodeSize, int windowSize, int timeout, 
			sched_nodeinfo_t *node_array, 
			solver_job_list_t *job_array)
{
	solver_job_list_t *solver_job_ptr;
	int solstat;
	int n = windowSize, m = nodeSize;
	double objval;
	double *x = NULL;
	double *pi = NULL;
	double *slack = NULL;
	double *dj = NULL;
	double *obj = NULL;
	int NUMCOLS = n * (2 * m + 2);

	CPXENVptr env = NULL;
	CPXLPptr lp = NULL;
	int status = 0;
	int i, j, k;
	int cur_numrows, cur_numcols;
	char envstr[256] = "ILOG_LICENSE_FILE=/home/seren/ILOG/CPLEX_Studio_AcademicResearch122/licenses/access.ilm";

	if ( envstr != NULL ) {
		CPXputenv (envstr);
	}

	env = CPXopenCPLEX (&status);
	if ( env == NULL ) {
		char  errmsg[1024];
		CPXgeterrorstring (env, status, errmsg);
		fprintf (stderr, "%s", errmsg);
		goto TERMINATE;
	}

	status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
	if ( status ) {
		goto TERMINATE;
	}

	status = CPXsetintparam (env, CPX_PARAM_DATACHECK, CPX_ON);
	if ( status ) {
		goto TERMINATE;
	}

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

	if ( lp == NULL ) {
		goto TERMINATE;
	}

	obj = (double*)malloc(NUMCOLS * sizeof(double));
	status = CPXsetdblparam(env,CPX_PARAM_TILIM,5);
	status = populatebynonzero (env, lp, nodeSize, windowSize, timeout, node_array, job_array);

	if ( status ) {
		fprintf (stderr, "Failed to populate problem.");
		goto TERMINATE;
	}

	status = CPXlpopt (env, lp);
	if ( status ) {
		fprintf (stderr, "Failed to optimize LP.");
		goto TERMINATE;
	}

	cur_numrows = CPXgetnumrows (env, lp);
	cur_numcols = CPXgetnumcols (env, lp);
	x = (double *) malloc (cur_numcols * sizeof(double));
	slack = (double *) malloc (cur_numrows * sizeof(double));
	dj = (double *) malloc (cur_numcols * sizeof(double));
	pi = (double *) malloc (cur_numrows * sizeof(double));

	if ( x == NULL ||
		slack == NULL ||
		dj    == NULL ||
		pi    == NULL   ) {
		status = CPXERR_NO_MEMORY;
		goto TERMINATE;
	}

	status = CPXsolution (env, lp, &solstat, &objval, x, pi, slack, dj);
	if ( status ) {
		goto TERMINATE;
	}

	/*debug3("\nSolution status = %d\n", solstat);*/
	printf("Solution value  = %f\n\n", objval);

	/*
	for (i = 0; i < cur_numrows; i++) {
		printf ("Row %d:  Slack = %10f  Pi = %10f\n", i, slack[i], pi[i]);
	}
	
	for (j = 0; j < cur_numcols; j++) {
		printf ("Column %d:  Value = %10f  Reduced cost = %10f\n",
		  j, x[j], dj[j]);
	}
	*/
	/*debug3("sending solution results to slurm");*/
/*
	for (j = 0; j < windowSize; j++) {
		if (x[j] > 0) {
			solver_job_ptr = &job_array[j];
			solver_job_ptr->node_bitmap = (bitstr_t *) bit_alloc (node_record_count);
			solver_job_ptr->job_ptr->details->req_node_bitmap = (bitstr_t *) bit_alloc (node_record_count);
			solver_job_ptr->onnodes = (int *) xmalloc (sizeof(int)*node_record_count);
			solver_job_ptr->job_ptr->details->req_node_layout = (int *)xmalloc(sizeof(int) * node_record_count);
			solver_job_ptr->job_ptr->details->req_node_bitmap = (bitstr_t *) bit_alloc (node_record_count);
			for (i = 0; i < nodeSize; i++) {
				k = (1 + i) * windowSize + j;
				if (x[k] > 0) {
					bit_set (solver_job_ptr->node_bitmap, (bitoff_t) (i));
					bit_set (solver_job_ptr->job_ptr->details->req_node_bitmap, (bitoff_t) (i));		
					node_array[i].rem_cpus -= x[k];
					node_array[i].rem_gpus -= solver_job_ptr->gpu;
					solver_job_ptr->onnodes[i] = x[k]; 
					solver_job_ptr->job_ptr->details->req_node_layout[i] = solver_job_ptr->onnodes[i]; 
					solver_job_ptr->alloc_total += x[k];
				}
			}
		} else
			job_array[j].alloc_total = 0;
	} 
*/
/*	status = CPXwriteprob (env, lp, "lpex1.lp", NULL);
	if ( status ) {
		fprintf (stderr, "Failed to write LP to disk.");
		goto TERMINATE;
	}
*/
TERMINATE:

	free_and_null ((char **) &x);
	free_and_null ((char **) &slack);
	free_and_null ((char **) &dj);
	free_and_null ((char **) &pi);

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

	if ( env != NULL ) {
		status = CPXcloseCPLEX (&env);
		if ( status ) {
			char  errmsg[1024];
			fprintf (stderr, "Could not close CPLEX environment.");
			CPXgeterrorstring (env, status, errmsg);
			fprintf (stderr, "%s", errmsg);
		}
	}     
	
	return (status);
}
void SolverInterfaceCpx::setGapTol(double tol)
{
	CPXsetdblparam(cpx_->getEnvironmentPtr(), CPX_PARAM_EPGAP, CoinMin(tol,1.0));
}
void SolverInterfaceCpx::setTimeLimit(double sec)
{
	CPXsetdblparam(cpx_->getEnvironmentPtr(), CPX_PARAM_TILIM, CoinMin(sec,1.0e+75));
}
Esempio n. 8
0
void mexFunction(
    int nlhs, mxArray *plhs[],
    int nrhs, const mxArray *prhs[]
)
{
  int display=0, i=0;
  long *lpenv=NULL ;
  CPXENVptr     env = NULL;
  int           status ;
  double value ;
  char param_name[128] ;
  int param_code=-1, dblfound=0, strfound=0 ;
  
  if (nrhs > 7 || nrhs < 1) {
    mexErrMsgTxt("Usage: [how] "
		 "= lp_set_param(lpenv, param_name, value, display)");
    return;
  }
  switch (nrhs) {
  case 4:
    if (mxGetM(prhs[3]) != 0 || mxGetN(prhs[3]) != 0) {
      if (!mxIsNumeric(prhs[3]) || mxIsComplex(prhs[3]) 
	  ||  mxIsSparse(prhs[3])
	  || !(mxGetM(prhs[3])==1 && mxGetN(prhs[3])==1)) {
	mexErrMsgTxt("4th argument (display) must be "
		     "an integer scalar.");
	return;
      }
      display = *mxGetPr(prhs[3]);
    }
  case 3:
    if (mxGetM(prhs[2]) != 0 || mxGetN(prhs[2]) != 0) {
      if (!mxIsNumeric(prhs[2]) || mxIsComplex(prhs[2]) 
	  ||  mxIsSparse(prhs[2])
	  || !(mxGetM(prhs[2])==1 && mxGetN(prhs[2])==1)) {
	mexErrMsgTxt("3rd argument (value) must be "
		     "an integer scalar.");
	return;
      }
      value = *mxGetPr(prhs[2]);
    }
  case 2:
    if (mxGetM(prhs[1]) != 0 || mxGetN(prhs[1]) != 0) {
      if (mxIsNumeric(prhs[1]) || mxIsComplex(prhs[1]) 
	  ||  mxIsSparse(prhs[1]) || !mxIsChar(prhs[1])
	  || !(mxGetM(prhs[1])==1) && mxGetN(prhs[1])>=1) {
	mexErrMsgTxt("2nd argument (param) must be "
		     "a string.");
	return;
      }
      mxGetString(prhs[1], param_name, 128);
    }
  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_set_param(lpenv,param_name,value,disp)");
    return;
  }
  if (display>2) fprintf(STD_OUT, "argument processing finished\n") ;

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

  for (i=0; i<NUM_PARAMS; i++)
      if (strcmp(param_info[i].name, param_name)==0)
	  param_code=param_info[i].code ;

  if (display>3) 
    fprintf(STD_OUT, "(param=%s(%i), value=%f) \n", param_name, param_code, value) ;
  if (param_code==-1)
    mxErrMsgTxt("illegal parameter name") ;

  for (i=0; i<NUM_DBLPARAMS; i++)
    if (param_code==dblParams[i])
      dblfound=1 ;
  for (i=0; i<NUM_STRPARAMS; i++)
    if (param_code==strParams[i])
      strfound=1 ;
  if (dblfound==1) {
    if (display>2) 
      fprintf(STD_OUT, "calling CPXsetdblparam\n") ;
    status = CPXsetdblparam(env, param_code, value);
    if ( status ) {
      fprintf (STD_OUT, "CPXsetdblparam failed.\n");
      goto TERMINATE;
    } 
  } else if (strfound==1)
  {
	  fprintf(STD_OUT, "sorry not implemented\n") ;
  } else {
    if (display>2) 
      fprintf(STD_OUT, "calling CPXsetintparam\n") ;
    status = CPXsetintparam(env, param_code, (int)value);
    if ( status ) {
      fprintf (STD_OUT, "CPXsetintparam 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") ;
  ;
  return ;
} 
Esempio n. 9
0
int
main (int  argc,
      char *argv[])
{
   int status = 0;

   /* Declare and allocate space for the variables and arrays where
      we will store the optimization results, including the status, 
      objective value, and variable values */
   
   int    solstat;
   double objval;
   double *x = NULL;
   
   CPXENVptr env = NULL;
   CPXLPptr  lp = NULL;

   int j;
   int cur_numcols;
   int wantorig = 1;
   int nameind = 1;

   /* Check the command line arguments */

   if ( argc != 2 ) {
      if ( argc != 3         ||
           argv[1][0] != '-' ||
           argv[1][1] != 'r'   ) {
         usage (argv[0]);
         goto TERMINATE;
      }
      wantorig = 0;
      nameind = 2;
   }

   /* 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 parameter 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 != 0 ) {
      fprintf (stderr, 
               "Failure to turn on screen indicator, error %d.\n",
               status);
      goto TERMINATE;
   }

   /* Create the problem, using the filename as the problem name */

   lp = CPXcreateprob (env, &status, argv[nameind]);

   /* 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.  Note that most CPLEX routines return
      an error code to indicate the reason for failure */

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

   /* Now read the file, and copy the data into the created lp */

   status = CPXreadcopyprob (env, lp, argv[nameind], NULL);
   if ( status ) {
      fprintf (stderr,
               "Failed to read and copy the problem data.\n");
      goto TERMINATE;
   }

   if ( CPXgetnumcols (env, lp) != CPXgetnumbin (env, lp) ) {
      fprintf (stderr, "Problem contains non-binary variables, exiting\n");
      goto TERMINATE;
   }

   /* Set parameters */

   if ( wantorig ) {
      /* Assure linear mappings between the presolved and original
         models */

      status = CPXsetintparam (env, CPXPARAM_Preprocessing_Linear, 0);
      if ( status )  goto TERMINATE;

      /* Let MIP callbacks work on the original model */

      status = CPXsetintparam (env, CPXPARAM_MIP_Strategy_CallbackReducedLP,
                               CPX_OFF);
      if ( status )  goto TERMINATE;
   }

   

   status = CPXsetdblparam (env, CPXPARAM_MIP_Tolerances_MIPGap,
                            (double) 1e-6);
   if ( status )  goto TERMINATE;

   /* Turn on traditional search for use with control callbacks */

   status = CPXsetintparam (env, CPXPARAM_MIP_Strategy_Search,
                            CPX_MIPSEARCH_TRADITIONAL);
   if ( status )  goto TERMINATE;

   /* Set up to use MIP callback */

   status = CPXsetheuristiccallbackfunc (env, rounddownheur, NULL);
   if ( status )  goto TERMINATE;

   /* Optimize the problem and obtain solution */

   status = CPXmipopt (env, lp);
   if ( status ) {
      fprintf (stderr, "Failed to optimize MIP.\n");
      goto TERMINATE;
   }

   solstat = CPXgetstat (env, lp);
   printf ("Solution status %d.\n", solstat);

   status = CPXgetobjval (env, lp, &objval);
   if ( status ) {
      fprintf (stderr, "Failed to obtain objective value.\n");
      goto TERMINATE;
   }

   printf ("Objective value %.10g\n", objval);

   cur_numcols = CPXgetnumcols (env, lp);

   /* Allocate space for solution */

   x = (double *) malloc (cur_numcols * sizeof (double));
   if ( x == NULL ) {
      fprintf (stderr, "No memory for solution values.\n");
      goto TERMINATE;
   }

   status = CPXgetx (env, lp, x, 0, cur_numcols-1);
   if ( status ) {
      fprintf (stderr, "Failed to obtain solution.\n");
      goto TERMINATE;
   }

   /* Write out the solution */

   for (j = 0; j < cur_numcols; j++) {
      if ( fabs (x[j]) > 1e-10 ) {
         printf ( "Column %d:  Value = %17.10g\n", j, x[j]);
      }
   }


TERMINATE:

   /* Free the solution vector */

   free_and_null ((char **) &x);

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

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

   /* Free 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 parameter 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);
      }
   }
     
   return (status);

} /* END main */
Esempio n. 10
0
extern int solve_allocation(int nodeSize, int windowSize, int timeout, 
			sched_nodeinfo_t *node_array, 
			solver_job_list_t *job_array)
{
	solver_job_list_t *sjob_ptr;
	struct job_details *job_det_ptr;
	int solstat;
	int n = windowSize, m = nodeSize;
	double objval;
	double *x = NULL;
	double *pi = NULL;
	double *slack = NULL;
	double *dj = NULL;

	CPXENVptr env = NULL;
	CPXLPptr lp = NULL;
	int status = 0;
	int i, j, k;
	int cur_numrows, cur_numcols;

	char envstr[256];
	sprintf(envstr,"ILOG_LICENSE_FILE=%s",get_cplex_license_address());
	if ( envstr != NULL ) {
		CPXputenv (envstr);
	}

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

	status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
	if (status) {
		fatal("Failure to turn on screen indicator, error %d.",status);
		goto TERMINATE;
	}

	status = CPXsetintparam (env, CPX_PARAM_DATACHECK, CPX_ON);
	if (status) {
		fatal("Failure to turn on data checking, error %d.", status);
		goto TERMINATE;
	}

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

	if (lp == NULL) {
		fatal("Failed to create LP.");
		goto TERMINATE;
	}

	status = CPXsetdblparam(env,CPX_PARAM_TILIM,timeout);
	status = populatebynonzero (env, lp, m, n, timeout, 
					node_array, job_array);

	if ( status ) {
		fprintf (stderr, "Failed to populate problem.");
		goto TERMINATE;
	}

	status = CPXlpopt (env, lp);
	if ( status ) {
		fprintf (stderr, "Failed to optimize LP.");
		goto TERMINATE;
	}

	cur_numrows = CPXgetnumrows (env, lp);
	cur_numcols = CPXgetnumcols (env, lp);
	x = (double *) malloc (cur_numcols * sizeof(double));
	slack = (double *) malloc (cur_numrows * sizeof(double));
	dj = (double *) malloc (cur_numcols * sizeof(double));
	pi = (double *) malloc (cur_numrows * sizeof(double));

	if ( x == NULL ||
		slack == NULL ||
		dj    == NULL ||
		pi    == NULL   ) {
		status = CPXERR_NO_MEMORY;
		fatal ("Could not allocate memory for solution.");
		goto TERMINATE;
	}

	status = CPXsolution (env, lp, &solstat, &objval, x, pi, slack, dj);
	if ( status ) {
		fatal ("Failed to obtain solution.");
		goto TERMINATE;
	}

	for (j = 0; j < windowSize; j++) {
		if (x[j] > 0) {
			sjob_ptr = &job_array[j];
			job_det_ptr = sjob_ptr->job_ptr->details;
			sjob_ptr->node_bitmap = (bitstr_t *) 
				bit_alloc (node_record_count);
			job_det_ptr->req_node_bitmap = (bitstr_t *) 
				bit_alloc (node_record_count);
			sjob_ptr->onnodes = (uint32_t *) xmalloc 
				(sizeof(uint32_t) * node_record_count);
			job_det_ptr->req_node_layout = (uint16_t *) xmalloc 
				(sizeof(uint16_t) * node_record_count);
			job_det_ptr->req_node_bitmap = (bitstr_t *) bit_alloc
				(node_record_count);
			for (i = 0; i < nodeSize; i++) {
				k = (1 + i) * windowSize + j;
				if (x[k] > 0) {
					bit_set (sjob_ptr->node_bitmap, 
						(bitoff_t) (i));
					bit_set (job_det_ptr->req_node_bitmap, 
						(bitoff_t) (i));		
					node_array[i].rem_cpus -= x[k];
					node_array[i].rem_gpus -= sjob_ptr->gpu;
					sjob_ptr->onnodes[i] = x[k]; 
					job_det_ptr->req_node_layout[i] = 
						sjob_ptr->onnodes[i]; 
					sjob_ptr->alloc_total += x[k];
				}
			}
		} else
			job_array[j].alloc_total = 0;
	} 

TERMINATE:

	free_and_null ((char **) &x);
	free_and_null ((char **) &slack);
	free_and_null ((char **) &dj);
	free_and_null ((char **) &pi);

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

	if (env != NULL) {
		status = CPXcloseCPLEX (&env);
		if (status) {
			char errmsg[1024];
			fatal("Could not close CPLEX environment.");
			CPXgeterrorstring (env, status, errmsg);
			fatal("%s", errmsg);
		}
	}     
	
	return (status);
}
Esempio n. 11
0
// solver initialisation 
// requires the list of versioned packages and the total amount of variables (including additional ones)
int cplex_solver::init_solver(PSLProblem *problem, int other_vars) {
	int status;
	_solutionCount = 0;
	_nodeCount = 0;
	_timeCount = 0;

	// Coefficient initialization
	initialize_coeffs(problem->rankCount() + other_vars);

	/* Initialize the CPLEX environment */
	env = CPXopenCPLEX (&status);
	if ( env == NULL ) {
		char  errmsg[1024];
		fprintf (stderr, "Could not open CPLEX environment.\n");
		CPXgeterrorstring (env, status, errmsg);
		fprintf (stderr, "%s", errmsg);
		exit(-1);
	}

	/* Set the value of the time limit*/
	status = CPXsetdblparam (env, CPX_PARAM_TILIM, time_limit);
	if ( status ) {
		fprintf (stderr, "Failure to set the time limit, error %d.\n", status);
		exit(-1);
	}

	/* Enhance EPGAP to handle big values correctly */
	status = CPXsetdblparam (env, CPX_PARAM_EPGAP, 0.0);
	if ( status ) {
		fprintf (stderr, "Failure to set EPGAP, error %d.\n", status);
		exit(-1);
	}

	/* Limit the number of thread to 1 */
	status = CPXsetintparam (env, CPX_PARAM_THREADS, 1);
	if ( status ) {
		fprintf (stderr, "Failure to set thread limit to 1, error %d.\n", status);
		exit(-1);
	}

	if (verbosity >= DEFAULT) {
		/* Turn on output to the screen */
		status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
		if ( status ) {
			fprintf (stderr, "Failure to turn on screen indicator, error %d.\n", status);
			exit(-1);
		}
		/* MIP node log display information */
		int verb = verbosity >= SEARCH ? 5 : verbosity >= VERBOSE ? 2 : 1;
		status = CPXsetintparam (env, CPX_PARAM_MIPDISPLAY, verb);
		//		int val = -1;
		//		CPXgetintparam (env, CPX_PARAM_MIPDISPLAY, &val);
		//		cerr <<  val << endl;
		if ( status ) {
			fprintf (stderr, "Failure to turn off presolve, error %d.\n", status);
			exit(-1);
		}

	}

	/* Create the problem. */
	lp = CPXcreateprob (env, &status, "lpex1");

	/* 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 CPX_PARAM_SCRIND causes the error message to
     appear on stdout.  */

	if ( lp == NULL ) {
		fprintf (stderr, "Failed to create LP.\n");
		exit(-1);
	}

	first_objective = 0;

	lb = (double *)malloc(nb_vars*sizeof(double));
	ub = (double *)malloc(nb_vars*sizeof(double));
	vartype = (char *)malloc(nb_vars*sizeof(char));
	varname = (char **)malloc(nb_vars*sizeof(char *));

	if ((lb  == (double *)NULL) ||
			(ub  == (double *)NULL) ||
			(vartype  == (char *)NULL) ||
			(varname  == (char **)NULL)) {
		fprintf(stderr, "cplex_solver: initialization: not enough memory.\n");
		exit(-1);
	}

	init_vars(problem, nb_vars);
	return 0;
}
Esempio n. 12
0
int
main (void)
{
   CPXENVptr env;
   CPXLPptr lp = NULL;
   int *cone = NULL;
   int status;
   CPXCHANNELptr resc, warnc, errc, logc;
   int retval = -1;

   /* Initialize CPLEX and get a reference to the output channels.
    * If any of this fails immediately terminate the program.
    */
   env = CPXopenCPLEX (&status);
   if ( env == NULL || status != 0 )
      abort ();

   status = CPXgetchannels (env, &resc, &warnc, &errc, &logc);
   if ( status != 0 )
      abort ();

   /* CPLEX is fully setup. Enable output.
    */
   status = CPXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status != 0 )
      goto TERMINATE;

   /* Create model. */
   lp = CPXcreateprob (env, &status, "xsocpex1");
   if ( lp == NULL || status != 0 )
      goto TERMINATE;
   if ( !createmodel (env, lp, &cone) )
      goto TERMINATE;

   /* Solve the problem to optimality. */
   CPXmsg (logc, "Optimizing ...\n");
   status = CPXsetdblparam (env, CPXPARAM_Barrier_QCPConvergeTol, CONVTOL);
   if ( status != 0 )
      goto TERMINATE;
   if ( (status = CPXhybbaropt (env, lp, CPX_ALG_NONE)) != 0 )
      goto TERMINATE;

   if ( CPXgetstat (env, lp) != CPX_STAT_OPTIMAL ) {
      CPXmsg (errc, "Cannot test KKT conditions on non-optimal solution.\n");
      goto TERMINATE;
   }

   /* Now test KKT conditions on the result. */
   if ( !checkkkt (env, lp, cone, TESTTOL) ) {
      CPXmsg (logc, "Testing of KKT conditions failed.\n");
      CPXmsg (errc, "Testing of KKT conditions failed.\n");
      goto TERMINATE;
   }

   CPXmsg (resc, "KKT conditions are satisfied.\n");
   retval = 0;
 TERMINATE:
   free (cone);
   if ( lp != NULL )
      CPXfreeprob (env, &lp);
   CPXcloseCPLEX (&env);

   return retval;
}
Esempio n. 13
0
long GenModelCplex::Init(string name)
{
    //strParam.count("log_file")
    //dblParam.count("relative_mip_gap_tolerance")
    //dblParam.count("absolute_mip_gap_tolerance")
    //dblParam.count("time_limit")
    //dblParam.count("bounds_feasibility_tolerance")
    //dblParam.count("optimality_tolerance")
    //dblParam.count("markowitz_tolerance"))
    //longParam.count("threads")
    //longParam.count("cutpass")
    //longParam.count("pumplevel")
    //longParam.count("mipemphasis")
    //longParam.count("probinglevel")
    //longParam.count("max_iteration_limit");
    //boolParam.count("preprocoff") : turn on/off preprocessing
    //boolParam.count("datacheckoff")
    //boolParam.count("screen_output")
    //boolParam.count("usecutcb")
    
    if(solverdata == NULL)
        solverdata = new CplexData();
    else
    {
        static_cast<CplexData*>(solverdata)->Delete();
        static_cast<CplexData*>(solverdata)->Reset();
    }

    CplexData* d = static_cast<CplexData*>(solverdata);
    int status = 0;

    d->env = CPXopenCPLEX (&status);

    // If an error occurs
    if ( d->env == NULL )
        return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Could not open CPLEX environment"));
    
    
    hassolution = false;
    
    // Log file
    if(strParam.count("log_file") > 0)
    {
        d->cpxfileptr =  CPXfopen(strParam["log_file"].c_str(), "w");
        status = CPXsetlogfile(d->env, d->cpxfileptr);
        if ( status )
            return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set the log file"));
    }
    
    // General settings
    boolParam["log_output_stdout"] = true;
    SetParam("log_output_stdout", CPX_PARAM_SCRIND, "bool", "Failure to turn on/off log output to stdout");
	SetParam("log_level", CPX_PARAM_MIPDISPLAY, "long", "Failure to set log level");
    SetParam("use_data_checking", CPX_PARAM_DATACHECK, "bool", "Failure to turn on/off data checking");
    SetParam("nb_threads", CPX_PARAM_THREADS, "long", "Failure to set the number of threads");
    if(boolParam.count("use_preprocessor") > 0 && !boolParam["use_preprocessor"])
    {
        SetDirectParam(CPX_PARAM_AGGFILL, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_AGGFILL)");
        SetDirectParam(CPX_PARAM_PREPASS, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_PREPASS)");
        SetDirectParam(CPX_PARAM_AGGIND, long2param(CPX_OFF), "long", "Failure to use preprocessor (CPX_PARAM_AGGIND)");
        SetDirectParam(CPX_PARAM_DEPIND, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_DEPIND)");
        SetDirectParam(CPX_PARAM_PRELINEAR, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_PRELINEAR)");
        SetDirectParam(CPX_PARAM_PREDUAL, long2param(-1), "long", "Failure to use preprocessor (CPX_PARAM_PREDUAL)");
        SetDirectParam(CPX_PARAM_REDUCE, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_REDUCE)");
        SetDirectParam(CPX_PARAM_PREIND, long2param(CPX_OFF), "long", "Failure to use preprocessor (CPX_PARAM_PREIND)");
    }
    
    // MIP settings
    SetParam("nb_cut_pass", CPX_PARAM_CUTPASS, "long", "Failure to set the number of cut pass");
    SetParam("feasibility_pump_level", CPX_PARAM_FPHEUR, "long", "Failure to set the feasibility pump level");
    SetParam("probing_level", CPX_PARAM_PROBE, "long", "Failure to set the probing level");
	SetParam("mip_emphasis", CPX_PARAM_MIPEMPHASIS, "long", "Failure to set the MIP emphasis");
	SetParam("mip_search", CPX_PARAM_MIPSEARCH, "long", "Failure to set the MIP search strategy");
	SetParam("starting_algo", CPX_PARAM_STARTALG, "long", "Failure to set the starting algo parameter");
	SetParam("node_algo", CPX_PARAM_SUBALG, "long", "Failure to set the node algo parameter");
	
	if(boolParam.count("use_cut_callback") > 0 && boolParam["use_cut_callback"])
    {
        SetDirectParam(CPX_PARAM_PRELINEAR, long2param(0), "long", "Failure to use cut callback (CPX_PARAM_PRELINEAR)");
        SetDirectParam(CPX_PARAM_MIPCBREDLP, long2param(0), "long", "Failure to use cut callback (CPX_PARAM_MIPCBREDLP)");
    }
    
    // Tolerance and limits
    SetParam("time_limit", CPX_PARAM_TILIM, "dbl", "Failure to set time limit");
    SetParam("max_iteration_limit", CPX_PARAM_ITLIM, "long", "Failure to set the maximal number of simplex iterations");
    SetParam("bounds_feasibility_tolerance", CPX_PARAM_EPRHS, "dbl", "Failure to set bounds feasibility tolerance");
    SetParam("optimality_tolerance", CPX_PARAM_EPOPT, "dbl", "Failure to set optimality tolerance");
    SetParam("markowitz_tolerance", CPX_PARAM_EPMRK, "dbl", "Failure to set Markowitz tolerance");
    SetParam("absolute_mip_gap_tolerance", CPX_PARAM_EPAGAP, "dbl", "Failure to set absolute gap tolerance");
    SetParam("relative_mip_gap_tolerance", CPX_PARAM_EPGAP, "dbl", "Failure to set relative gap tolerance");
    if(boolParam.count("maximize") > 0 && boolParam["maximize"])
        SetParam("lp_objective_limit", CPX_PARAM_OBJULIM, "dbl", "Failure to set lp objective limit");
    else
        SetParam("lp_objective_limit", CPX_PARAM_OBJLLIM, "dbl", "Failure to set lp objective limit");
    
    // MIP Emphasis
    if(longParam.count("mipemphasis"))
    {
        status = CPXsetintparam (d->env, CPX_PARAM_MIPEMPHASIS, longParam["mipemphasis"]);
    }

    // Probing level
    if(longParam.count("probinglevel"))
    {
        status = CPXsetintparam (d->env, CPX_PARAM_PROBE, longParam["probinglevel"]);
    }

    if ( status )
    {
        fprintf (stderr, "Failure to set cut callback parameters, error %d->\n", status);
        return 1;
    }
    binit = true;
    
    if(dblParam.count("feastol"))
        status = CPXsetdblparam (d->env, CPX_PARAM_EPRHS, dblParam["feastol"]);
    if ( status )
    {
        fprintf (stderr, "Failure to change feasibility tolerance, error %d->\n", status);
        return 1;
    }
    if(dblParam.count("opttol"))
        status = CPXsetdblparam (d->env, CPX_PARAM_EPOPT, dblParam["opttol"]);
    if ( status )
    {
        fprintf (stderr, "Failure to change optimality tolerance, error %d->\n", status);
        return 1;
    }
    if(dblParam.count("marktol"))
        status = CPXsetdblparam (d->env, CPX_PARAM_EPMRK, dblParam["marktol"]);
    if ( status )
    {
        fprintf (stderr, "Failure to change Markowitz tolerance, error %d->\n", status);
        return 1;
    }
    
    if(longParam.count("threads"))
    {
        printf("Threads: %ld\n", longParam["threads"]);
        status = CPXsetintparam (d->env, CPX_PARAM_THREADS, longParam["threads"]);
        if ( status )
        {
            fprintf (stderr, "Failure to change the number of threads, error %d->\n", status);
            return 1;
        } 
    }

    // Turn off preprocessing
    if(boolParam.count("preprocoff") > 0 && boolParam["preprocoff"])
    {
        status = CPXsetintparam (d->env, CPX_PARAM_AGGFILL, 0);
        status = status && CPXsetintparam (d->env, CPX_PARAM_PREPASS, 0);
        status = status && CPXsetintparam (d->env, CPX_PARAM_AGGIND, CPX_OFF);
        status = status && CPXsetintparam (d->env, CPX_PARAM_DEPIND, 0);
        status = status && CPXsetintparam (d->env, CPX_PARAM_PRELINEAR, 0);
        status = status && CPXsetintparam (d->env, CPX_PARAM_PREDUAL, -1);
        status = status && CPXsetintparam (d->env, CPX_PARAM_REDUCE, 0);
        status = status && CPXsetintparam (d->env, CPX_PARAM_PREIND, CPX_OFF);
    }
    if ( status )
    {
        fprintf (stderr, "Failure to turn off preprocessing, error %d->\n", status);
        return 1;
    }

    // Turn on data checking
    if(boolParam.count("datacheckoff") > 0 && boolParam["datacheckoff"])
        status = CPXsetintparam (d->env, CPX_PARAM_DATACHECK, CPX_OFF);
    else
        status = CPXsetintparam (d->env, CPX_PARAM_DATACHECK, CPX_ON);

    if ( status )
    {
        fprintf (stderr, "Failure to turn on data checking, error %d->\n", status);
        return 1;
    }

    // Sets a relative tolerance on the gap between the best integer objective and the objective of the best node remaining (between 0.0 and 1.0)
    if(dblParam.count("epgap"))
    {
        //printf("setting epgap\n");
        status = CPXsetdblparam (d->env, CPX_PARAM_EPGAP, dblParam["epgap"]);
        if ( status )
        {
            fprintf (stderr, "Failure to set relative gap tolerance, error %d->\n", status);
            return 1;
        }
    }


    // Create the problem
    d->lp = CPXcreateprob (d->env, &status, name.c_str());
    if ( d->lp == NULL )
    {
        fprintf (stderr, "Failed to create LP.\n");
        return 1;
    }

	fflush(stdout);

    return 0;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
int CPLEXInitialize() {
	int Status = 0;
	
	//First I open the CPLEX environment if it is not already open
	if (CPLEXenv == NULL) {
		CPLEXenv = CPXopenCPLEX (&Status);
	}
	if (CPLEXenv == NULL || Status) {
		FErrorFile() << "Failed to initialize CPLEX environment. Check license server on aterneus." << endl;
		FlushErrorFile();
		return FAIL;
	}

	//Now I set any environment variables
	Status = CPXsetintparam(CPLEXenv, CPX_PARAM_SCRIND, CPX_ON);
	Status = CPXsetdblparam(CPLEXenv, CPX_PARAM_WORKMEM, 50);
	Status = CPXsetstrparam(CPLEXenv, CPX_PARAM_WORKDIR, FOutputFilepath().data());
	Status = CPXsetintparam(CPLEXenv, CPX_PARAM_NODEFILEIND, 2);
	Status = CPXsetdblparam(CPLEXenv, CPX_PARAM_TRELIM, 50);

	if (Status) {
		FErrorFile() << "Failed to set screen indicators to on." << endl;
		FlushErrorFile();
		return FAIL;
	}

	if (GetParameter("CPLEX solver time limit").length() > 0 && GetParameter("CPLEX solver time limit").compare("none") != 0) { 
		Status = CPXsetdblparam (CPLEXenv, CPX_PARAM_TILIM, atof(GetParameter("CPLEX solver time limit").data()));
		if (Status) {
			FErrorFile() << "Failed to set CPLEX time limit." << endl;
			FlushErrorFile();
			return FAIL;
		}
	}

	//I set the number of processors to run on if allowed to
	
	// SYSTEM_INFO sysinfo;
	// GetSystemInfo( &sysinfo );

	// int numCPU = sysinfo.dwNumberOfProcessors;

	Status = CPXsetintparam(CPLEXenv, CPX_PARAM_THREADS, 1);
	Status = CPXsetintparam(CPLEXenv, CPX_PARAM_PARALLELMODE, 0);
	Status = CPXsetintparam (CPLEXenv, CPX_PARAM_MIPDISPLAY, 0);

	//Next I clear out any models that currently exist
	if (CPLEXClearSolver() != SUCCESS) {
		return FAIL; //error message already printed	
	}

	//Now I create a new CPLEX model
	CPLEXModel = CPXcreateprob (CPLEXenv, &Status, "LPProb");
	Status = CPXchgprobtype(CPLEXenv, CPLEXModel, CPXPROB_LP);
	if (Status || CPLEXModel == NULL) {
		FErrorFile() << "Failed to create new CPLEX model." << endl;
		FlushErrorFile();
		return FAIL;
	}

	return SUCCESS;
}
Esempio n. 16
0
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;
}
Esempio n. 17
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
Esempio n. 18
0
int CSolver:: SetParamDouble(int whichparam, double newvalue){
    return  CPXsetdblparam(m_env, whichparam, newvalue);
}
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;
}