示例#1
0
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
示例#2
0
/** Solve the <code>problem</code> using a distributed implementation of
 * Benders' decomposition.
 */
bool
BendersOpt::solve (Problem const *problem,
                   int argc, char const *const *argv,
                   std::vector<char const *> const &machines)
{
   IloEnv env = problem->getModel().getEnv();

   std::vector<Block *> blocks;
   Block *master = 0;
   bool result = false;
   try {
      // Extract blocks and master problem.
      std::cout << "Extracting " << problem->getNBlocks() << " blocks."
                << std::endl;
      for (IloInt b = 0; b < problem->getNBlocks(); ++b)
         blocks.push_back(new Block(problem, b, argc, argv, machines));
      master = new Block(problem, blocks);

      // Write out the master and all blocks (for debugging).
      master->cplex.exportModel("master.lp");
      for (BlockVector::size_type b = 0; b < blocks.size(); ++b) {
         std::stringstream s;
         s << "block" << b << ".lp";
         blocks[b]->cplex.exportModel(s.str().c_str());
      }

      // Solve the master.
      // If we find a feasible solution then perform a final solve
      // with the original problem so that we get solution values for
      // all variables in the original problem.
      if ( master->cplex.solve() ) {
         // Perform a last solve to get the solution values.
         IloNumArray vals(env), startVals(env);
         IloNumVarArray startVars(env);
         master->cplex.getValues(vals, master->vars);
         IloCplex cplex(problem->getModel());
         // Fix integral variables to their value in the master solution
         // and add them as MIP start.
         for (IloInt i = 0; i < vals.getSize(); ++i)
            if ( master->vars[i].getType() != IloNumVar::Float ) {
               double const v = IloRound(vals[i]);
               IloNumVar x = master->varMap[master->vars[i]];
               startVals.add(v);
               startVars.add(x);
               // We add lazy constraints so as to make sure that
               // - we don't modify the original model
               // - the problem has only the unique optimal solution
               //   we are interested in
               cplex.addLazyConstraint(x == v);
            }
         cplex.addMIPStart(startVars, startVals);
         cplex.solve();

         // Report the results.
         std::cout << "#### Problem solved (" << cplex.getObjValue() << ", "
                   << cplex.getCplexStatus() << ")." << std::endl;
         IloNumVarArray vars = problem->getVariables();
         for (IloInt i = 0; i < vars.getSize(); ++i)
            std::cout << "#### \tx[" << i << "] = " << cplex.getValue(vars[i])
                      << std::endl;
         cplex.end();
         result = true;
      }
   } catch (...) {
      if ( master )
         delete master;
      while ( blocks.size() > 0 ) {
         delete blocks.back();
         blocks.pop_back();
      }
      throw;
   }

   delete master;
   while ( blocks.size() > 0 ) {
      delete blocks.back();
      blocks.pop_back();
   }

   return result;
}
示例#3
0
ILOBRANCHCALLBACK1(SOSbranch, IloSOS1Array, sos) {
    IloNumArray    x;
    IloNumVarArray var;

    try {
        IloInt i;
        x   = IloNumArray(getEnv());
        var = IloNumVarArray(getEnv());
        IloNum bestx = EPS;
        IloInt besti = -1;
        IloInt bestj = -1;
        IloInt num = sos.getSize();

        for (i = 0; i < num; i++) {
            if ( getFeasibility(sos[i]) == Infeasible ) {
                var.clear();
                sos[i].getVariables(var);
                getValues(x, var);
                IloInt n = var.getSize();
                for (IloInt j = 0; j < n; j++) {
                    IloNum inf = IloAbs(x[j] - IloRound(x[j]));
                    if ( inf > bestx ) {
                        bestx = inf;
                        besti = i;
                        bestj = j;
                    }
                }
            }
        }

        if ( besti >= 0 ) {
            IloCplex::BranchDirectionArray dir;
            IloNumArray                    val;
            try {
                dir = IloCplex::BranchDirectionArray(getEnv());
                val = IloNumArray(getEnv());
                var.clear();
                sos[besti].getVariables(var);
                IloInt n = var.getSize();
                for (IloInt j = 0; j < n; j++) {
                    if ( j != bestj ) {
                        dir.add(IloCplex::BranchDown);
                        val.add(0.0);
                    } else {
                        dir.add(IloCplex::BranchUp);
                        val.add(1.0);
                    }
                }
                makeBranch(var,        val, dir,                  getObjValue());
                makeBranch(var[bestj], 0.0, IloCplex::BranchDown, getObjValue());
            }
            catch (...) {
                dir.end();
                val.end();
                throw;
            }
            dir.end();
            val.end();
        }
    }
    catch (...) {
        var.end();
        x.end();
        throw;
    }

    var.end();
    x.end();
}