Exemple #1
0
MSIndexVector MSIntTableColumn::rangeGradeDown(const MSIndexVector &start_,const MSIndexVector &end_)
{
  if (MSView::model()!=0&&start_.length()>0&&start_.length()==end_.length())
   {
     MSIntVector &vector=*(MSIntVector *)_model;
     MSIndexVector index(vector.length());
     for (unsigned i=0;i<start_.length();i++)
      {
	MSIndexVector subIndex;
	subIndex.series(end_(i)-start_(i)+1,start_(i));
	MSIntVector subVector=MSIntVector::select(vector,subIndex);
	MSIndexVector sortedIndex=subVector.gradeDown();
	unsigned startIndex=start_(i);
	for (unsigned j=0;j<sortedIndex.length();j++)
	 {
	   index.replaceAt(startIndex+j,sortedIndex(j)+startIndex);
	 }
      }
     return index;
   }
  else return MSIndexVector::nullVector();
}
int main (int argc, char **argv) {

  IloEnv env;

  try {
    IloCplex cplex(env);
    IloTimer timer(env);

    const IloNum startTime = cplex.getCplexTime();

    parseCommandLine(argc, argv);
    printCommandLine(argc, argv);

    // set all default constraint weights as zero
    consWts["NonOperatorsAtMostOnce"]           = 0;
    consWts["StackDepthUpperBound"]             = 0;
    consWts["ExactlyOneUnknown"]                = 0;
    consWts["NoTwoConsecutiveMultiplications"]  = 0;  // note: this may be disabled if word "dozen" appears
    consWts["NoTwoConsecutiveDivisions"]        = 0;
    consWts["NoConsecutiveMultAndDiv"]          = 0;
    consWts["NoNegatives"]                      = 0;
    consWts["TypeConsistency"]                  = 0;
    consWts["EqualityFirstOrLast"]              = 0;
    consWts["IntConstantsImplyIntUnknown"]      = 0;
    consWts["PreserveOrderingInText"]           = 0;
    consWts["UnknownFirstOrLast"]               = 0;
    consWts["EqualityNextToUnknown"]            = 0;
    consWts["HasAddition"]                      = 0;
    consWts["HasSubtraction"]                   = 0;
    consWts["HasMultiplication"]                = 0;
    consWts["HasDivision"]                      = 0;

    // parse config file defining constraint weights
    parseConfigFile(param_wts_config_file);

    cout << "Starting IloTimer" << endl;
    timer.start();

    // parse arithmetic model parameters; note: this may override previously
    // set constraint weights
    if (strlen(arith_filename) > 0)
      parseInputFile(arith_filename);

    // set cplex paramters
    setCplexParameters(cplex);

    // import or build the model
    IloModel       model(env);
    IloObjective   obj(env);
    IloNumVarArray corevars(env);
    IloRangeArray  rngs(env);

    if (strlen(mip_filename) > 0) {
      cout << "------- Importing the model -------" << endl;
      cplex.importModel(model, mip_filename, obj, corevars, rngs);
      cout << "Model imported at " << (cplex.getCplexTime() - startTime) << " sec" << endl;
    }
    else {
      cout << "------- Building the model -------" << endl;
      buildArithmeticModel(model, obj, corevars, rngs);
    }

    int nvars = corevars.getSize();
    cout << "Number of Core Variables: " << nvars << endl;

    cplex.extract(model);
    cout << "Model extracted at " << (cplex.getCplexTime() - startTime) << " sec" << endl;

    // save the MIP model to a file, if desired
    if (!param_savemodel.empty()) {
      cout << endl << "Saving generated MIP model to " << param_savemodel << endl << endl;
      cplex.exportModel(param_savemodel.c_str());
    }

    // find out whether it is a minimization problem or a maximization one
    bool isMinimization = true;
    if (cplex.getObjective().getSense() == IloObjective::Maximize)
      isMinimization = false;

    // ask cplex to use MIPInfoCallback
    cplex.use(MIPInfoCallback(env, isMinimization, cplex, startTime));

    cout << "------- Solving the extracted model -------" << endl;
    //const bool solutionFound = cplex.solve();
    const bool solutionFound = (param_nsolutions > 1 ? cplex.populate() : cplex.solve());
    const int nSolutionsFound = cplex.getSolnPoolNsolns();

    cout << "Stopping IloTimer" << endl;
    timer.stop();
    const IloNum endTime = cplex.getCplexTime();

    cout << "-------------------------------------------" << endl;
    printCommandLine(argc, argv);
    cout << "-------------------------------------------" << endl;
    cout << "Number of cplex nodes        = " << cplex.getNnodes() << endl;
    cout << "Number of cplex iterations   = " << cplex.getNiterations() << endl;
    cout << "Aggregated CPU time          = " << timer.getTime() << " seconds" << endl;
    cout << "Elapsed wall clock time      = " << endTime - startTime << " seconds" << endl;
    cout << "Number of threads used       = " << param_threads << endl;
    cout << "Solution status              = " << cplex.getStatus() << endl;

    if (solutionFound) {
      cout << "Solution value               = " << cplex.getObjValue() << endl;
      cout << "Optimality Gap (in %)        = " << fabs((cplex.getBestObjValue() - cplex.getObjValue()) / (1.0 * cplex.getObjValue())) * 100 << endl;
      //cout << "Maximum bound violation      = " << cplex.getQuality(IloCplex::MaxPrimalInfeas) << endl;
    }
    cout << endl << "parameters: n=" << n << " l=" << l << " k=" << k << " p=" << p << " q=" << q << " m=" << m << endl;
    if (solutionFound) {
      cout << "TOTAL " << nSolutionsFound << " solutions found" << endl;
      int nAllowedSolutionsFound = 0;
      if (param_printexpr || param_printanswer || param_printsoln) {
        IloNumArray objValues(env, nSolutionsFound);
        vector<pair<IloNum,unsigned> > sortedIndex(nSolutionsFound);  // to sort solutions by objective value
        vector<FormattedExpr> expressions(nSolutionsFound);
        // extract all solutions as formatted expressions
        for (int s=0; s<nSolutionsFound; s++) {
          IloNumArray vals(env);
          cplex.getValues(vals, corevars, s);
          // convert solution values to integers; note: simple int cast may lead to errors!
          IloIntArray intvals(env, vals.getSize());
          for (int i=0; i<vals.getSize(); i++)
            intvals[i] = IloRound(vals[i]);  // use IloRound rather than std::round
          if (param_printsoln)
            prettyPrintSoln(intvals);
          objValues[s] = cplex.getObjValue(s);
          expressions[s] = getFormattedExpr(intvals);
          sortedIndex[s] = pair<IloNum,unsigned> (objValues[s],s);
        }
        // sort solutions by increasing objective value
        std::stable_sort(sortedIndex.begin(), sortedIndex.end());
        // identify which expressions are unique (ignoring type differences);
        // prefer to keep those that appear earlier in the above sorted order
        set<int>    uniqueExprIndices;
        set<string> seenExpressions;
        if (!param_allowdupes) {
          for (int s=0; s<nSolutionsFound; s++) {
            const int sId = sortedIndex[s].second;
            const string & exprPf = expressions[sId].postfix;
            if (seenExpressions.find(exprPf) == seenExpressions.end()) {
              uniqueExprIndices.insert(sId);
              seenExpressions.insert(exprPf);
            }
          }
        }
        // evaluate all expressions with a single call to Python's SymPy package
        if (param_printanswer)
          solveExpressionsWithSymPy(expressions);
        // print expressions if desired, in sorted order
        if (param_printexpr) {
          cout << "SOLN: CORRECT | POS/NEG | INT/FRA | OBJ-SCORE | TRUE-ANS | ANS | INFIX | POSTFIX | TYPED-POSTFIX" << endl;
          for (int s=0; s<nSolutionsFound; s++) {
            const int sId = sortedIndex[s].second;
            if (!param_allowdupes && uniqueExprIndices.find(sId) == uniqueExprIndices.end())
              continue;
            const FormattedExpr & expr = expressions[sId];
            const double answerValue = atof(expr.answer.c_str());
            const bool isCorrect = (fabs(answerValue - trueAnswer) < epsilon);
            const bool isAnswerNegative = answerValue < 0;
            const bool isAnswerInteger = isInt(answerValue);
            if (!isAnswerNegative && (!allIntConstants || consWts["IntConstantsImplyIntUnknown"] == 0 || isAnswerInteger)) {
              ++nAllowedSolutionsFound;
              cout << "EXPR: " << isCorrect
                   << " | " << (isAnswerNegative ? "NEG" : "POS")
                   << " | " << (isAnswerInteger ? "INT" : "FRA")
                   << " | " << objValues[sId]
                   << " | " << trueAnswer
                   << " | " << expr.answer
                   << " | " << expr.infix
                   << " | " << expr.postfix
                   << " | " << expr.typedPostfix
                   << endl;
            }
          }
        }
      }
      const string solnProperty = (param_allowdupes ? "" : " unique,")
        + string(" non-negative")
        + (allIntConstants && consWts["IntConstantsImplyIntUnknown"] != 0 ? ", integer-valued " : " ");
      cout << "NET " << nAllowedSolutionsFound << solnProperty << "solutions found out of "
           << nSolutionsFound << " total solutions" << endl;
    }

    cout << "-------------------------------------------" << endl;
    cout << "RESULT:"
         << " NODES " << cplex.getNnodes()
         << " | ITERATIONS " << cplex.getNiterations()
         << " | CPUTIME " << timer.getTime()
         << " | WALLTIME " << endTime - startTime
         << " | THREADS " << param_threads
         << " | STATUS " << cplex.getStatus();
    if (solutionFound)
      cout << " | SOLUTION " << cplex.getObjValue()
           << " | OPTGAP " << fabs((cplex.getBestObjValue() - cplex.getObjValue()) / (1.0 * cplex.getObjValue())) * 100;
    else
      cout << " | SOLUTION - | OPTGAP -";
    cout << endl;

    //try {     // basis may not exist
    //  IloCplex::BasisStatusArray cstat(env);
    //  cplex.getBasisStatuses(cstat, vars);
    //  cout << "Basis statuses               = " << cstat << endl;
    //}
    //catch (...) {
    //}


  }
  catch (IloException& e) {
    cerr << "Concert exception caught: " << e << endl;
  }
  catch (...) {
    cerr << "Unknown exception caught" << endl;
  }

  env.end();
  return 0;
}  // END main
Exemple #3
0
  int
  MilpRounding::solution(double &solutionValue, double *betterSolution)
  {
    if(model_->getCurrentPassNumber() > 1) return 0;
    if (model_->currentDepth() > 2 && (model_->getNodeCount()%howOften_)!=0)
      return 0;
 
    int returnCode = 0; // 0 means it didn't find a feasible solution

    OsiTMINLPInterface * nlp = NULL;
    if(setup_->getAlgorithm() == B_BB)
      nlp = dynamic_cast<OsiTMINLPInterface *>(model_->solver()->clone());
    else
      nlp = dynamic_cast<OsiTMINLPInterface *>(setup_->nonlinearSolver()->clone());

    TMINLP2TNLP* minlp = nlp->problem();
 
    // set tolerances
    double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
    //double primalTolerance = 1.0e-6;

    int n;
    int m;
    int nnz_jac_g;
    int nnz_h_lag;
    Ipopt::TNLP::IndexStyleEnum index_style;
    minlp->get_nlp_info(n, m, nnz_jac_g,
			nnz_h_lag, index_style);

    const Bonmin::TMINLP::VariableType* variableType = minlp->var_types();
    const double* x_sol = minlp->x_sol();
    const double* g_l = minlp->g_l();
    const double* g_u = minlp->g_u();

    const double * colsol = model_->solver()->getColSolution();


    // Get information about the linear and nonlinear part of the instance
    TMINLP* tminlp = nlp->model();
    vector<Ipopt::TNLP::LinearityType> c_lin(m);
    tminlp->get_constraints_linearity(m, c_lin());
    vector<int> c_idx(m);
    int n_lin = 0;
    for (int i=0;i<m;i++) {
      if (c_lin[i]==Ipopt::TNLP::LINEAR)
	c_idx[i] = n_lin++;
      else
	c_idx[i] = -1;
    }


    // Get the structure of the jacobian
    vector<int> indexRow(nnz_jac_g);
    vector<int> indexCol(nnz_jac_g);
    minlp->eval_jac_g(n, x_sol, false,
		      m, nnz_jac_g,
		      indexRow(), indexCol(), 0);

    // get the jacobian values 
    vector<double> jac_g(nnz_jac_g);
    minlp->eval_jac_g(n, x_sol, false,
                      m, nnz_jac_g,
                      NULL, NULL, jac_g());

    // Sort the matrix to column ordered
    vector<int> sortedIndex(nnz_jac_g);
    CoinIotaN(sortedIndex(), nnz_jac_g, 0);
    MatComp c;
    c.iRow = indexRow();
    c.jCol = indexCol();
    std::sort(sortedIndex.begin(), sortedIndex.end(), c);

    vector<int> row (nnz_jac_g);
    vector<double> value (nnz_jac_g);
    vector<int> columnStart(n,0); 
    vector<int> columnLength(n,0);
    int indexCorrection = (index_style == Ipopt::TNLP::C_STYLE) ? 0 : 1;
    int iniCol = -1;
    int nnz = 0;
    for(int i=0; i<nnz_jac_g; i++) {
      int thisIndexCol = indexCol[sortedIndex[i]]-indexCorrection;
      int thisIndexRow = c_idx[indexRow[sortedIndex[i]] - indexCorrection];
      if(thisIndexCol != iniCol) {
	iniCol = thisIndexCol;
	columnStart[thisIndexCol] = nnz;
	columnLength[thisIndexCol] = 0;
      }
      if(thisIndexRow == -1) continue;
      columnLength[thisIndexCol]++;
      row[nnz] = thisIndexRow;
      value[nnz] = jac_g[i];
      nnz++;
    }

    // Build the row lower and upper bounds
    vector<double> newRowLower(n_lin);
    vector<double> newRowUpper(n_lin);
    for(int i = 0 ; i < m ; i++){
      if(c_idx[i] == -1) continue;
      newRowLower[c_idx[i]] = g_l[i];
      newRowUpper[c_idx[i]] = g_u[i];
    }

    // Get solution array for heuristic solution
    vector<double> newSolution(n);
    std::copy(x_sol, x_sol + n, newSolution.begin());

    // Define the constraint matrix for MILP
    CoinPackedMatrix matrix(true,n_lin,n, nnz, value(), row(), columnStart(), columnLength());

      // create objective function and columns lower and upper bounds for MILP
      // and create columns for matrix in MILP
      //double alpha = 0;
      double beta = 1;
      vector<double> objective(n);
      vector<int> idxIntegers;
      idxIntegers.reserve(n);
      for(int i = 0 ; i < n ; i++){
         if(variableType[i] != Bonmin::TMINLP::CONTINUOUS){
            idxIntegers.push_back(i);
            objective[i] = beta*(1 - 2*colsol[i]);
         }
      }

#if 0
      // Get dual multipliers and build gradient of the lagrangean
      const double * duals = nlp->getRowPrice() + 2 *n;
      vector<double> grad(n, 0); 
      vector<int> indices(n, 0);
      tminlp->eval_grad_f(n, x_sol, false, grad());
      for(int i = 0 ; i < m ; i++){
        if(c_lin[i] == Ipopt::TNLP::LINEAR) continue;
        int nnz;
        tminlp->eval_grad_gi(n, x_sol, false, i, nnz, indices(), NULL);  
        tminlp->eval_grad_gi(n, x_sol, false, i, nnz, NULL, grad());
        for(int k = 0 ; k < nnz ; k++){
          objective[indices[k]] += alpha *duals[i] * grad[k];
        } 
      }
      for(int i = 0 ; i < n ; i++){
         if(variableType[i] != Bonmin::TMINLP::CONTINUOUS)
         objective[i] += alpha * grad[i];
         //if(fabs(objective[i]) < 1e-4) objective[i] = 0;
         else objective[i] = 0;
      }
      std::copy(objective.begin(), objective.end(), std::ostream_iterator<double>(std::cout, " "));
      std::cout<<std::endl;
#endif

      // load the problem to OSI
      OsiSolverInterface *si = mip_->solver();
      assert(si != NULL);
      CoinMessageHandler * handler = model_->messageHandler()->clone();
      si->passInMessageHandler(handler);
      si->messageHandler()->setLogLevel(1);

      si->loadProblem(matrix, model_->solver()->getColLower(), model_->solver()->getColUpper(), objective(), 
                      newRowLower(), newRowUpper());
      si->setInteger(idxIntegers(), static_cast<int>(idxIntegers.size()));
      si->applyCuts(noGoods);

      bool hasFractionnal = true;
      while(hasFractionnal){
        mip_->optimize(DBL_MAX, 0, 60);
        hasFractionnal = false;
#if 0
        bool feasible = false;
        if(mip_->getLastSolution()) {
  	const double* solution = mip_->getLastSolution();
          std::copy(solution, solution + n, newSolution.begin());
  	feasible = true;
  
        }

    if(feasible) {
      // fix the integer variables and solve the NLP
      // also add no good cut
      CoinPackedVector v;
      double lb = 1;
      for (int iColumn=0;iColumn<n;iColumn++) {
	if (variableType[iColumn] != Bonmin::TMINLP::CONTINUOUS) {
	  double value=newSolution[iColumn];
	  if (fabs(floor(value+0.5)-value)>integerTolerance) {
#ifdef DEBUG_BON_HEURISTIC_DIVE_MIP
	    cout<<"It should be infeasible because: "<<endl;
	    cout<<"variable "<<iColumn<<" is not integer"<<endl;
#endif
	    feasible = false;
	    break;
	  }
	  else {
	    value=floor(newSolution[iColumn]+0.5);
            if(value > 0.5){
              v.insert(iColumn, -1);
              lb -= value;
            }
	    minlp->SetVariableUpperBound(iColumn, value);
	    minlp->SetVariableLowerBound(iColumn, value);
	  }
	}
      }
      }
#endif
      }
      bool feasible = false;
      if(mip_->getLastSolution()) {
	const double* solution = mip_->getLastSolution();
        std::copy(solution, solution + n, newSolution.begin());
	feasible = true;

        delete handler;
      }
      

    if(feasible) {
      // fix the integer variables and solve the NLP
      // also add no good cut
      CoinPackedVector v;
      double lb = 1;
      for (int iColumn=0;iColumn<n;iColumn++) {
	if (variableType[iColumn] != Bonmin::TMINLP::CONTINUOUS) {
	  double value=newSolution[iColumn];
	  if (fabs(floor(value+0.5)-value)>integerTolerance) {
	    feasible = false;
	    break;
	  }
	  else {
	    value=floor(newSolution[iColumn]+0.5);
            if(value > 0.5){
              v.insert(iColumn, -1);
              lb -= value;
            }
	    minlp->SetVariableUpperBound(iColumn, value);
	    minlp->SetVariableLowerBound(iColumn, value);
	  }
	}
      }
      OsiRowCut c;
      c.setRow(v);
      c.setLb(lb);
      c.setUb(DBL_MAX);
      noGoods.insert(c);
      if(feasible) {
	nlp->initialSolve();
	if(minlp->optimization_status() != Ipopt::SUCCESS) {
	  feasible = false;
	}
	std::copy(x_sol,x_sol+n, newSolution.begin());
      }
    }
    if(feasible) {
      double newSolutionValue;
      minlp->eval_f(n, newSolution(), true, newSolutionValue); 
      if(newSolutionValue < solutionValue) {
        std::copy(newSolution.begin(), newSolution.end(), betterSolution);
	solutionValue = newSolutionValue;
	returnCode = 1;
      }
    }

    delete nlp;

#ifdef DEBUG_BON_HEURISTIC_DIVE_MIP
    std::cout<<"DiveMIP returnCode = "<<returnCode<<std::endl;
#endif

    return returnCode;
  }