void PerspCutGenerator::generateCut() { const double * x = s_->getPrimal(); UInt binindex; binindex = bp_->getIndex(); FunctionPtr f = cp_->getFunction(); UInt indexvar = 0; ConstVariablePtr cvp; double sb = x[binindex]; double vsol = 0.0; // Generate solution y=(x/z,1), x are continuous and z is binary variable double * y = new double[rnv_]; std::fill(y, y + rnv_, 0); for (VarSetConstIterator it=f->varsBegin(); it!=f->varsEnd(); ++it) { cvp = *it; indexvar = cvp->getIndex(); //std::cout << cvp->getName() << " " << x[indexvar] << std::endl; if (indexvar != binindex) { vsol = x[indexvar]; y[indexvar] = vsol/sb; //std::cout << "corresponding y " << y[indexvar] << std::endl; } } y[binindex] = 1; gPCut(f,y); delete [] y; return; }
bool MultilinearTermsHandler::isFeasible(ConstSolutionPtr sol, RelaxationPtr , bool &, double &) { const double *x = sol->getPrimal(); bool is_feas = true; #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << "Checking feasibility: " << std::endl; #endif for (ConstTermIterator it = termsR_.begin(); it != termsR_.end(); ++it) { ConstVariablePtr zt = it->first; SetOfVars const &jt = it->second; if (allVarsBinary_(jt)) continue; double zval = x[zt->getIndex()]; double xval = 1.0; for(SetOfVars::const_iterator jt_it = jt.begin(); jt_it != jt.end(); ++jt_it) { xval *= x[(*jt_it)->getIndex()]; } #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << "Term for variable: " << std::endl; zt->write(std::cout); std::cout << " has error: " << fabs(zval - xval) << std::endl; #endif if (fabs(zval - xval) > eTol_) { is_feas = false; break; } } return(is_feas); }
void KnapCovHandler::separate(ConstSolutionPtr sol, NodePtr, RelaxationPtr rel, CutManager * cmanager, SolutionPoolPtr , bool * , SeparationStatus * status) { // Check integer feasibility of sol, must add cuts if it is not integral. numvars_ = minlp_->getNumVars(); VariableType type; const double * x = sol->getPrimal(); // Is the relaxation solution is integer feasible. bool isintfeas = true; // Iterators for variables. VariableConstIterator it; VariableConstIterator begin = rel->varsBegin(); VariableConstIterator end = rel->varsEnd(); // Temporary variable holder. ConstVariablePtr var; // Value of variable. double value; bool separated = false; UInt n_added = 0; // Check if integrality is satisfied for each integer variable. for (it=begin; it!=end; ++it) { var = *it; type = var->getType(); if (type==Binary || type==Integer) { value = x[var->getIndex()]; if (fabs(value - floor(value + 0.5)) > intTol_) { isintfeas = false; break; } } } if (isintfeas == false) { // We do another check in CoverCutGneerator for integrality, may be we // should eliminate it and use the one above. // Generate cover cuts from current relaxation. CoverCutGeneratorPtr cover = (CoverCutGeneratorPtr) new CoverCutGenerator(rel,sol, env_); // Add cuts to the relaxation by using cut manager. CutVector violatedcuts = cover->getViolatedCutList(); CutIterator itc; CutIterator beginc = violatedcuts.begin(); CutIterator endc = violatedcuts.end(); // Serdar I am not sure if we should add the constraints generated by // addCuts to the constraint vector of knapsack cover handler. // Currently CutMan2::addCuts does not add the cuts to the relaxation formulation. cmanager->addCuts(beginc, endc); cmanager->separate(rel, sol, &separated, &n_added); if (n_added>0) { *status = SepaResolve; } // Update statistics by using return from cover cut generator. ConstCovCutGenStatsPtr covstats = cover->getStats(); // Later put the code below to updateStats function. stats_->knaps += covstats->knaps; stats_->cuts += covstats->cuts; stats_->extended += covstats->extended; stats_->simple += covstats->simple; stats_->gns += covstats->gns; stats_->singlectwo += covstats->singlectwo; } }
void PerspCutGenerator::gPCut(FunctionPtr f, double * y) { int error = 0, errorgr = 0; //NonlinearFunctionPtr nlf = cp_->getNonlinearFunction(); LinearFunctionPtr lf = cp_->getLinearFunction(); double conseval = f->eval(y, &error); double * cgrad = new double[rnv_]; std::fill(cgrad, cgrad + rnv_, 0); f->evalGradient(y, cgrad, &errorgr); lf_ = (LinearFunctionPtr) new LinearFunction(); if (errorgr == 0 && error ==0) { double gradu =0.0 ; // Gradient of continuous variables in the constraint. double gradfi = 0.0; // Index of current variable considered. UInt varindex = 0; // Soluion of variable at vector y. double ysolvar = 0.0; ConstVariablePtr var ; ConstraintPtr newc; for (VarSetConstIterator it = f->varsBegin(); it!= f->varsEnd(); ++it) { var = *it; varindex = var->getIndex(); //std::cout << var->getName() << " " << y[varindex] << std::endl; if(varindex!=bp_->getIndex()){ gradfi =cgrad[varindex]; //std::cout << var->getName() << " Gradient: " << gradfi << std::endl; // Add terms for each variable. lf_->addTerm(var, gradfi); // Solution value of variable. ysolvar = y[varindex]; // gradient for variable u is calculated. gradu -= (gradfi * ysolvar); } //else { //gradu +=lf->getWeight(bp_); //} } // In perspective reformulated constraint coefficient of binary variable is // included in conseval // its coefficient in original constraint minus the upper bound of the constraint if(cp_->getUb() != +INFINITY){ gradu-=(cp_->getUb()); } else { gradu+=(cp_->getLb()); } gradu+=conseval; // We can add binary variable to linearization, when we considered all // variables except the binary variable so that the linearization // coefficient of binary variable is calculated. lf_->addTerm(bp_, gradu); return; } else { logger_->msgStream(LogError) << me_ <<" Gradient" << " or nonlinear part of the function is not defined at the current point" <<std::endl; } return; }
BranchPtr CxUnivarHandler::doBranch_(BranchDirection UpOrDown, ConstVariablePtr v, double bvalue) { BranchPtr branch; LinModsPtr linmods; #if defined(DEBUG_CXUNIVARHANDLER) std::cout << "CxUnivarHandler, Branching: " << (UpOrDown == DownBranch ? "Down" : "Up") << " at value: " << bvalue << " on: " << std::endl; v->write(std::cout); #endif // Zero out tmpX and grad each time, or else bad things happen for (UInt j = 0; j < tmpX_.size(); ++j) { tmpX_[j] = 0.0; grad_[j] = 0.0; } branch = (BranchPtr) new Branch(); linmods = (LinModsPtr) new LinMods(); // Change bounds on the x var (called v here) if (UpOrDown == DownBranch) { VarBoundModPtr mod = (VarBoundModPtr) new VarBoundMod(v, Upper, bvalue); linmods->insert(mod); // Find *all* cons_data that has v as an input variable. CxUnivarConstraintIterator dit; for (dit = cons_data_.begin(); dit != cons_data_.end(); ++dit) { if ((*dit)->getRInputVar() == v) { ConstVariablePtr rov = (*dit)->getROutVar(); FunctionPtr fn = (*dit)->getOriginalCon()->getFunction(); int error; // Change the secant constraint ConstraintPtr secCon = (*dit)->getSecantCon(); LinearFunctionPtr lf; FunctionPtr f; double xlb = v->getLb(); double xub = bvalue; // TODO: Check the error value! tmpX_[v->getIndex()] = xlb; double fxlb = fn->eval(tmpX_, &error); tmpX_[v->getIndex()] = xub; double fxub = fn->eval(tmpX_, &error); tmpX_[v->getIndex()] = 0.0; // TODO: check/remedy numerical issues in this division double m = 0.0; if (xub - xlb > 10e-7) { m = (fxub - fxlb)/(xub - xlb); } double intercept = fxlb - m*xlb; lf = (LinearFunctionPtr) new LinearFunction(); lf->addTerm(rov, 1.0); lf->addTerm(v, -m); LinConModPtr lcmod = (LinConModPtr) new LinConMod(secCon, lf, -INFINITY, intercept); linmods->insert(lcmod); // Change all linearization constraints ConstraintVector::iterator lin_it; for(lin_it = (*dit)->linConsBegin(); lin_it != (*dit)->linConsEnd(); ++lin_it) { ConstraintPtr c = *lin_it; } } } } else { VarBoundModPtr mod = (VarBoundModPtr) new VarBoundMod(v, Lower, bvalue); linmods->insert(mod); } assert(!"add Mod correctly here."); branch->addPMod(linmods); return branch; }
void CxUnivarConstraintData::addSecant(RelaxationPtr rel, ConstVariablePtr riv, ConstVariablePtr rov, FunctionPtr fn, DoubleVector& tmpX, bool init, ModVector &mods) { int error; double xlb, xub, fxlb, fxub, m, intercept; LinearFunctionPtr lf; FunctionPtr f; // First add the secant inequalities based on variable bounds xlb = riv->getLb(); xub = riv->getUb(); #if defined(DEBUG_CXUNIVARHANDLER) std::cout << "Adding secant on variable rix index: " << riv->getIndex() << " rov index: " << rov->getIndex() << " xlb: " << xlb << " xub: " << xub << std::endl; #endif // no secant if unbounded either way if (xlb <= -0.9*INFINITY || xub >= 0.9*INFINITY) { std::cout << "Cannot add secant -- bound is infinite" << std::endl; return; } // TODO: Check the error value! tmpX[riv->getIndex()] = xlb; fxlb = fn->eval(tmpX, &error); tmpX[riv->getIndex()] = xub; fxub = fn->eval(tmpX, &error); tmpX[riv->getIndex()] = 0.0; // TODO: check/remedy numerical issues in this division if (xub - xlb > 10e-7) { m = (fxub - fxlb)/(xub - xlb); } else { m = 0.0; } intercept = fxlb - m*xlb; lf = (LinearFunctionPtr) new LinearFunction(); lf->addTerm(rov, 1.0); lf->addTerm(riv, -m); // rovar <= m*rivar + intercept if (init) { f = (FunctionPtr) new Function(lf); secCon_ = rel->newConstraint(f, -INFINITY, intercept); } else { rel->changeConstraint(secCon_, lf, -INFINITY, intercept); LinConModPtr lcmod = (LinConModPtr) new LinConMod(secCon_, lf, -INFINITY, intercept); mods.push_back(lcmod); } }
void CxUnivarConstraintData::addLin(RelaxationPtr rel, ConstVariablePtr riv, ConstVariablePtr rov, FunctionPtr fn, DoubleVector& tmpX, DoubleVector& grad, bool init, ModVector &mods) { int error; ConstraintPtr cons; double xlb = riv->getLb(); double xub = riv->getUb(); double fxlbval=0, fxubval=0, dfxlbval=0, dfxubval=0; double tmpxval, fxval, dfxval; LinearFunctionPtr lf; FunctionPtr f; // More sophisticated strategies hopefully could be obtained by simply // changing this array int npts = 3; double xvals[] = {xlb, xub, (xub-xlb)/2.0}; #if defined(DEBUG_CXUNIVARHANDLER) std::cout << "Adding linearizations. rix id: " << riv->getId() << " rix index: " << riv->getIndex() << " rov id: " << rov->getId() << " rov index: " << rov->getIndex() << " xlb: " << xlb << " xub: " << xub << std::endl; #endif for (int i = 0; i < npts; i++) { // Zero out tmpX and grad each time, or else bad things happen for (UInt j = 0; j < tmpX.size(); ++j) { tmpX[j] = 0.0; grad[j] = 0.0; } if (i == 2) { // Third linearization point taken to be where first two intersect: // x3 = (f'(xub)*xub - f'(xlb)*xlb + f(xlb) - f(xub))/(f'(xub) - f'(xlb)) // Unless this would put it too close to one of the end points if (dfxubval - dfxlbval > 0.0001 || dfxubval - dfxlbval < -0.0001) { tmpxval = (dfxubval*xub - dfxlbval*xlb + fxlbval - fxubval)/ (dfxubval - dfxlbval); if (tmpxval < xlb + (xub-xlb)*0.05) { xvals[2] = xlb + (xub-xlb)*0.05; } else if (tmpxval > xub - (xub-xlb)*0.05) { xvals[2] = xub - (xub-xlb)*0.05; } else { xvals[2] = tmpxval; } } } tmpX[riv->getIndex()] = xvals[i]; error = 0; fxval = fn->eval(tmpX, &error); fn->evalGradient(&tmpX[0], &grad[0], &error); #if defined(DEBUG_CXUNIVARHANDLER2) for (UInt j = 0; j < tmpX.size(); ++j) { std::cout << "x[" << j << "] = " << tmpX[j] << " dfdx[" << j << "] = " << grad[j] << std::endl; } #endif dfxval = grad[riv->getIndex()]; if (i == 0) { fxlbval = fxval; dfxlbval = dfxval; } else if (i == 1) { fxubval = fxval; dfxubval = dfxval; } // linearization: rov >= f(xval) + f'(xval)(riv - xval) // rov - f'(xval)*riv >= f(xval) - f'(xval)*xval lf = (LinearFunctionPtr) new LinearFunction(); lf->addTerm(rov, 1.0); lf->addTerm(riv, -dfxval); if (init) { f = (FunctionPtr) new Function(lf); cons = rel->newConstraint(f, fxval - dfxval*xvals[i], INFINITY); linCons_.push_back(cons); } else { #if defined(DEBUG_CXUNIVARHANDLER) std::cout << "Will change 'linearization ' constraint to have " << "linear function: "; lf->write(std::cout); std::cout << std::endl; #endif rel->changeConstraint(linCons_[i], lf, fxval - dfxval*xvals[i], INFINITY); LinConModPtr lcmod = (LinConModPtr) new LinConMod(linCons_[i], lf, fxval - dfxval*xvals[i], INFINITY); mods.push_back(lcmod); } } tmpX[riv->getIndex()] = 0.0; grad[riv->getIndex()] = 0.0; }
void MultilinearTermsHandler::getBranchingCandidates(RelaxationPtr, const DoubleVector &x, ModVector &, BrVarCandSet &cands, BrCandVector &, bool &is_inf) { // Implementation notes: // (1) You must insert into the set cands // (2) Super naive implmentation: Just pick the variable from infeasible // terms whose total 'bound product' is largest std::set<ConstVariablePtr> candidates; for (ConstTermIterator it = termsR_.begin(); it != termsR_.end(); ++it) { ConstVariablePtr zt = it->first; SetOfVars const &jt = it->second; if (allVarsBinary_(jt)) continue; double zval = x[zt->getIndex()]; #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << "Relaxation term variable: "; zt->write(std::cout); std::cout << " Has LP value: " << zval << std::endl; #endif double termval = 1.0; double largest_score = eTol_; ConstVariablePtr largest_score_var; for(SetOfVars::const_iterator jt_it = jt.begin(); jt_it != jt.end(); ++jt_it) { ConstVariablePtr termvar = *jt_it; termval *= x[termvar->getIndex()]; #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << "Term variable: "; termvar->write(std::cout); std::cout << " has value: " << x[termvar->getIndex()] << std::endl; #endif double score = (termvar->getUb() - x[termvar->getIndex()])* (x[termvar->getIndex()] - termvar->getLb()); if (score > largest_score) { largest_score = score; largest_score_var = termvar; } } if (fabs(zval - termval) > eTol_) { candidates.insert(largest_score_var); #if defined(DEBUG_MULTILINEARTERMS_HANDLER) largest_score_var->write(std::cout); std::cout << " will be a candidate" << std::endl; #endif } } #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << "Branching candidates are: " << std::endl; for(SetOfVars::const_iterator it = candidates.begin(); it != candidates.end(); ++it) { (*it)->write(std::cout); } #endif for(SetOfVars::const_iterator it = candidates.begin(); it != candidates.end(); ++it) { ConstVariablePtr v = *it; BrVarCandPtr br_can = (BrVarCandPtr) new BrVarCand(v, v->getIndex(), 0.5, 0.5); cands.insert(br_can); } is_inf = false; }