Example #1
0
void SmpsIO(const char * const name )
{
		SmiScnModel smi;

		// read SMPS model from files
		//	<name>.core, <name>.time, and <name>.stoch
		smi.readSmps(name);

		// generate OSI solver object
		// 	here we use OsiClp
		OsiClpSolverInterface *clp = new OsiClpSolverInterface();

		// set solver object for SmiScnModel
		smi.setOsiSolverHandle(*clp);

		// load solver data
		// 	this step generates the deterministic equivalent
		//	and returns an OsiSolver object
		OsiSolverInterface *osiStoch = smi.loadOsiSolverData();

		// set some nice Hints to the OSI solver
		osiStoch->setHintParam(OsiDoPresolveInInitial,true);
		osiStoch->setHintParam(OsiDoScale,true);
		osiStoch->setHintParam(OsiDoCrash,true);

		// solve
		osiStoch->initialSolve();

		// print results
		printf("Solved stochastic program %s\n", name);
		printf("Number of rows: %d\n",osiStoch->getNumRows());
		printf("Number of cols: %d\n",osiStoch->getNumCols());
		printf("Optimal value: %g\n",osiStoch->getObjValue());

		// print solution to file
		string outfilename(name);
		const string suffix(".out");
		outfilename = outfilename + suffix;
		FILE *fp = fopen(outfilename.c_str(),"w");
		int numScenarios=smi.getNumScenarios();

		for (int i=0 ; i<numScenarios; ++i) {
			double *dsoln=NULL;
			int numCols=0;
			fprintf(fp,"Scenario %d \n",i);
			dsoln = smi.getColSolution(i,&numCols);
			for (int j=0; j<numCols; j++)
				fprintf(fp,"%g \n",dsoln[j]);
			free(dsoln);
		}
		fclose(fp);


}
Example #2
0
/*
  Function for parameters that are enabled/disabled with a hint.
*/
int pushCbcOsiHint (CoinParam *param)

{
    assert (param != 0) ;
    CbcOsiParam *osiParam = dynamic_cast<CbcOsiParam *>(param) ;
    assert (osiParam != 0) ;
    OsiSolverInterface *osi = osiParam->obj() ;
    assert(osi != 0) ;
    /*
      Setup to return nonfatal/fatal error (1/-1) by default, so that all we need
      to do is correct to 0 (no error) if we're successful.
    */
    int retval ;
    if (CoinParamUtils::isInteractive()) {
        retval = 1 ;
    } else {
        retval = -1 ;
    }
    /*
      Set the sense for the hint.
    */
    std::string kwd = param->kwdVal() ;
    bool sense ;
    if (kwd == "off") {
        sense = false ;
    } else {
        sense = true ;
    }
    /*
      Grab the parameter code and translate to an OSI parameter key.
    */
    CbcOsiParam::CbcOsiParamCode code = osiParam->paramCode() ;
    OsiHintParam key ;
    switch (code) {
    case CbcOsiParam::PRESOLVE: {
        key = OsiDoPresolveInInitial ;
        break ;
    }
    case CbcOsiParam::SCALING: {
        key = OsiDoScale ;
        break ;
    }
    default: {
        std::cerr << "pushCbcOsiHint: no equivalent OsiHintParam for "
                  << "parameter code `" << code << "'." << std::endl ;
        retval = -1 ;
        break ;
    }
    }

    bool setOK = osi->setHintParam(key, sense, OsiHintDo) ;

    if (setOK) {
        return (0) ;
    } else {
        return (retval) ;
    }
}
Example #3
0
void* problem_convert_to_osi(Problem *p)
{
    int i;
    double rowLb, rowUb;
    OsiSolverInterface *solver = new OsiClpSolverInterface();
    CoinBuild cb;

    solver->setIntParam(OsiNameDiscipline, 2);
    solver->messageHandler()->setLogLevel(0);
    solver->setHintParam(OsiDoReducePrint,true,OsiHintTry);

    for(i = 0; i < p->numCols; i++)
    {
        solver->addCol(0, NULL, NULL, p->colLb[i], p->colUb[i], p->objCoef[i]);
        solver->setColName(i, p->colName[i]);
        
        if(p->colType[i] == CONTINUOUS)
            solver->setContinuous(i);
        else 
            solver->setInteger(i);
    }

    for(i = 0; i < p->numRows; i++)
    {
        switch(p->rowSense[i])
        {
            case 'E':
                rowLb = p->rhs[i];
                rowUb = p->rhs[i];
            break;

            case 'L':
                rowLb = -p->infty;
                rowUb = p->rhs[i];
            break;

            case 'G':
                rowLb = p->rhs[i];
                rowUb = p->infty;
            break;

            default:
                fprintf(stderr, "Error: invalid type of constraint!\n");
                exit(EXIT_FAILURE);
        }

        cb.addRow(p->rowNElements[i], p->idxsByRow[i], p->coefsByRow[i], rowLb, rowUb);
    }

    solver->addRows(cb);
    
    for(i = 0; i < p->numRows; i++)
        solver->setRowName(i, p->rowName[i]);

    return solver;
}
Example #4
0
int pushCbcOsiLogLevel (CoinParam *param)

{
    assert (param != 0) ;
    CbcOsiParam *osiParam = dynamic_cast<CbcOsiParam *>(param) ;
    assert (osiParam != 0) ;
    OsiSolverInterface *osi = osiParam->obj() ;
    assert(osi != 0) ;

    int lvl = param->intVal() ;
    /*
      Setup to return nonfatal/fatal error (1/-1) by default, so that all we need
      to do is correct to 0 (no error) if we're successful.
    */
    int retval ;
    if (CoinParamUtils::isInteractive()) {
        retval = 1 ;
    } else {
        retval = -1 ;
    }
    /*
      Now try to do the right thing with a hint. Harder to say -- assume that log
      level 1 is `normal'.
    */
    OsiHintStrength strength ;
    bool sense ;
    if (lvl < 1) {
        strength = OsiHintDo ;
        sense = true ;
    } else if (lvl == 1) {
        strength = OsiHintIgnore ;
        sense = true ;
    } else if (lvl == 2) {
        strength = OsiHintTry ;
        sense = false ;
    } else {
        strength = OsiHintDo ;
        sense = false ;
    }

    bool setOK = osi->setHintParam(OsiDoReducePrint, sense, strength) ;

    /*
      Recover the message handler and set the log level directly.
    */
    CoinMessageHandler *hndl = osi->messageHandler() ;
    assert (hndl != 0) ;
    hndl->setLogLevel(lvl) ;

    if (setOK) {
        return (0) ;
    } else {
        return (retval) ;
    }
}
    ILPSolverCbc::ILPSolverCbc()
    {
        // CbcModel assumes ownership over solver and deletes it in its destructor.
        OsiSolverInterface* solver = new OsiClpSolverInterface();

        // Output should come from CBC, not from CBCs solver.
        solver->messageHandler()->setLogLevel(0);
        solver->setHintParam(OsiDoReducePrint, 1);

        d_model.assignSolver(solver, true);
        set_default_parameters(this);
    }
Example #6
0
int main (int argc, const char *argv[])
{
/*
  Start off with various bits of initialisation that don't really belong
  anywhere else.

  First off, synchronise C++ stream i/o with C stdio. This makes debugging
  output a bit more comprehensible. It still suffers from interleave of cout
  (stdout) and cerr (stderr), but -nobuf deals with that.
*/
  std::ios::sync_with_stdio() ;
/*
  Suppress an popup window that Windows shows in response to a crash. See
  note at head of file.
*/
  WindowsErrorPopupBlocker();
/*
  Might as well make use of this convenient Xpress feature.
*/
#ifdef COIN_HAS_XPR
  OsiXprSolverInterface::setLogFileName("xprCallTrace.txt");
#endif

/*
  Process command line parameters.
*/
  std::map<std::string,std::string> parms ;
  if (processParameters(argc,argv,parms) == false)
    return 1;

  std::string mpsDir = parms["-mpsDir"] ;
  std::string netlibDir = parms["-netlibDir"] ;

/*
  Test Osi{Row,Col}Cut routines.
*/
#ifdef COIN_HAS_XPR  
  {
    OsiXprSolverInterface xprSi;
    testingMessage( "Testing OsiRowCut with OsiXprSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutUnitTest(&xprSi,mpsDir), {}, xprSi, "rowcut unittest");
  }
  {
    OsiXprSolverInterface xprSi;
    testingMessage( "Testing OsiColCut with OsiXprSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiColCutUnitTest(&xprSi,mpsDir), {}, xprSi, "colcut unittest");
  }
  {
    OsiXprSolverInterface xprSi;
    testingMessage( "Testing OsiRowCutDebugger with OsiXprSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutDebuggerUnitTest(&xprSi,mpsDir), {}, xprSi, "rowcut debugger unittest");
  }
#endif

#ifdef COIN_HAS_CPX
  {
    OsiCpxSolverInterface cpxSi;
    testingMessage( "Testing OsiRowCut with OsiCpxSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutUnitTest(&cpxSi,mpsDir), {}, cpxSi, "rowcut unittest");
  }
  {
    OsiCpxSolverInterface cpxSi;
    testingMessage( "Testing OsiColCut with OsiCpxSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiColCutUnitTest(&cpxSi,mpsDir), {}, cpxSi, "colcut unittest");
  }
  {
    OsiCpxSolverInterface cpxSi;
    testingMessage( "Testing OsiRowCutDebugger with OsiCpxSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutDebuggerUnitTest(&cpxSi,mpsDir), {}, cpxSi, "rowcut debugger unittest");
  }
#endif

#ifdef USETESTSOLVER
  {
    OsiTestSolverInterface testSi;
    testingMessage( "Testing OsiRowCut with OsiTestSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutUnitTest(&testSi,mpsDir), {}, testSi, "rowcut unittest");
  }
  {
    OsiTestSolverInterface testSi;
    testingMessage( "Testing OsiColCut with OsiTestSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiColCutUnitTest(&testSi,mpsDir), {}, testSi, "colcut unittest");
  }
#endif

#ifdef COIN_HAS_GLPK
  {
    OsiGlpkSolverInterface glpkSi;
    testingMessage( "Testing OsiRowCut with OsiGlpkSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutUnitTest(&glpkSi,mpsDir), {}, glpkSi, "rowcut unittest");
  }
  {
    OsiGlpkSolverInterface glpkSi;
    testingMessage( "Testing OsiColCut with OsiGlpkSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiColCutUnitTest(&glpkSi,mpsDir), {}, glpkSi, "colcut unittest");
  }
  {
    OsiGlpkSolverInterface glpkSi;
    testingMessage( "Testing OsiRowCutDebugger with OsiGlpkSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutDebuggerUnitTest(&glpkSi,mpsDir), {}, glpkSi, "rowcut debugger unittest");
  }
#endif

#ifdef COIN_HAS_MSK  
  {
    OsiMskSolverInterface MskSi;
    testingMessage( "Testing OsiRowCut with OsiMskSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutUnitTest(&MskSi,mpsDir), {}, MskSi, "rowcut unittest");
  }
  {
    OsiMskSolverInterface MskSi;
    testingMessage( "Testing OsiColCut with OsiMskSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiColCutUnitTest(&MskSi,mpsDir), {}, MskSi, "colcut unittest");
  }
  {
    OsiMskSolverInterface MskSi;
    testingMessage( "Testing OsiRowCutDebugger with OsiMskSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutDebuggerUnitTest(&MskSi,mpsDir), {}, MskSi, "rowcut debugger unittest");
  }
#endif

#ifdef COIN_HAS_GRB
  {
    OsiGrbSolverInterface grbSi;
    testingMessage( "Testing OsiRowCut with OsiGrbSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutUnitTest(&grbSi,mpsDir), {}, grbSi, "rowcut unittest");
  }
  {
    OsiGrbSolverInterface grbSi;
    testingMessage( "Testing OsiColCut with OsiGrbSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiColCutUnitTest(&grbSi,mpsDir), {}, grbSi, "colcut unittest");
  }
  {
    OsiGrbSolverInterface grbSi;
    testingMessage( "Testing OsiRowCutDebugger with OsiGrbSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutDebuggerUnitTest(&grbSi,mpsDir), {}, grbSi, "rowcut debugger unittest");
  }
#endif

#ifdef COIN_HAS_SOPLEX
  {
    OsiSpxSolverInterface spxSi;
    testingMessage( "Testing OsiRowCut with OsiSpxSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutUnitTest(&spxSi,mpsDir), {}, spxSi, "rowcut unittest");
  }
  {
    OsiSpxSolverInterface spxSi;
    testingMessage( "Testing OsiColCut with OsiSpxSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiColCutUnitTest(&spxSi,mpsDir), {}, spxSi, "colcut unittest");
  }
  {
    OsiSpxSolverInterface spxSi;
    testingMessage( "Testing OsiRowCutDebugger with OsiSpxSolverInterface\n" );
    OSIUNITTEST_CATCH_ERROR(OsiRowCutDebuggerUnitTest(&spxSi,mpsDir), {}, spxSi, "rowcut debugger unittest");
  }
#endif

  testingMessage( "Testing OsiCuts\n" );
  OSIUNITTEST_CATCH_ERROR(OsiCutsUnitTest(), {}, "osi", "osicuts unittest");

/*
  Testing OsiCuts only? A useful option when doing memory access and leak
  checks. Keeps the run time to something reasonable.
*/
  if (parms.find("-cutsOnly") != parms.end()) {
    testingMessage( "Stopping after OsiCuts tests.\n" );
    return 0;
  }

/*
  Run the OsiXXX class test for each solver. It's up to the solver implementor
  to decide whether or not to run OsiSolverInterfaceCommonUnitTest. Arguably
  this should be required.
*/
#ifdef COIN_HAS_XPR
  testingMessage( "Testing OsiXprSolverInterface\n" );
  OSIUNITTEST_CATCH_ERROR(OsiXprSolverInterfaceUnitTest(mpsDir,netlibDir), {}, "xpress", "osixpr unittest");
#endif

#ifdef COIN_HAS_CPX
  testingMessage( "Testing OsiCpxSolverInterface\n" );
  OSIUNITTEST_CATCH_ERROR(OsiCpxSolverInterfaceUnitTest(mpsDir,netlibDir), {}, "cplex", "osicpx unittest");
#endif

#ifdef USETESTSOLVER
  testingMessage( "Testing OsiTestSolverInterface\n" );
  OSIUNITTEST_CATCH_ERROR(OsiTestSolverInterfaceUnitTest(mpsDir,netlibDir), {}, "vol", "ositestsolver unittest");
#endif
  
#ifdef COIN_HAS_GLPK
  testingMessage( "Testing OsiGlpkSolverInterface\n" );
  OSIUNITTEST_CATCH_ERROR(OsiGlpkSolverInterfaceUnitTest(mpsDir,netlibDir), {}, "glpk", "osiglpk unittest");
#endif
  
#ifdef COIN_HAS_MSK
  testingMessage( "Testing OsiMskSolverInterface\n" );
  OSIUNITTEST_CATCH_ERROR(OsiMskSolverInterfaceUnitTest(mpsDir,netlibDir), {}, "mosek", "osimsk unittest");
#endif

#ifdef COIN_HAS_GRB
  testingMessage( "Testing OsiGrbSolverInterface\n" );
  OSIUNITTEST_CATCH_ERROR(OsiGrbSolverInterfaceUnitTest(mpsDir,netlibDir), {}, "gurobi", "osigrb unittest");
#endif

#ifdef COIN_HAS_SOPLEX
  testingMessage( "Testing OsiSpxSolverInterface\n" );
  OSIUNITTEST_CATCH_ERROR(OsiSpxSolverInterfaceUnitTest(mpsDir,netlibDir), {}, "soplex", "osispx unittest");
#endif

/*
  Each solver has run its specialised unit test. Check now to see if we need to
  run through the Netlib problems.
*/
  if (parms.find("-testOsiSolverInterface") != parms.end())
  {
    // Create vector of solver interfaces
    std::vector<OsiSolverInterface*> vecSi;
#   if COIN_HAS_XPR
    OsiSolverInterface * xprSi = new OsiXprSolverInterface;
    vecSi.push_back(xprSi);
#   endif
#   if COIN_HAS_CPX
    OsiSolverInterface * cpxSi = new OsiCpxSolverInterface;
    vecSi.push_back(cpxSi);
#   endif
#   if COIN_HAS_GLPK
    OsiSolverInterface * glpkSi = new OsiGlpkSolverInterface;
    glpkSi->setHintParam(OsiDoPresolveInInitial,true,OsiHintTry) ;
    glpkSi->setHintParam(OsiDoReducePrint,true,OsiHintDo) ;
    vecSi.push_back(glpkSi);
#   endif
#   if COIN_HAS_MSK
    OsiSolverInterface * MskSi = new OsiMskSolverInterface;
    vecSi.push_back(MskSi);
#   endif
#   if COIN_HAS_GRB
    OsiSolverInterface * grbSi = new OsiGrbSolverInterface;
    vecSi.push_back(grbSi);
#   endif
#   if COIN_HAS_SOPLEX
    OsiSolverInterface * spxSi = new OsiSpxSolverInterface;
    vecSi.push_back(spxSi);
#   endif
#   ifdef USETESTSOLVER
/*
  The test solver is normally Vol, which can't do any of the netlib problems.
  So let's not try.
*/
    {
      std::string solverName ;
      OsiSolverInterface * testSi = new OsiTestSolverInterface;
      testSi->getStrParam(OsiSolverName,solverName) ;
      if (solverName != "vol")
      { vecSi.push_back(testSi); }
      else
      { testingMessage("Test solver vol cannot do Netlib. Skipping.\n") ; }
    }
#   endif

    if (vecSi.size() > 0)
    { testingMessage( "Testing OsiSolverInterface on Netlib problems.\n" );
      OSIUNITTEST_CATCH_ERROR(OsiSolverInterfaceMpsUnitTest(vecSi,netlibDir), {}, "osi", "netlib unittest");
    }

    unsigned int i;
    for (i=0; i<vecSi.size(); i++)
      delete vecSi[i];
  }
  else {
    testingMessage( "***Skipped Testing of OsiSolverInterface on Netlib problems***\n" );
    testingMessage( "***use -testOsiSolverInterface to run them.***\n" );
  }

/*
  We're done. Report on the results.
*/
  std::cout.flush();
  outcomes.print();

  int nerrors;
  int nerrors_expected;
  outcomes.getCountBySeverity(TestOutcome::ERROR, nerrors, nerrors_expected);

  if (nerrors > nerrors_expected)
    std::cerr << "Tests completed with " << nerrors - nerrors_expected << " unexpected errors." << std::endl ;
  else
    std::cerr << "All tests completed successfully\n";

  return nerrors - nerrors_expected;
}
Example #7
0
// mex function usage:
//  [x,y,status] = mexosi(n_vars,n_cons,A,x_lb,x_ub,c,Ax_lb,Ax_ub,isMIP,isQP,vartype,Q,options)
//                        0      1      2 3    4    5 6     7     8     9    10     11 12
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
	// Enable printing in MATLAB
	int loglevel = 0;
	DerivedHandler *mexprinter = new DerivedHandler(); // assumed open	
	mexprinter->setLogLevel(loglevel);		 
	// check that we have the right number of inputs
	if(nrhs < 10) mexErrMsgTxt("At least 10 inputs required in call to mexosi. Bug in osi.m?...");
	// check that we have the right number of outputs
	if(nlhs < 3) mexErrMsgTxt("At least 3 ouptuts required in call to mexosi. Bug in osi.m?...");

    // Get pointers to input values
	const int    n_vars = (int)*mxGetPr(prhs[0]);
	const int    n_cons = (int)*mxGetPr(prhs[1]);
	const mxArray    *A =  prhs[2];
	const double  *x_lb =  mxGetPr(prhs[3]);
	const double  *x_ub =  mxGetPr(prhs[4]);
	const double     *c =  mxGetPr(prhs[5]);
	const double *Ax_lb =  mxGetPr(prhs[6]);
	const double *Ax_ub =  mxGetPr(prhs[7]);
	const bool    isMIP = (bool)*(mxLogical*)mxGetData(prhs[8]);
	const bool     isQP = (bool)*(mxLogical*)mxGetData(prhs[9]);
	mxLogical *isinteger = (mxLogical*)mxGetData(prhs[10]);
	const mxArray*    Q = prhs[11];
	// process the options
	int  returnStatus = 0;
	// extract row/col/value data from A
	const mwIndex * A_col_starts = mxGetJc(A);
	const mwIndex * A_row_index  = mxGetIr(A);
	const double  * A_data       = mxGetPr(A);
    // figure out the number of non-zeros in A
    int nnz = (int)(A_col_starts[n_vars] - A_col_starts[0]); // number of non-zeros
    //mexPrintf("nnz = %d, n_vars = %d, n_cons = %d\n",nnz,n_vars,n_cons);

    // we need to convert these into other types of indices for Coin to use them
    std::vector<CoinBigIndex> A_col_starts_coin(A_col_starts,A_col_starts+n_vars+1);
    std::vector<int>          A_row_index_coin(A_row_index,A_row_index+nnz);
    
    // declare the solver
    OsiSolverInterface* pSolver;
// 	initialize the solver
    if ( isMIP ) {
        pSolver = new OsiCbcSolverInterface;
    } else {
        pSolver = new OsiClpSolverInterface;
    }
   
//	OsiCbcSolverInterface is deprecated and CbcModel should be used instead but don't
//	know how to get that working with loadProblem. 
//     OsiCbcSolverInterface solver1;
//     CbcModel model(solver1);
//     CbcMain0(model);
//     OsiSolverInterface * pSolver = model.solver();
    
	if (nrhs>12) { // get stuff out of the options structure if provided
		// Finish me
	}
    
//     mexPrintf("Setting Log Level to 0.\n");
	// load the problem
	mexPrintf("Loading the problem.\n");
	pSolver->loadProblem( n_vars, n_cons, // problem size
						  &A_col_starts_coin[0], &A_row_index_coin[0], A_data, // the A matrix
						  x_lb,  x_ub, c, // the objective and bounds
						  Ax_lb, Ax_ub ); // the constraint bounds
    
//     pSolver->messageHandler()->setLogLevel(0); // This doesn't seem to work
    pSolver->setHintParam(OsiDoReducePrint,true,OsiHintTry);
    
	// deal with integer inputs
	if ( isMIP ) {
		for(int i=0;i<n_vars;i++) {
			if (isinteger[i]) pSolver->setInteger(i);
		}
	}
	if (isQP) {
		error("QP is not working yet");
		// need to call loadQuadraticObjective here ???
	}
    
//     CbcModel model(pSolver);
//     model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
    
    
	// solve the problem
	//mexPrintf("Trying to solve the problem.\n");
    if (isMIP) {
        pSolver->branchAndBound();
//         model.branchAndBound();
    } else {
//         model.initialSolve();
        pSolver->initialSolve();
    }
	
	// Allocate memory for return data
    plhs[0] = mxCreateDoubleMatrix(n_vars,1, mxREAL); // for the solution
    plhs[1] = mxCreateDoubleMatrix(n_cons,1, mxREAL); // for the constraint prices
    plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL);      // for the return status
    double *x = mxGetPr(plhs[0]);
    double *y = mxGetPr(plhs[1]);
    double *returncode = mxGetPr(plhs[2]);
	
	// Copy solutions if available
	if ( pSolver->isProvenOptimal() ) {
//     if ( model.isProvenOptimal() ) {
//     if ( model.solver()->isProvenOptimal() ) {
        //mexPrintf("Solution found.\n");
		// extract the solutions
		const double * solution = pSolver->getColSolution();
		const double * dualvars = pSolver->getRowPrice();
		// copy the solution to the outpus
		memcpy(x,solution,n_vars*sizeof(double));
		memcpy(y,dualvars,n_cons*sizeof(double));
		*returncode = 1;
	} else {
		if ( pSolver->isProvenPrimalInfeasible() ) {
			mexPrintf("Primal problem is proven infeasible.\n");
			*returncode = 0;
		} else if ( pSolver->isProvenDualInfeasible() ) {
			mexPrintf("Dual problem is proven infeasible.\n");
			*returncode = -1;
		} else if ( pSolver->isPrimalObjectiveLimitReached() ) {
			mexPrintf("The primal objective limit was reached.\n");
			*returncode = -2;
		} else if ( pSolver->isDualObjectiveLimitReached() ) {
			mexPrintf("The dual objective limit was reached.\n");
			*returncode = -3;
		} else if ( pSolver->isIterationLimitReached() ) {
			mexPrintf("The iteration limit was reached\n");
			*returncode = -4;
		}
	}
	// clean up memory
	if ( mexprinter!= NULL) delete mexprinter;	
	delete pSolver;
}
Example #8
0
//#############################################################################
OsiSolverInterface *
MibSBilevel::setUpModel(OsiSolverInterface * oSolver, bool newOsi,
			const double *lpSol)
{

  /** Create lower-level model with fixed upper-level vars **/

  int probType =
    model_->MibSPar_->entry(MibSParams::bilevelProblemType);

  bool warmStartLL =
    model_->MibSPar_->entry(MibSParams::warmStartLL);

  bool doDualFixing =
    model_->MibSPar_->entry(MibSParams::doDualFixing);

  std::string feasCheckSolver =
    model_->MibSPar_->entry(MibSParams::feasCheckSolver);

  OsiSolverInterface * nSolver;

  double etol(model_->etol_);
  int i(0), j(0), index1(0), index2(0);
  int uCols(model_->getUpperDim());
  int lRows(model_->getLowerRowNum());
  int lCols(model_->getLowerDim());
  int * uColIndices = model_->getUpperColInd();
  int * lColIndices = model_->getLowerColInd();
  int * lRowIndices = model_->getLowerRowInd();

  double objSense(model_->getLowerObjSense());  
  double * lObjCoeffs = model_->getLowerObjCoeffs();
     
  const CoinPackedMatrix * matrix = oSolver->getMatrixByRow();
  double coeff(0.0);
  if (!lpSol){
     lpSol = oSolver->getColSolution();   
  }
  const double * origRowLb = model_->getOrigRowLb();
  const double * origRowUb = model_->getOrigRowUb();
  const double * origColLb = model_->getOrigColLb();
  const double * origColUb = model_->getOrigColUb();
  double * rowUb = new double[lRows];
  double * rowLb = new double[lRows];
  double * colUb = new double[lCols];
  double * colLb = new double[lCols];
  //CoinZeroN(rowUb, lRows);
  //CoinZeroN(rowLb, lRows);
  //CoinZeroN(colUb, lCols);
  //CoinZeroN(colLb, lCols);

  /** Set the row bounds **/
  
  for(i = 0; i < lRows; i++){
     rowLb[i] = origRowLb[lRowIndices[i]];
     rowUb[i] = origRowUb[lRowIndices[i]];
  }
     
  for(i = 0; i < lCols; i++){
     colLb[i] = origColLb[lColIndices[i]];
     colUb[i] = origColUb[lColIndices[i]];
  }
  
  if (newOsi){
     if (feasCheckSolver == "Cbc"){
	nSolver = new OsiCbcSolverInterface();
     }else if (feasCheckSolver == "SYMPHONY"){
	nSolver = new OsiSymSolverInterface();
     }else if (feasCheckSolver == "CPLEX"){
#ifdef USE_CPLEX
	nSolver = new OsiCpxSolverInterface();
#else
	throw CoinError("CPLEX chosen as solver, but it has not been enabled",
			"setUpModel", "MibsBilevel");
#endif
     }else{
	throw CoinError("Unknown solver chosen",
			"setUpModel", "MibsBilevel");
     }
	
     int * integerVars = new int[lCols];
     double * objCoeffs = new double[lCols];
     
     CoinFillN(integerVars, lCols, 0);
     //CoinZeroN(objCoeffs, lCols);
     
     int intCnt(0);
  
     /** Fill in array of lower-level integer variables **/
     
     for(i = 0; i < lCols; i++){
	index1 = lColIndices[i];
	if(oSolver->isInteger(index1)){
	   integerVars[intCnt] = i;
	   intCnt++;
	}
     }
     
     CoinDisjointCopyN(lObjCoeffs, lCols, objCoeffs);
     
     CoinPackedMatrix * newMat = new CoinPackedMatrix(false, 0, 0);
     newMat->setDimensions(0, lCols);
     double tmp(0.0);
     
     /*
       for(i = 0; i < lRows; i++){
       CoinPackedVector row;
       index1 = lRowIndices[i];
       start = matStarts[index1];
       end = start + matrix->getVectorSize(index1);
       for(j = start; j < end; j++){
       index2 = matIndices[j];
       //tmp = findIndex(index, lCols, lColIndices);
       tmp = binarySearch(0, lCols - 1, index2, lColIndices);
       if(tmp > -1)
       row.insert(tmp, matElements[j]);
       }
       newMat->appendRow(row);
       }
     */
     for(i = 0; i < lRows; i++){
	CoinPackedVector row;
	index1 = lRowIndices[i];
	for(j = 0; j < lCols; j++){
	   index2 = lColIndices[j];
	   tmp = matrix->getCoefficient(index1, index2);
	   row.insert(j, tmp);
	}
	newMat->appendRow(row);
     }

     /*
       nSolver->assignProblem(newMat, colLb, colUb,
       objCoeffs, rowLb, rowUb);
     */
     
     nSolver->loadProblem(*newMat, colLb, colUb,
			  objCoeffs, rowLb, rowUb);
     
     for(i = 0; i < intCnt; i++){
	nSolver->setInteger(integerVars[i]);
     }
     //nSolver->setInteger(integerVars, intCnt);
     
     nSolver->setObjSense(objSense); //1 min; -1 max
     
     nSolver->setHintParam(OsiDoReducePrint, true, OsiHintDo);

#if 0
     if(0){
	dynamic_cast<OsiCbcSolverInterface *> 
	   (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
     }
     else{
	dynamic_cast<OsiSymSolverInterface *> 
	   (nSolver)->setSymParam("prep_level", -1);
	
	dynamic_cast<OsiSymSolverInterface *> 
	   (nSolver)->setSymParam("verbosity", -2);
	
	dynamic_cast<OsiSymSolverInterface *> 
	   (nSolver)->setSymParam("max_active_nodes", 1);
     }
#endif
     delete [] integerVars;

  }else{
     nSolver = solver_;
  }

#define SYM_VERSION_IS_WS strcmp(SYMPHONY_VERSION, "WS")  

#if SYMPHONY_VERSION_IS_WS
  if (feasCheckSolver == "SYMPHONY" && probType == 1 && warmStartLL &&
      !newOsi && doDualFixing){ //Interdiction

     /** Get upper bound from best known (feasible) lower level solution and try 
	 to fix additional variables by sensitivity analysis **/

     std::vector<std::pair<AlpsKnowledge*, double> > solutionPool;
     model_->getKnowledgeBroker()->
	getAllKnowledges(AlpsKnowledgeTypeSolution, solutionPool);

     const double * sol; 
     double objval, Ub(objSense*nSolver->getInfinity());
     BlisSolution* blisSol;
     std::vector<std::pair<AlpsKnowledge*, double> >::const_iterator si;
     for (si = solutionPool.begin(); si != solutionPool.end(); ++si){
	blisSol = dynamic_cast<BlisSolution*>(si->first);
	sol = blisSol->getValues();
	for (i = 0; i < uCols; i++){
	   if (lpSol[uColIndices[i]] > 1 - etol &&
	       sol[lColIndices[i]] > 1-etol){
	      break;
	   }
	}
	if (i == uCols && -objSense*blisSol->getQuality() < Ub){
	   Ub = -objSense*blisSol->getQuality();
	}
     }

     /** Figure out which variables get fixed by the upper level solution **/

     int *newUbInd = new int[uCols];
     int *newLbInd = new int[uCols];
     double *newUbVal = new double[uCols];
     double *newLbVal = new double[uCols];
     double newLb;
     for (i = 0; i < uCols; i++){
	newUbInd[i] = uColIndices[i];
	newLbInd[i] = uColIndices[i];
	newLbVal[i] = 0;
	if (lpSol[uColIndices[i]] > 1 - etol){
	   newUbVal[i] = 0;
	}else{
	   newUbVal[i] = 1;
	}
     }
	
     /** If we found an upper bound, then do the dual fixing **/

     if (Ub < objSense*nSolver->getInfinity()){
	sym_environment *env = 
	   dynamic_cast<OsiSymSolverInterface *>(nSolver)->getSymphonyEnvironment();

	for (i = 0; i < uCols; i++){
	   if (newUbVal[i] == 1){
	      // Try fixing it to zero
	      newUbVal[i] = 0; 
	      sym_get_lb_for_new_rhs(env, 0, NULL, NULL, uCols, newLbInd,
				     newLbVal, uCols, newUbInd, newUbVal,
				     &newLb);
	      if (objSense*newLb > Ub + etol){
		 //Victory! This variable can be fixed to 1 permanently
		 newLbVal[i] = 1;
	      }
	      //Set upper bound back to 1
	      newUbVal[i] = 1;
	      
	      if (newLbVal[i] == 0){
		 // Try fixing it to one
		 newLbVal[i] = 1;
		 sym_get_lb_for_new_rhs(env, 0, NULL, NULL, uCols, newLbInd,
					newLbVal, uCols, newUbInd, newUbVal,
					&newLb);
		 if (objSense*newLb > Ub + etol){
		    //Victory! This variable can be fixed to 0 permanently
		    newUbVal[i] = 0;
		 }
		 newLbVal[i] = 0;
	      }
	   }
	   
	}
     }
     
     /** Now set the row bounds to account for fixings **/
     
     /** This is probably very frgaile. Assuming interdiction 
	 rows come last. It would be better to set variable 
	 bounds directly, but this doesn't seem to work right now. **/
     int iRowStart = lRows-uCols; 

#if 1
     for(i = iRowStart; i < lRows; i++){
	nSolver->setRowLower(i, newLbVal[i-iRowStart]);
	nSolver->setRowUpper(i, newUbVal[i-iRowStart]);
     }
#else
     for(i = 0; i < uCols; i++){
	nSolver->setColLower(i, newLbVal[i]);
	nSolver->setColUpper(i, newUbVal[i]);
     }
#endif     
     delete[] newUbInd;
     delete[] newLbInd;
     delete[] newUbVal;
     delete[] newLbVal;
  }else{
#endif
     //FIXME: NEED TO GET ROW SENSE HERE
     
     /** Get contribution of upper-level columns **/
     
     double * upComp = new double[lRows];
     CoinFillN(upComp, lRows, 0.0);
     
     for(i = 0; i < lRows; i++){
	index1 = lRowIndices[i];
	for(j = 0; j < uCols; j++){
	   index2 = uColIndices[j];
	   coeff = matrix->getCoefficient(index1, index2);
	   if (coeff != 0){
	      upComp[i] += coeff * lpSol[index2];
	   }
	}
     }
     
     /** Correct the row bounds to account for fixed upper-level vars **/
     
     for(i = 0; i < lRows; i++){
	nSolver->setRowLower(i, rowLb[i] - upComp[i]);
	nSolver->setRowUpper(i, rowUb[i] - upComp[i]);
     }
     
     delete [] upComp;

#if SYMPHONY_VERSION_IS_WS
  }
#endif

  //I don't think this is needed
  //if(!getWarmStart())
  //  setWarmStart(nSolver->getWarmStart());

  return nSolver;

}
Example #9
0
//#############################################################################
void 
MibSBilevel::checkBilevelFeasiblity(bool isRoot)
{
  
  int cutStrategy =
    model_->MibSPar_->entry(MibSParams::cutStrategy);

  bool warmStartLL =
    model_->MibSPar_->entry(MibSParams::warmStartLL);

  int maxThreadsLL =
    model_->MibSPar_->entry(MibSParams::maxThreadsLL);

  int whichCutsLL =
    model_->MibSPar_->entry(MibSParams::whichCutsLL);

  int probType =
    model_->MibSPar_->entry(MibSParams::bilevelProblemType);

  std::string feasCheckSolver =
     model_->MibSPar_->entry(MibSParams::feasCheckSolver);

  if (warmStartLL && (feasCheckSolver == "SYMPHONY") && solver_){
     solver_ = setUpModel(model_->getSolver(), false);
  }else{
     if (solver_){
	delete solver_;
     }
     solver_ = setUpModel(model_->getSolver(), true);
  }

  OsiSolverInterface *lSolver = solver_;

  //CoinWarmStart * ws = getWarmStart();
  //if (ws != NULL){
  //   lSolver->setWarmStart(ws);
  //}
  //delete ws;

  if(1)
    lSolver->writeLp("lowerlevel");

  if (feasCheckSolver == "Cbc"){
    dynamic_cast<OsiCbcSolverInterface *> 
      (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0);
  }else if (feasCheckSolver == "SYMPHONY"){
     //dynamic_cast<OsiSymSolverInterface *> 
     // (lSolver)->setSymParam("prep_level", -1);
    
     sym_environment *env = dynamic_cast<OsiSymSolverInterface *> 
	(lSolver)->getSymphonyEnvironment();

     if (warmStartLL){
	sym_set_int_param(env, "keep_warm_start", TRUE);
	if (probType == 1){ //Interdiction
	   sym_set_int_param(env, "should_use_rel_br", FALSE);
	   sym_set_int_param(env, "use_hot_starts", FALSE);
	   sym_set_int_param(env, "should_warmstart_node", TRUE);
	   sym_set_int_param(env, "sensitivity_analysis", TRUE);
	   sym_set_int_param(env, "sensitivity_bounds", TRUE);
	   sym_set_int_param(env, "set_obj_upper_lim", FALSE);
	}
     }
     //Always uncomment for debugging!!
     sym_set_int_param(env, "do_primal_heuristic", FALSE);
     sym_set_int_param(env, "verbosity", -2);
     sym_set_int_param(env, "prep_level", -1);
     sym_set_int_param(env, "max_active_nodes", maxThreadsLL);
     sym_set_int_param(env, "tighten_root_bounds", FALSE);
     sym_set_int_param(env, "max_sp_size", 100);
     sym_set_int_param(env, "do_reduced_cost_fixing", FALSE);
     if (whichCutsLL == 0){
	sym_set_int_param(env, "generate_cgl_cuts", FALSE);
     }else{
	sym_set_int_param(env, "generate_cgl_gomory_cuts", GENERATE_DEFAULT);
     }
     if (whichCutsLL == 1){
	sym_set_int_param(env, "generate_cgl_knapsack_cuts", 
			  DO_NOT_GENERATE);
	sym_set_int_param(env, "generate_cgl_probing_cuts", 
			  DO_NOT_GENERATE);
	sym_set_int_param(env, "generate_cgl_clique_cuts", 
			  DO_NOT_GENERATE);
	sym_set_int_param(env, "generate_cgl_twomir_cuts", 
			  DO_NOT_GENERATE);
	sym_set_int_param(env, "generate_cgl_flowcover_cuts", 
			  DO_NOT_GENERATE);
     }
  }else if (feasCheckSolver == "CPLEX"){
#ifdef USE_CPLEX
     lSolver->setHintParam(OsiDoReducePrint);
     lSolver->messageHandler()->setLogLevel(0);
     CPXENVptr cpxEnv = 
	dynamic_cast<OsiCpxSolverInterface*>(lSolver)->getEnvironmentPtr();
     assert(cpxEnv);
     CPXsetintparam(cpxEnv, CPX_PARAM_SCRIND, CPX_OFF);
     CPXsetintparam(cpxEnv, CPX_PARAM_THREADS, maxThreadsLL);
#endif
  }
  
  if (warmStartLL && feasCheckSolver == "SYMPHONY"){
     lSolver->resolve();
     setWarmStart(lSolver->getWarmStart());
  }else{
     lSolver->branchAndBound();
  }

  const double * sol = model_->solver()->getColSolution();
  double objVal(lSolver->getObjValue() * model_->getLowerObjSense());
  
  MibSTreeNode * node = static_cast<MibSTreeNode *>(model_->activeNode_);
  MibSTreeNode * parent = 
    static_cast<MibSTreeNode *>(model_->activeNode_->getParent());

  if((!node->isBoundSet()) 
     && (node->getIndex() != 0)){
    double parentBound = parent->getLowerUB();
    node->setLowerUB(parentBound);
    node->setIsBoundSet(true);
  }
  
  if(objVal > node->getLowerUB()){
    
    node->setLowerUB(objVal);
    node->setIsBoundSet(true);
    
  }

  double etol(model_->etol_);
  double lowerObj = getLowerObj(sol, model_->getLowerObjSense());  

  int lN(model_->lowerDim_); // lower-level dimension
  int uN(model_->upperDim_); // lower-level dimension
  if(!optLowerSolution_)
    optLowerSolution_ = new double[lN];

  if(!optLowerSolutionOrd_)
    optLowerSolutionOrd_ = new double[lN];
  
  CoinZeroN(optLowerSolution_, lN);
  CoinZeroN(optLowerSolutionOrd_, lN);
  int * lowerColInd = model_->getLowerColInd();
  int * upperColInd = model_->getUpperColInd();

  int index(0);
  
  if(0){
    std::cout << "objVal: " << objVal << std::endl;
    std::cout << "lowerObj: " << lowerObj << std::endl;
  }

  if(fabs(objVal - lowerObj) < etol){
     /** Current solution is bilevel feasible **/
     
     const double * values = lSolver->getColSolution();
     int lN(model_->getLowerDim());
     int i(0);
     
     // May want to take out this update and keep current - both optimal
     // changed this 7/1 to allow for continuous vars
     /*
     for(i = 0; i < lN; i++){
	lowerSolution_[i] = (double) floor(values[i] + 0.5);
     } 
     */
 
    for(i = 0; i < lN; i++){
	if(lSolver->isInteger(i))
	   lowerSolution_[i] = (double) floor(values[i] + 0.5);
	else
	   lowerSolution_[i] = (double) values[i];
     } 

     isBilevelFeasible_ = true;
     useBilevelBranching_ = false;
     
  }else if (lSolver->isProvenOptimal()){
     /** Current solution is not bilevel feasible, 
	 but we may still have a solution **/
     
     //std::cout << "Solution is not bilevel feasible." << std::endl;

     const double * values = lSolver->getColSolution();
     int lN(model_->getLowerDim());
     int i(0);

     //added this 7/1 to store y* for val func cut
     for(i = 0; i < lN; i++){
	if(lSolver->isInteger(i))
	   optLowerSolution_[i] = (double) floor(values[i] + 0.5);
	else
	   optLowerSolution_[i] = (double) values[i];
     }
     
     int numCols = model_->solver()->getNumCols();
     int pos(0);

#if 1
     for(i = 0; i < numCols; i++){
	if ((pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd)) >= 0){
	   optLowerSolutionOrd_[pos] = optLowerSolution_[pos];
	}
     }
#else
     double upperObj(0);
     double * newSolution = new double[numCols];  
     const double * upperObjCoeffs = model_->solver()->getObjCoefficients();
     for(i = 0; i < numCols; i++){
	pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd);
	if(pos < 0){
	   pos = model_->bS_->binarySearch(0, uN - 1, i, upperColInd);
	   newSolution[i] = sol[i];
	}
	else{
	   newSolution[i] = optLowerSolution_[pos];
	   optLowerSolutionOrd_[pos] = optLowerSolution_[pos];
	}
	upperObj += newSolution[i] * upperObjCoeffs[i];
     }

     if(model_->checkUpperFeasibility(newSolution)){
	MibSSolution *mibsSol = new MibSSolution(numCols, newSolution,
						 upperObj,
						 model_);
	
	model_->storeSolution(BlisSolutionTypeHeuristic, mibsSol);
     }
     delete [] newSolution;
#endif	  
     
     /* run a heuristic to find a better feasible solution */
     heuristic_->findHeuristicSolutions();


     isBilevelFeasible_ = false;
     if(cutStrategy != 1)
       useBilevelBranching_ = true;
  }

  //delete lSolver;
  
}
Example #10
0
void ModelScenario(const char * const name )
{
	OsiClpSolverInterface *osiClp1 = new OsiClpSolverInterface();
	double INF=osiClp1->getInfinity();

	// example of direct interfaces for scenario generation

    /* Model dimensions */
    int nels=44; // ncol=27, nrow=9

	/* Sparse matrix data...organized by row */
    int mrow[]={ 0, 0, 0, 0, 0,
		1, 1, 1, 1,
		2, 2, 2,
		3, 3, 3, 3, 3,
		4, 4, 4, 4,
		5, 5, 5, 5, 5, 5,
		6, 6, 6, 6, 6,
		7, 7, 7, 7, 7, 7,
		8, 8, 8, 8, 8, 8 };
	  int mcol[]={ 0, 1, 2, 3, 4,
		5, 6, 7, 8,
		9,10, 11,
		12, 13, 14, 15, 16,
		0,        12, 17, 18,
		1, 5, 9,  13, 19, 20,
		2, 6,     14, 21, 22,
		3, 7, 10, 15, 23, 24,
		4, 8, 11, 16, 25, 26 };

    double dels[] = { 1.0, 1.0, 1.0, 1.0, 1.0,
		1.0, 1.0, 1.0, 1.0,
		1.0, 1.0, 1.0,
		1.0, 1.0, 1.0, 1.0, 1.0,
		16.0,              9.0, -1.0, 1.0,
		15.0, 10.0,  5.0, 11.0, -1.0, 1.0,
		28.0, 14.0,       22.0, -1.0, 1.0,
		23.0, 15.0,  7.0, 17.0, -1.0, 1.0,
		81.0, 57.0, 29.0, 55.0, -1.0, 1.0 };

    /* Objective */
    double dobj[]={ 18.0, 21.0, 18.0, 16.0, 10.0, 15.0, 16.0, 14.0, 9.0,
		10.0,  9.0,  6.0, 17.0, 16.0, 17.0, 15.0, 10.0, 0.0,
		13.0,  0.0, 13.0,  0.0,  7.0,  0.0,  7.0,  0.0, 1.0 };

    /* Column bounds */
    double dclo[]={ 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,
		0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,
		0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0 };



    double dcup[]={ INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,
		INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,
		INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF };

    /* Row bounds */
    double drlo[]={ -INF, -INF, -INF, -INF,  0.0, 4.0, 0.0, 8.0, 10.0 };
    double drup[]={ 10.0, 19.0, 25.0, 15.0,  0.0, 7.0, 0.0, 8.0, 90.0 };

    /* Stages */
    int nstg=2;
    int n_first_stg_rows=4;
    int rstg[]={ 0,0,0,0,1,1,1,1,1 };
    int cstg[]={ 0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,1,
		1,1,1,1,1,1,1,1,1 };

    /* Stochastic data */
    int nindp=5;
    int nsamp[]={ 5, 2, 5, 5, 3 };
    double demand[]={ 200, 220, 250, 270, 300,
		50, 150,
		140, 160, 180, 200, 220,
		10, 50, 80, 100, 340,
		580, 600, 620 };
    double dprobs[]={ 0.2, 0.05, 0.35, 0.2, 0.2,
		0.3, 0.7,
		0.1, 0.2, 0.4, 0.2, 0.1,
		0.2, 0.2, 0.3, 0.2, 0.1,
		0.1, 0.8, 0.1 };

    /* local variables */
    int ns=1,ii,iii,jj,*indx,*incr;
    double dp=1.0;

    for (ii=0;ii<nindp;ii++) ns *= nsamp[ii];     /* Compute number of scenarios */


	// initialize SmiModel
	SmiScnModel *smiModel = new SmiScnModel();
	smiModel->setOsiSolverHandle(*osiClp1);

	// set core model using Osi interface
	OsiClpSolverInterface ocsi;
	ocsi.loadProblem(CoinPackedMatrix( 1,mrow,mcol,dels,nels),dclo,dcup,dobj,drlo,drup);
	SmiCoreData *osiCore = new SmiCoreData(&ocsi,nstg,cstg,rstg);

	cout << "ModelScenario: Created CoreData" << endl;

	// Coin structures for scenario updates to right hand sides
	CoinPackedVector cpv_rlo;
	CoinPackedVector cpv_rup;

    // initialize right hand side data for first scenario
    indx = (int *) malloc( (1+nindp)*sizeof(int) );
    memset( indx,0,(1+nindp)*sizeof(int));
    for (jj=0;jj<nindp;jj++) {
		indx[jj+1] += indx[jj] + nsamp[jj];
		dp *= dprobs[ indx[jj] ];

		drlo[n_first_stg_rows + jj] = demand[ indx[jj] ];
		drup[n_first_stg_rows + jj] = demand[ indx[jj] ];

		cpv_rlo.insert(n_first_stg_rows + jj,demand[ indx[jj] ]);
		cpv_rup.insert(n_first_stg_rows + jj,demand[ indx[jj] ]);
    }

	cout << "ModelScenario: Adding " << ns << " scenarios" << endl;

	// first scenario
	int anc = 0;
	int branch = 1;
	int	is = smiModel->generateScenario(osiCore,NULL,NULL,NULL,NULL,
									&cpv_rlo,&cpv_rup,branch,anc,dp);



	/***** ...main loop to generate scenarios from discrete random variables
		For each scenario index ii:
        If the sample size nsamp[jj] divides the scenario index ii,
		reverse the increment direction incr[jj]
		and increase the random variable index jj by 1.
        Increment the jj'th random variable by incr[jj]
		and generate new sample data.
    ***** */

    /* sample space increment initialized to 1 */
    incr = (int *) malloc( nindp*sizeof(int) );
    for (jj=0;jj<nindp;jj++) incr[jj] = 1;

    for (int iss=1;iss<ns;iss++) {
		iii=iss; jj=0;
		while ( !(iii%nsamp[jj]) ) {
			iii /= nsamp[jj];
			incr[jj] = -incr[jj];
			jj++;
		}
		dp /= dprobs[ indx[jj] ];
		indx[jj] += incr[jj];
		dp *= dprobs[ indx[jj] ];

		// set data
		drlo[n_first_stg_rows + jj] = demand[ indx[jj] ];
		drup[n_first_stg_rows + jj] = demand[ indx[jj] ];

		cpv_rlo.setElement(cpv_rlo.findIndex(n_first_stg_rows + jj),demand[ indx[jj] ]);
		cpv_rup.setElement(cpv_rup.findIndex(n_first_stg_rows + jj),demand[ indx[jj] ]);

		// genScenario
		is = smiModel->generateScenario(osiCore,NULL,NULL,NULL,NULL,
			&cpv_rlo,&cpv_rup,branch,anc,dp);


	}

	assert(ns==smiModel->getNumScenarios());
	cout << "ModelScenario: Finished adding scenarios" << endl;



	// load problem data into OsiSolver
	smiModel->loadOsiSolverData();
	// get Osi pointer
	OsiSolverInterface *smiOsi = smiModel->getOsiSolverInterface();
	// set some parameters
	smiOsi->setHintParam(OsiDoPresolveInInitial,true);
	smiOsi->setHintParam(OsiDoScale,true);
	smiOsi->setHintParam(OsiDoCrash,true);
	// solve using Osi Solver
	smiOsi->initialSolve();
	// test optimal value
    	assert(fabs(smiOsi->getObjValue()-1566.042)<0.01);

	// test solutions
	const double *dsoln = smiOsi->getColSolution();
	double objSum = 0.0;

	/* The canonical way to traverse the tree:
	   For each scenario, get the leaf node.
	   Then get the parent.  Repeat until parent is NULL.
	   (Only the root node has a NULL parent.)
	 */


	for(is=0; is<ns; ++is)
	{
		/* this loop calculates the scenario objective value */
		double scenSum = 0.0;

		// start with leaf node
		SmiScnNode *node = smiModel->getLeafNode(is);

		// leaf node probability is the scenario probability
		double scenprob = node->getModelProb();

		while (node != NULL)
		{

			// getColStart returns the starting index of node in OSI model
			for(int j=node->getColStart(); j<node->getColStart()+node->getNumCols(); ++j)
			{
				// getCoreColIndex returns the corresponding Core index
				// in the original (user's) ordering
				scenSum += dobj[node->getCoreColIndex(j)]*dsoln[j];


			}
			// get parent of node
			node = node->getParent();
		}
		objSum += scenSum*scenprob;
	}

	assert(fabs(smiOsi->getObjValue()-objSum) < 0.01);

		// print results
		printf("Solved stochastic program %s\n", name);
		printf("Number of rows: %d\n",smiOsi->getNumRows());
		printf("Number of cols: %d\n",smiOsi->getNumCols());
		printf("Optimal value: %g\n",smiOsi->getObjValue());

}
Example #11
0
void ModelDiscrete(const char * const name)
{
	// example of direct interfaces for discrete distribution

	OsiClpSolverInterface *osiClp1 = new OsiClpSolverInterface();
	double INF=osiClp1->getInfinity();

    /* Model dimensions */
    int nels=44; // ncol=27, nrow=9

	/* Sparse matrix data...organized by row */
    int mrow[]={ 0, 0, 0, 0, 0,
		1, 1, 1, 1,
		2, 2, 2,
		3, 3, 3, 3, 3,
		4, 4, 4, 4,
		5, 5, 5, 5, 5, 5,
		6, 6, 6, 6, 6,
		7, 7, 7, 7, 7, 7,
		8, 8, 8, 8, 8, 8 };
	  int mcol[]={ 0, 1, 2, 3, 4,
		5, 6, 7, 8,
		9,10, 11,
		12, 13, 14, 15, 16,
		0,        12, 17, 18,
		1, 5, 9,  13, 19, 20,
		2, 6,     14, 21, 22,
		3, 7, 10, 15, 23, 24,
		4, 8, 11, 16, 25, 26 };

    double dels[] = { 1.0, 1.0, 1.0, 1.0, 1.0,
		1.0, 1.0, 1.0, 1.0,
		1.0, 1.0, 1.0,
		1.0, 1.0, 1.0, 1.0, 1.0,
		16.0,              9.0, -1.0, 1.0,
		15.0, 10.0,  5.0, 11.0, -1.0, 1.0,
		28.0, 14.0,       22.0, -1.0, 1.0,
		23.0, 15.0,  7.0, 17.0, -1.0, 1.0,
		81.0, 57.0, 29.0, 55.0, -1.0, 1.0 };

    /* Objective */
    /* Objective */
    double dobj[]={ 18.0, 21.0, 18.0, 16.0, 10.0, 15.0, 16.0, 14.0, 9.0,
		10.0,  9.0,  6.0, 17.0, 16.0, 17.0, 15.0, 10.0, 0.0,
		13.0,  0.0, 13.0,  0.0,  7.0,  0.0,  7.0,  0.0, 1.0 };

    /* Column bounds */
    double dclo[]={ 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,
		0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,
		0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0 };



    double dcup[]={ INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,
		INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,
		INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF,  INF };

    /* Row bounds */
    double drlo[]={ -INF, -INF, -INF, -INF,  0.0, 4.0, 0.0, 8.0, 10.0 };
    double drup[]={ 10.0, 19.0, 25.0, 15.0,  0.0, 7.0, 0.0, 8.0, 90.0 };

    /* Stages */
    int nstg=2;
    int n_first_stg_rows=4;
    int rstg[]={ 0,0,0,0,1,1,1,1,1 };
    int cstg[]={ 0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,1,
		1,1,1,1,1,1,1,1,1 };

    /* Stochastic data */
    int nindp=5;
    int nsamp[]={ 5, 2, 5, 5, 3 };
    double demand[]={ 200, 220, 250, 270, 300,
		50, 150,
		140, 160, 180, 200, 220,
		10, 50, 80, 100, 340,
		580, 600, 620 };
    double dprobs[]={ 0.2, 0.05, 0.35, 0.2, 0.2,
		0.3, 0.7,
		0.1, 0.2, 0.4, 0.2, 0.1,
		0.2, 0.2, 0.3, 0.2, 0.1,
		0.1, 0.8, 0.1 };

    /* local variables */
    int ii,jj;

	// initialize SmiModel
	SmiScnModel *smiModel = new SmiScnModel();
	smiModel->setOsiSolverHandle(*osiClp1);


	// set core model using Osi interface
	OsiClpSolverInterface ocsi;
	ocsi.loadProblem(CoinPackedMatrix( 1,mrow,mcol,dels,nels),dclo,dcup,dobj,drlo,drup);

	// core model
	SmiCoreData *smiCore = new SmiCoreData(&ocsi,nstg,cstg,rstg);

	cout << "ModelDiscrete: generated Core data" << endl;

	// Create discrete distribution
	SmiDiscreteDistribution *smiDD = new SmiDiscreteDistribution(smiCore);

	cout << "ModelDiscrete: adding random variables" << endl;

	int index=0;
	for (jj=0;jj<nindp;jj++)
	{
		SmiDiscreteRV *smiRV = new SmiDiscreteRV(1);
		for (ii=0;ii<nsamp[jj];ii++)
		{
			CoinPackedVector empty_vec;
			CoinPackedMatrix empty_mat;
			CoinPackedVector cpv_rlo ;
			CoinPackedVector cpv_rup ;
			cpv_rlo.insert(n_first_stg_rows + jj, demand[index+ii]);
			cpv_rup.insert(n_first_stg_rows + jj, demand[index+ii]);
			smiRV->addEvent(empty_mat,empty_vec,empty_vec,empty_vec,cpv_rlo,cpv_rup,dprobs[index+ii]);
			cpv_rlo.clear();
			cpv_rup.clear();
		}
		smiDD->addDiscreteRV(smiRV);
		index+=nsamp[jj];
	}

	assert(smiDD->getNumRV() == nindp);
	cout << "ModelDiscrete: added " << nindp << " random variables" << endl;



	cout << "ModelDiscrete: processing into scenarios" << endl;

	smiModel->processDiscreteDistributionIntoScenarios(smiDD);

	// load problem data into OsiSolver
	smiModel->loadOsiSolverData();
	// get Osi pointer
	OsiSolverInterface *smiOsi = smiModel->getOsiSolverInterface();
	// set some parameters
	smiOsi->setHintParam(OsiDoPresolveInInitial,true);
	smiOsi->setHintParam(OsiDoScale,true);
	smiOsi->setHintParam(OsiDoCrash,true);
	// solve using Osi Solver
	smiOsi->initialSolve();
	// test optimal value
    	assert(fabs(smiOsi->getObjValue()-1566.042)<0.01);

	// test solutions
	const double *dsoln = smiOsi->getColSolution();
	double objSum = 0.0;

	/* The canonical way to traverse the tree:
	   For each scenario, get the leaf node.
	   Then get the parent.  Repeat until parent is NULL.
	   (Only the root node has a NULL parent.)
	 */

	for(int is=0; is<smiModel->getNumScenarios(); ++is)
	{
		/* this loop calculates the scenario objective value */
		double scenSum = 0.0;

		// start with leaf node
		SmiScnNode *node = smiModel->getLeafNode(is);

		// leaf node probability is the scenario probability
		double scenprob = node->getModelProb();

		while (node != NULL)
		{
			// getColStart returns the starting index of node in OSI model
			for(int j=node->getColStart(); j<node->getColStart()+node->getNumCols(); ++j)
			{
				// getCoreColIndex returns the corresponding Core index
				// in the original (user's) ordering
				scenSum += dobj[node->getCoreColIndex(j)]*dsoln[j];


			}

			// get parent of node
			node = node->getParent();
		}
		objSum += scenSum*scenprob;
	}

	assert(fabs(smiOsi->getObjValue()-objSum) < 0.01);

		// print results
		printf("Solved stochastic program %s\n", name);
		printf("Number of rows: %d\n",smiOsi->getNumRows());
		printf("Number of cols: %d\n",smiOsi->getNumCols());
		printf("Optimal value: %g\n",smiOsi->getObjValue());


}
Example #12
0
int main(int argc, char **argv)
{
    VRPH_version();

    int i, j, k, n, status, num_attempts, *sol_buff, *IP_sol_buff;
    char in_file[200];
    double lambda, best_heur_sol=VRP_INFINITY;
    bool first_sol=false, bootstrap=false;;
    VRPSolution *fresh_solution;
    OsiSolverInterface *si;
    const double *x;
    int last_num_cols=0, route_id=0;
    time_t start, stop;
    int *orderings[MAX_ROUTES];
    for(i=0;i<MAX_ROUTES;i++)
        orderings[i]=NULL;
    

    // Set timing counters to 0
    heur_time=mip_time=0;

    // Check arguments
    if(argc<5)
    {
        fprintf(stderr,"Usage: %s -f input_file -n num_runs [-v,-b,-c max_columns -d cols_to_delete]\n",
            argv[0]);
        fprintf(stderr,"\t Will solve the problem num_solutions times and add the routes\n");
        fprintf(stderr,"\t to a set partitioning problem.\n");
        fprintf(stderr,"\t Other options:\n");
        fprintf(stderr,"\t -v runs in verbose mode\n");
        fprintf(stderr,"\t -b will use bootstrapping where we send the set partitioning\n"
                       "\t    solution back to the metaheuristic solver\n");
        fprintf(stderr,"\t -c max_columns will allow this many active columns/variables in the IP.\n");
        fprintf(stderr,"\t    Default value is max_columns=500\n");
        fprintf(stderr,"\t -d num_cols_to_delete will delete this many columns once we have too many\n");
        fprintf(stderr,"\t    in the IP. Default value is num_cols_to_delete=100\n");
        exit(-1);
    }

    // Set defaults
    verbose=false;
    max_columns=500;
    num_cols_to_delete=100;

    // Parse command line
    for(i=0;i<argc;i++)
    {
        if(strcmp(argv[i],"-f")==0)
            strcpy(in_file,argv[i+1]);
        if(strcmp(argv[i],"-n")==0)
            num_attempts=atoi(argv[i+1]);
        if(strcmp(argv[i],"-v")==0)
            verbose=true;
         if(strcmp(argv[i],"-b")==0)
            bootstrap=true;
         if(strcmp(argv[i],"-c")==0)
             max_columns=atoi(argv[i+1]);
         if(strcmp(argv[i],"-d")==0)
             num_cols_to_delete=atoi(argv[i+1]);
    }

    // This is the # of non-VRPH_DEPOT nodes
    n=VRPGetDimension(in_file);
    // This will be used to import/export solutions
    fresh_solution = new VRPSolution(n);
    // Create buffers for importing solutions
    sol_buff= new int[n+2];
    IP_sol_buff = new int[n+2];

    // Declare an OSI interface
    si=new OsiGlpkSolverInterface;
    si->setIntParam(OsiNameDiscipline,2);

    for(i=0;i<n;i++)
    {
        si->addRow(0,NULL,NULL,1,1);
    }

    // Declare a VRP of the right size and import the file
    VRP V(n);
    ClarkeWright CW(n);
    VRPRoute route(n);
    V.read_TSPLIB_file(in_file);
    // Set up a "route warehouse" to store the routes to be added to the IP
    V.route_wh=new VRPRouteWarehouse(HASH_TABLE_SIZE);
  
    // Set up a minimization problem
    si->setObjSense(1);
    // Set to error only output
    si->setHintParam(OsiDoReducePrint,true, OsiHintDo);
    // Unfortunately GLPK still prints out something regarding the conflict graph

    for(i=0;i<num_attempts;i++)
    {
        if(i==0 || !bootstrap) 
        {
            lambda=.5+1.5*lcgrand(0);
            // Start with a clean VRP object
            V.reset();
            CW.Construct(&V, lambda, false);
            if(verbose)
                printf("CW solution %d[%5.3f]: %f\n",i,lambda,V.get_total_route_length()-V.get_total_service_time());
        }
        else
            // Use the solution from the IP
            V.import_solution_buff(IP_sol_buff);
        
        // Run VRPH's RTR algorithm to improve the solution
        start=clock();
        V.RTR_solve(ONE_POINT_MOVE | TWO_POINT_MOVE | TWO_OPT | VRPH_USE_NEIGHBOR_LIST,
            30, 5, 2, .01, 30, VRPH_LI_PERTURB, VRPH_FIRST_ACCEPT,false);
        stop=clock();
        heur_time += (stop-start);

        if(verbose)
            printf("RTR Metaheuristic found solution %5.3f\n",V.get_total_route_length()-V.get_total_service_time());
        
        // The RTR algorithm keeps a "warehouse" of the best solutions discovered during
        // the algorithm's search
        // Now go through the solutions in the solution warehouse and add the new routes
        // discovered to the IP
        for(j=0;j<V.solution_wh->num_sols;j++)
        {
            // Import solution j from the warehouse 
            V.import_solution_buff(V.solution_wh->sols[j].sol);
                
            if(V.get_total_route_length()-V.get_total_service_time() < best_heur_sol)
                best_heur_sol = V.get_total_route_length()-V.get_total_service_time() ;

            // Now add the routes from this solution to the IP
            for(k=1;k<=V.get_total_number_of_routes();k++)
            {
                // Clean up the route by running INTRA_ROUTE optimizations only
                // using the route_search method of the different local search
                // heuristics, accepting improving moves only (VRPH_DOWNHILL)
                OnePointMove OPM;
                TwoOpt TO;
                ThreeOpt ThO;
                while(OPM.route_search(&V,k,k,VRPH_DOWNHILL|VRPH_INTRA_ROUTE_ONLY )){}
                while(TO.route_search(&V,k,k,VRPH_DOWNHILL|VRPH_INTRA_ROUTE_ONLY  )){};
                while(ThO.route_search(&V,k,VRPH_DOWNHILL|VRPH_INTRA_ROUTE_ONLY )){};

                // Copy route k from the solution to the VRPRoute R
                V.update_route(k,&route);
                route.create_name();
                // Add it to the "route warehouse" - this uses a hash table to keep track
                // of duplicate columns
                status=V.route_wh->add_route(&route);

                if(status!=DUPLICATE_ROUTE)
                {
                    // This route is not currently in the WH and so it cannot be in the
                    // set partitioning problem
                    //OSI_add_route(si,&V,&route);
                    OSI_add_route(si,&V,&route,route_id,orderings);
                    route_id++;
                }
            }
            
            // Set the row RHS's if we need to
            if(first_sol)
            {
                first_sol=false;
                for(int rownum=0;rownum<n;rownum++)
                    si->setRowBounds(rownum,1,1);
                // Note that changing this to >= would be a set covering problem
                // where each customer can be visited by more than one route
            }
        }

        // Now erase all the solutions from the WH
        V.solution_wh->liquidate();

        if(verbose)
        {
            printf("Attempt %02d:  Solving IP with %d columns\n",i,si->getNumCols());
            printf("%d routes in the WH\n",V.route_wh->num_unique_routes);
        }

        // Solve the current set partitioning problem using the MIP solver
        start=clock();
        si->branchAndBound();
        stop=clock();
        mip_time += (stop-start);

        double opt=si->getObjValue();
        x=si->getColSolution();
        last_num_cols=si->getNumCols();
        if(verbose)
            printf("Optimal solution (%d columns) is %f\n",last_num_cols,opt);

        
        // Now recover the solution from the IP solution
        OSI_recover_solution(si, orderings, IP_sol_buff);
       
        if(verbose)
            printf("IP solution has obj. function value: %5.2f\n"
            "Best heuristic  obj. function value: %5.2f\n",
            si->getObjValue(),best_heur_sol);     
    }

    if(verbose)
        printf(
        "\nResults\n"
        "--------\n"
        "After %d runs\n"
        "IP solution has obj. function value: %5.2f\n"
        "Best heuristic  obj. function value: %5.2f\n",
        num_attempts,si->getObjValue(),best_heur_sol);

    // print to stderr since GLPK prints "conflict graph" to stdout (a known bug...)
    // best_heur_sol best_mip_sol heur_time mip_time
    fprintf(stderr,"%5.3f %5.3f %5.3f %5.3f\n", best_heur_sol, si->getObjValue(),
        (double)(heur_time)/CLOCKS_PER_SEC, (double)(mip_time)/CLOCKS_PER_SEC);

    delete V.route_wh;
    delete fresh_solution;
    delete [] sol_buff;
    delete [] IP_sol_buff;
    delete si;

    for(i=0;i<MAX_ROUTES;i++)
        if(orderings[i])
            delete [] orderings[i];

     
    return 0;
}
Example #13
0
OsiSolverInterface* cpropagation_preprocess(CPropagation *cp, int nindexes[])
{
    if(cp->varsToFix == 0)
    {
        /* printf("There are no variables to remove from the problem!\n"); */
        return NULL; /* returns a pointer to original solver */
    }

    const double *colLb = problem_vars_lower_bound(cp->problem), *colUb = problem_vars_upper_bound(cp->problem);
    const double *objCoef = problem_vars_obj_coefs(cp->problem);
    const char *ctype = problem_vars_type(cp->problem);

    double sumFixedObj = 0.0; /* stores the sum of objective coefficients of all variables fixed to 1 */

    OsiSolverInterface *preProcSolver = new OsiClpSolverInterface();
    preProcSolver->setIntParam(OsiNameDiscipline, 2);
    preProcSolver->messageHandler()->setLogLevel(0);
    preProcSolver->setHintParam(OsiDoReducePrint,true,OsiHintTry);
    //preProcSolver->setObjName(cp->solver->getObjName());

    for(int i = 0, j = 0; i < problem_num_cols(cp->problem); i++)
    {
        nindexes[i] = -1;
        if(cp->isToFix[i] == UNFIXED)
        {
            preProcSolver->addCol(0, NULL, NULL, colLb[i], colUb[i], objCoef[i]);
            preProcSolver->setColName(j, problem_var_name(cp->problem, i));
            if(problem_var_type(cp->problem, i) == CONTINUOUS)
                preProcSolver->setContinuous(j);
            else 
                preProcSolver->setInteger(j);
            nindexes[i] = j++;
        }
        else if(cp->isToFix[i] == ACTIVATE)
            sumFixedObj += objCoef[i];
    }

    if(fabs(sumFixedObj) > EPS)
    {
        /* adding a variable with cost equals to the sum of all coefficients of variables fixed to 1 */
        preProcSolver->addCol(0, NULL, NULL, 1.0, 1.0, sumFixedObj);
        preProcSolver->setColName(preProcSolver->getNumCols()-1, "sumFixedObj");
        preProcSolver->setInteger(preProcSolver->getNumCols()-1);
    }

    for(int idxRow = 0; idxRow < problem_num_rows(cp->problem); idxRow++)
    {
        const int nElements = problem_row_size(cp->problem, idxRow);
        const int *idxs = problem_row_idxs(cp->problem, idxRow);
        const double *coefs = problem_row_coefs(cp->problem, idxRow);
        vector< int > vidx; vidx.reserve(problem_num_cols(cp->problem));
        vector< double > vcoef; vcoef.reserve(problem_num_cols(cp->problem));
        double activeCoefs = 0.0;

        for(int i = 0; i < nElements; i++)
        {
            if(cp->isToFix[idxs[i]] == UNFIXED)
            {
                assert(nindexes[idxs[i]] >= 0 && nindexes[idxs[i]] < problem_num_cols(cp->problem));
                vidx.push_back(nindexes[idxs[i]]);
                vcoef.push_back(coefs[i]);
            }
            else if(cp->isToFix[idxs[i]] == ACTIVATE)
            	activeCoefs += coefs[i];
        }

        if(!vidx.empty())
        {
        	double rlb, rub;
        	const char sense = problem_row_sense(cp->problem, idxRow);
        	
        	if(sense == 'E')
            {
                rlb = problem_row_rhs(cp->problem, idxRow) - activeCoefs;
                rub = problem_row_rhs(cp->problem, idxRow) - activeCoefs;
            }
        	else if(sense == 'L')
            {
                rlb = preProcSolver->getInfinity();
                rub = problem_row_rhs(cp->problem, idxRow) - activeCoefs;
            }
        	else if(sense == 'G')
            {
                rlb = problem_row_rhs(cp->problem, idxRow) - activeCoefs;
                rub = preProcSolver->getInfinity();
            }
        	else
        	{
        		fprintf(stderr, "Error: invalid type of constraint!\n");
        		exit(EXIT_FAILURE);
        	}

        	preProcSolver->addRow((int)vcoef.size(), &vidx[0], &vcoef[0], rlb, rub);
            preProcSolver->setRowName(idxRow, problem_row_name(cp->problem, idxRow));
        }
	}

    return preProcSolver;
}
Example #14
0
int doBaCParam (CoinParam *param)

{
    assert (param != 0) ;
    CbcGenParam *genParam = dynamic_cast<CbcGenParam *>(param) ;
    assert (genParam != 0) ;
    CbcGenCtlBlk *ctlBlk = genParam->obj() ;
    assert (ctlBlk != 0) ;
    CbcModel *model = ctlBlk->model_ ;
    assert (model != 0) ;
    /*
      Setup to return nonfatal/fatal error (1/-1) by default.
    */
    int retval ;
    if (CoinParamUtils::isInteractive()) {
        retval = 1 ;
    } else {
        retval = -1 ;
    }
    ctlBlk->setBaBStatus(CbcGenCtlBlk::BACAbandon, CbcGenCtlBlk::BACmInvalid,
                         CbcGenCtlBlk::BACwNotStarted, false, 0) ;
    /*
      We ain't gonna do squat without a good model.
    */
    if (!ctlBlk->goodModel_) {
        std::cout << "** Current model not valid!" << std::endl ;
        return (retval) ;
    }
    /*
      Start the clock ticking.
    */
    double time1 = CoinCpuTime() ;
    double time2 ;
    /*
      Create a clone of the model which we can modify with impunity. Extract
      the underlying solver for convenient access.
    */
    CbcModel babModel(*model) ;
    OsiSolverInterface *babSolver = babModel.solver() ;
    assert (babSolver != 0) ;
# if CBC_TRACK_SOLVERS > 0
    std::cout
        << "doBaCParam: initial babSolver is "
        << std::hex << babSolver << std::dec
        << ", log level " << babSolver->messageHandler()->logLevel()
        << "." << std::endl ;
# endif
    /*
      Solve the root relaxation. Bail unless it solves to optimality.
    */
    if (!solveRelaxation(&babModel)) {
        ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBareRoot) ;
        return (0) ;
    }
# if COIN_CBC_VERBOSITY > 0
    std::cout
        << "doBaCParam: initial relaxation z = "
        << babSolver->getObjValue() << "." << std::endl ;
# endif
    /*
      Are we up for fixing variables based on reduced cost alone?
    */
    if (ctlBlk->djFix_.action_ == true) {
        reducedCostHack(babSolver, ctlBlk->djFix_.threshold_) ;
    }
    /*
      Time to consider preprocessing. We'll do a bit of setup before getting to
      the meat of the issue.

      preIppSolver will hold a clone of the unpreprocessed constraint system.
      We'll need it when we postprocess. ippSolver holds the preprocessed
      constraint system.  Again, we clone it and give the clone to babModel for
      B&C. Presumably we need an unmodified copy of the preprocessed system to
      do postprocessing, but the copy itself is hidden inside the preprocess
      object.
    */
    OsiSolverInterface *preIppSolver = 0 ;
    CglPreProcess ippObj ;
    bool didIPP = false ;

    int numberChanged = 0 ;
    int numberOriginalColumns = babSolver->getNumCols() ;
    CbcGenCtlBlk::IPPControl ippAction = ctlBlk->getIPPAction() ;

    if (!(ippAction == CbcGenCtlBlk::IPPOff ||
            ippAction == CbcGenCtlBlk::IPPStrategy)) {
        double timeLeft = babModel.getMaximumSeconds() ;
        preIppSolver = babSolver->clone() ;
        OsiSolverInterface *ippSolver ;
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: clone made prior to IPP is "
            << std::hex << preIppSolver << std::dec
            << ", log level " << preIppSolver->messageHandler()->logLevel()
            << "." << std::endl ;
#   endif

        preIppSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ;
        ippObj.messageHandler()->setLogLevel(babModel.logLevel()) ;

        CglProbing probingGen ;
        probingGen.setUsingObjective(true) ;
        probingGen.setMaxPass(3) ;
        probingGen.setMaxProbeRoot(preIppSolver->getNumCols()) ;
        probingGen.setMaxElements(100) ;
        probingGen.setMaxLookRoot(50) ;
        probingGen.setRowCuts(3) ;
        ippObj.addCutGenerator(&probingGen) ;
        /*
          For preProcessNonDefault, the 2nd parameter controls the conversion of
          clique and SOS constraints. 0 does nothing, -1 converts <= to ==, and
          2 and 3 form SOS sets under strict and not-so-strict conditions,
          respectively.
        */
        int convert = 0 ;
        if (ippAction == CbcGenCtlBlk::IPPEqual) {
            convert = -1 ;
        } else if (ippAction == CbcGenCtlBlk::IPPEqualAll) {
            convert = -2 ;
        } else if (ippAction == CbcGenCtlBlk::IPPSOS) {
            convert = 2 ;
        } else if (ippAction == CbcGenCtlBlk::IPPTrySOS) {
            convert = 3 ;
        }

        ippSolver = ippObj.preProcessNonDefault(*preIppSolver, convert, 10) ;
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: solver returned from IPP is "
            << std::hex << ippSolver << std::dec ;
        if (ippSolver) {
            std::cout
                << ", log level " << ippSolver->messageHandler()->logLevel() ;
        }
        std::cout << "." << std::endl ;
#   endif
        /*
          ippSolver == 0 is success of a sort --- integer preprocess has found the
          problem to be infeasible or unbounded. Need to think about how to indicate
          status.
        */
        if (!ippSolver) {
            std::cout
                << "Integer preprocess says infeasible or unbounded" << std::endl ;
            delete preIppSolver ;
            ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPP) ;
            return (0) ;
        }
#   if COIN_CBC_VERBOSITY > 0
        else {
            std::cout
                << "After integer preprocessing, model has "
                << ippSolver->getNumRows()
                << " rows, " << ippSolver->getNumCols() << " columns, and "
                << ippSolver->getNumElements() << " elements." << std::endl ;
        }
#   endif

        preIppSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;
        ippSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;

        if (ippAction == CbcGenCtlBlk::IPPSave) {
            ippSolver->writeMps("presolved", "mps", 1.0) ;
            std::cout
                << "Integer preprocessed model written to `presolved.mps' "
                << "as minimisation problem." << std::endl ;
        }

        OsiSolverInterface *osiTmp = ippSolver->clone() ;
        babModel.assignSolver(osiTmp) ;
        babSolver = babModel.solver() ;
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: clone of IPP solver passed to babModel is "
            << std::hex << babSolver << std::dec
            << ", log level " << babSolver->messageHandler()->logLevel()
            << "." << std::endl ;
#   endif
        if (!solveRelaxation(&babModel)) {
            delete preIppSolver ;
            ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPPRelax) ;
            return (0) ;
        }
#   if COIN_CBC_VERBOSITY > 0
        std::cout
            << "doBaCParam: presolved relaxation z = "
            << babSolver->getObjValue() << "." << std::endl ;
#   endif
        babModel.setMaximumSeconds(timeLeft - (CoinCpuTime() - time1)) ;
        didIPP = true ;
    }
    /*
      At this point, babModel and babSolver hold the constraint system we'll use
      for B&C (either the original system or the preprocessed system) and we have
      a solution to the lp relaxation.

      If we're using the COSTSTRATEGY option, set up priorities here and pass
      them to the babModel.
    */
    if (ctlBlk->priorityAction_ != CbcGenCtlBlk::BPOff) {
        setupPriorities(&babModel, ctlBlk->priorityAction_) ;
    }
    /*
      Install heuristics and cutting planes.
    */
    installHeuristics(ctlBlk, &babModel) ;
    installCutGenerators(ctlBlk, &babModel) ;
    /*
      Set up status print frequency for babModel.
    */
    if (babModel.getNumCols() > 2000 || babModel.getNumRows() > 1500 ||
            babModel.messageHandler()->logLevel() > 1)
        babModel.setPrintFrequency(100) ;
    /*
      If we've read in a known good solution for debugging, activate the row cut
      debugger.
    */
    if (ctlBlk->debugSol_.values_) {
        if (ctlBlk->debugSol_.numCols_ == babModel.getNumCols()) {
            babSolver->activateRowCutDebugger(ctlBlk->debugSol_.values_) ;
        } else {
            std::cout
                << "doBaCParam: debug file has incorrect number of columns."
                << std::endl ;
        }
    }
    /*
      Set ratio-based integrality gap, if specified by user.
    */
    if (ctlBlk->setByUser_[CbcCbcParam::GAPRATIO] == true) {
        double obj = babSolver->getObjValue() ;
        double gapRatio = babModel.getDblParam(CbcModel::CbcAllowableFractionGap) ;
        double gap = gapRatio * (1.0e-5 + fabs(obj)) ;
        babModel.setAllowableGap(gap) ;
        std::cout
            << "doBaCParam: Continuous objective = " << obj
            << ", so allowable gap set to " << gap << std::endl ;
    }
    /*
      A bit of mystery code. As best I can figure, setSpecialOptions(2) suppresses
      the removal of warm start information when checkSolution runs an lp to check
      a solution. John's comment, ``probably faster to use a basis to get integer
      solutions'' makes some sense in this context. Didn't try to track down
      moreMipOptions just yet.
    */
    babModel.setSpecialOptions(babModel.specialOptions() | 2) ;
    /*
      { int ndx = whichParam(MOREMIPOPTIONS,numberParameters,parameters) ;
        int moreMipOptions = parameters[ndx].intValue() ;
        if (moreMipOptions >= 0)
        { printf("more mip options %d\n",moreMipOptions);
          babModel.setSearchStrategy(moreMipOptions); } }
    */
    /*
      Begin the final run-up to branch-and-cut.

      Make sure that objects are set up in the solver. It's possible that whoever
      loaded the model into the solver also set up objects. But it's also
      entirely likely that none exist to this point (and interesting to note that
      IPP doesn't need to know anything about objects).
    */
    setupObjects(babSolver, didIPP, &ippObj) ;
    /*
      Set the branching method. We can't do this until we establish objects,
      because the constructor will set up arrays based on the number of objects,
      and there's no provision to set this information after creation. Arguably not
      good --- it'd be nice to set this in the prototype model that's cloned for
      this routine. In CoinSolve, shadowPriceMode is handled with the TESTOSI
      option.
    */
    OsiChooseStrong strong(babSolver) ;
    strong.setNumberBeforeTrusted(babModel.numberBeforeTrust()) ;
    strong.setNumberStrong(babModel.numberStrong()) ;
    strong.setShadowPriceMode(ctlBlk->chooseStrong_.shadowPriceMode_) ;
    CbcBranchDefaultDecision decision ;
    decision.setChooseMethod(strong) ;
    babModel.setBranchingMethod(decision) ;
    /*
      Here I've deleted a huge block of code that deals with external priorities,
      branch direction, pseudocosts, and solution. (PRIORITYIN) Also a block of
      code that generates C++ code.
    */
    /*
      Set up strategy for branch-and-cut. Note that the integer code supplied to
      setupPreProcessing is *not* compatible with the IPPAction enum. But at least
      it's documented. See desiredPreProcess_ in CbcStrategyDefault. `1' is
      accidentally equivalent to IPPOn.
    */

    if (ippAction == CbcGenCtlBlk::IPPStrategy) {
        CbcStrategyDefault strategy(true, 5, 5) ;
        strategy.setupPreProcessing(1) ;
        babModel.setStrategy(strategy) ;
    }
    /*
      Yes! At long last, we're ready for the big call. Do branch and cut. In
      general, the solver used to return the solution will not be the solver we
      passed in, so reset babSolver here.
    */
    int statistics = (ctlBlk->printOpt_ > 0) ? ctlBlk->printOpt_ : 0 ;
# if CBC_TRACK_SOLVERS > 0
    std::cout
        << "doBaCParam: solver at call to branchAndBound is "
        << std::hex << babModel.solver() << std::dec
        << ", log level " << babModel.solver()->messageHandler()->logLevel()
        << "." << std::endl ;
# endif
    babModel.branchAndBound(statistics) ;
    babSolver = babModel.solver() ;
# if CBC_TRACK_SOLVERS > 0
    std::cout
        << "doBaCParam: solver at return from branchAndBound is "
        << std::hex << babModel.solver() << std::dec
        << ", log level " << babModel.solver()->messageHandler()->logLevel()
        << "." << std::endl ;
# endif
    /*
      Write out solution to preprocessed model.
    */
    if (ctlBlk->debugCreate_ == "createAfterPre" &&
            babModel.bestSolution()) {
        CbcGenParamUtils::saveSolution(babSolver, "debug.file") ;
    }
    /*
      Print some information about branch-and-cut.
    */
# if COIN_CBC_VERBOSITY > 0
    std::cout
        << "Cuts at root node changed objective from "
        << babModel.getContinuousObjective()
        << " to " << babModel.rootObjectiveAfterCuts() << std::endl ;

    for (int iGen = 0 ; iGen < babModel.numberCutGenerators() ; iGen++) {
        CbcCutGenerator *generator = babModel.cutGenerator(iGen) ;
        std::cout
            << generator->cutGeneratorName() << " was tried "
            << generator->numberTimesEntered() << " times and created "
            << generator->numberCutsInTotal() << " cuts of which "
            << generator->numberCutsActive()
            << " were active after adding rounds of cuts" ;
        if (generator->timing()) {
            std::cout << " ( " << generator->timeInCutGenerator() << " seconds)" ;
        }
        std::cout << std::endl ;
    }
# endif

    time2 = CoinCpuTime();
    ctlBlk->totalTime_ += time2 - time1;
    /*
      If we performed integer preprocessing, time to back it out.
    */
    if (ippAction != CbcGenCtlBlk::IPPOff) {
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: solver passed to IPP postprocess is "
            << std::hex << babSolver << std::dec << "." << std::endl ;
#   endif
        ippObj.postProcess(*babSolver);
        babModel.assignSolver(preIppSolver) ;
        babSolver = babModel.solver() ;
#   if CBC_TRACK_SOLVERS > 0
        std::cout
            << "doBaCParam: solver in babModel after IPP postprocess is "
            << std::hex << babSolver << std::dec << "." << std::endl ;
#   endif
    }
    /*
      Write out postprocessed solution to debug file, if requested.
    */
    if (ctlBlk->debugCreate_ == "create" && babModel.bestSolution()) {
        CbcGenParamUtils::saveSolution(babSolver, "debug.file") ;
    }
    /*
      If we have a good solution, detach the solver with the answer. Fill in the
      rest of the status information for the benefit of the wider world.
    */
    bool keepAnswerSolver = false ;
    OsiSolverInterface *answerSolver = 0 ;
    if (babModel.bestSolution()) {
        babModel.setModelOwnsSolver(false) ;
        keepAnswerSolver = true ;
        answerSolver = babSolver ;
    }
    ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBAC,
                         keepAnswerSolver, answerSolver) ;
    /*
      And one last bit of information & statistics.
    */
    ctlBlk->printBaBStatus() ;
    std::cout << "    " ;
    if (keepAnswerSolver) {
        std::cout
            << "objective " << babModel.getObjValue() << "; " ;
    }
    std::cout
        << babModel.getNodeCount() << " nodes and "
        << babModel.getIterationCount() << " iterations - took "
        << time2 - time1 << " seconds" << std::endl ;

    return (0) ;
}