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); }
// This chunk of code adds // z_t = \sum_{k=1}^{2 |V_g|} \lambda_k^g, \Prod_{j \in J_t} \chi_j^{g,k} // \forall J_t \subseteq V_g void MultilinearTermsHandler::handleZDefConstraints_(RelaxationPtr relaxation, HandleCallingFunction wherefrom, ModVector &mods) { for(ConstTermIterator it = termsR_.begin(); it != termsR_.end(); ++it) { ConstVariablePtr zt = it->first; SetOfVars const &jt = it->second; for (UInt gix = 0; gix < groups_.size(); ++gix) { SetOfVars &vg = groups_[gix]; if (std::includes(vg.begin(), vg.end(), jt.begin(), jt.end())) { // jt is a subset of vg, add constraint LinearFunctionPtr lf = (LinearFunctionPtr) new LinearFunction(); lf->addTerm(zt, -1.0); int pix = 0; for (std::set<SetOfVars>::iterator it2 = points_[gix].begin(); it2 != points_[gix].end(); ++it2) { double prodval = 1.0; VariablePtr lam = lambdavars_[gix][pix]; for(SetOfVars::const_iterator jt_it = jt.begin(); jt_it != jt.end(); ++jt_it) { ConstVariablePtr xvar = *jt_it; double tmp = varIsAtLowerBoundAtPoint_(xvar, *it2) ? xvar->getLb() : xvar->getUb(); prodval *= tmp; } lf->addTerm(lam, prodval); ++pix; } FunctionPtr f = (FunctionPtr) new Function(lf); if (wherefrom == relaxInit_Call) { ConstraintPtr c = relaxation->newConstraint(f, 0.0, 0.0); zConMap_.insert(std::make_pair(IntVarPtrPair(gix, zt), c)); } else { IntVarPtrPairConstraintMap::iterator pos; pos = zConMap_.find(IntVarPtrPair(gix, zt)); if (pos == zConMap_.end()) { assert(0); } ConstraintPtr c = pos->second; //XXX Here you should just check if the constraint really was going to //change and do nothing if it doesn't... (will be faster). if (wherefrom == relaxNodeInc_Call) { relaxation->changeConstraint(c, lf, 0.0, 0.0); } LinConModPtr lcmod = (LinConModPtr) new LinConMod(c, lf, 0.0, 0.0); mods.push_back(lcmod); } } } } }
void Hypergraph::create(std::map<ConstVariablePtr, SetOfVars > const &terms) { // Add the vertices std::map<ConstVariablePtr, SetOfVars >::const_iterator terms_it; for(terms_it = terms.begin(); terms_it != terms.end(); ++terms_it) { SetOfVars const &jt = terms_it->second; for(SetOfVars::iterator it = jt.begin(); it != jt.end(); ++it) { V_.insert(*it); } } // Add empty lists for the hyperedges for(SetOfVars::iterator v_it = V_.begin(); v_it != V_.end(); ++v_it) { std::list<SetOfVars> e_list; adjList_.insert(make_pair(*v_it, e_list)); } // Now add the edges for(terms_it = terms.begin(); terms_it != terms.end(); ++terms_it) { SetOfVars const &jt = terms_it->second; E_.insert(jt); // Put it in the adjacency lists for (SetOfVars::const_iterator it = jt.begin(); it != jt.end(); ++it) { AdjListType::iterator pos = adjList_.find(*it); assert(pos != adjList_.end()); std::list<SetOfVars> &e_list = pos->second; e_list.push_back(jt); } // Determine weight ConstVariablePtr zvar = terms_it->first; double zweight = 0.0; for (ConstrSet::iterator it2 = zvar->consBegin(); it2 != zvar->consEnd(); ++it2) { const LinearFunctionPtr lf = (*it2)->getLinearFunction(); double w = lf->getWeight(zvar); #if defined(DEBUG_MULTILINEARTERMS_HANDLER) zvar->write(std::cout); std::cout << " has weight: " << w << " in constraint: "; (*it2)->write(std::cout); #endif zweight += fabs(w); } // Add objective weight const LinearFunctionPtr obj = problem_->getObjective()->getLinearFunction(); if (obj != 0) { double w = obj->getWeight(zvar); zweight += fabs(w); } weights_.insert(make_pair(jt, zweight)); originalWeights_.insert(make_pair(jt, zweight)); } }
void MultilinearTermsHandler::handleXDefConstraints_(RelaxationPtr relaxation, HandleCallingFunction wherefrom, ModVector &mods) { for (UInt gix = 0; gix < groups_.size(); ++gix) { for(SetOfVars::const_iterator it = groups_[gix].begin(); it != groups_[gix].end(); ++it) { ConstVariablePtr xvar = *it; LinearFunctionPtr lf = (LinearFunctionPtr) new LinearFunction(); lf->addTerm(xvar, -1.0); int pix = 0; for (std::set<SetOfVars>::iterator it2 = points_[gix].begin(); it2 != points_[gix].end(); ++it2) { VariablePtr lam = lambdavars_[gix][pix]; double val = varIsAtLowerBoundAtPoint_(xvar, *it2) ? xvar->getLb() : xvar->getUb(); lf->addTerm(lam, val); #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << xvar->getName() << ", lam: " << gix << "," << pix << " value is: " << val << std::endl; #endif ++pix; } FunctionPtr f = (FunctionPtr) new Function(lf); if (wherefrom == relaxInit_Call) { ConstraintPtr c = relaxation->newConstraint(f, 0.0, 0.0); xConMap_.insert(std::make_pair(IntVarPtrPair(gix, xvar), c)); } else { IntVarPtrPairConstraintMap::iterator pos; pos = xConMap_.find(IntVarPtrPair(gix, xvar)); if (pos == xConMap_.end()) { assert(0); } ConstraintPtr c = pos->second; //XXX Here you should just check if the constraint really was going to //change and do nothing if it doesn't... (will be faster). if (wherefrom == relaxNodeInc_Call) { relaxation->changeConstraint(c, lf, 0.0, 0.0); } else { assert(0); } LinConModPtr lcmod = (LinConModPtr) new LinConMod(c, lf, 0.0, 0.0); mods.push_back(lcmod); } } } }
void Hypergraph::write(std::ostream &out) const { for(AdjListType::const_iterator it = adjList_.begin(); it != adjList_.end(); ++it) { ConstVariablePtr v = it->first; std::cout << "Vertex: "; v->write(out); std::list<SetOfVars> e_list = it->second; for(std::list<SetOfVars>::const_iterator e_it = e_list.begin(); e_it != e_list.end(); ++e_it) { std::cout << " has edge: " << std::endl; for(SetOfVars::const_iterator v_it = e_it->begin(); v_it != e_it->end(); ++v_it) { (*v_it)->write(out); } } } }
void MultilinearTermsHandler::setupWeights_() { for(ConstTermIterator it = termsR_.begin(); it != termsR_.end(); ++it) { ConstVariablePtr zvar = it->first; double zweight = 0.0; for (ConstrSet::iterator it2 = zvar->consBegin(); it2 != zvar->consEnd(); ++it2) { const LinearFunctionPtr lf = (*it2)->getLinearFunction(); double w = lf->getWeight(zvar); #if defined(DEBUG_MULTILINEARTERMS_HANDLER) zvar->write(std::cout); std::cout << " has weight: " << w << " in constraint: "; (*it2)->write(std::cout); #endif zweight += fabs(w); } weights_.insert(std::make_pair(zvar, zweight)); } }
void MultilinearFormulation::boundsOnProduct(ConstVariablePtr x1, ConstVariablePtr x2, double &lb, double &ub) { double l1 = x1->getLb(); double u1 = x1->getUb(); double l2 = x2->getLb(); double u2 = x2->getUb(); lb = l1 * l2; ub = l1 * l2; lb = std::min(lb, u1*l2); ub = std::max(ub, u1*l2); lb = std::min(lb, u1*u2); ub = std::max(ub, u1*u2); lb = std::min(lb, l1*u2); ub = std::max(ub, l1*u2); }
BranchPtr MultilinearTermsHandler::doBranch_(BranchDirection UpOrDown, ConstVariablePtr v, double bvalue) { BranchPtr branch; BoundType lu; VariableType vtype = v->getType(); #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << "Branching: " << (UpOrDown == DownBranch ? "Down" : "Up") << " at value: " << bvalue << " on: " << std::endl; v->write(std::cout); #endif branch = (BranchPtr) new Branch(); double branching_value = bvalue; // Change bounds on the x var (called v here) if (UpOrDown == DownBranch) { lu = Upper; if (vtype != Continuous) branching_value = floor(bvalue); } else { lu = Lower; if (vtype != Continuous) branching_value = ceil(bvalue); } VarBoundModPtr vmod = (VarBoundModPtr) new VarBoundMod(v, lu, branching_value); assert(!"check whether this needs to be addRMod instead"); branch->addPMod(vmod); branch->setActivity(0.5);// TODO: set this correctly return branch; }
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; }
ModificationPtr MultilinearTermsHandler::getBrMod(BrCandPtr cand, DoubleVector &xval, RelaxationPtr , BranchDirection dir) { LinModsPtr linmods; //XXX Put (bool init) back in handle{x,z}def... BrVarCandPtr vcand = boost::dynamic_pointer_cast <BrVarCand> (cand); VariablePtr v = vcand->getVar(); double branching_value = xval[v->getIndex()]; BoundType lu; VariableType vtype = v->getType(); // Change bounds on the x var (called v here) if (dir == DownBranch) { lu = Upper; if (vtype != Continuous) branching_value = floor(branching_value); } else { lu = Lower; if (vtype != Continuous) branching_value = ceil(branching_value); } linmods = (LinModsPtr) new LinMods(); VarBoundModPtr vmod = (VarBoundModPtr) new VarBoundMod(v, lu, branching_value); linmods->insert(vmod); // This chunk of code changes the // x_{V_g} = \sum_{k=1}^{2 |V_g|} \lambda_k^g \chi^{k,g} \forall g \in G for (UInt gix = 0; gix < groups_.size(); ++gix) { for(SetOfVars::const_iterator it = groups_[gix].begin(); it != groups_[gix].end(); ++it) { ConstVariablePtr xvar = *it; if (v != xvar) continue; LinearFunctionPtr lf = (LinearFunctionPtr) new LinearFunction(); lf->addTerm(xvar, -1.0); UInt pix = 0; for (std::set<SetOfVars>::iterator it2 = points_[gix].begin(); it2 != points_[gix].end(); ++it2) { VariablePtr lam = lambdavars_[gix][pix]; double val = -INFINITY; bool atLower = varIsAtLowerBoundAtPoint_(v, *it2); bool atUpper = !atLower; if (lu == Upper && atUpper) val = branching_value; else if (lu == Lower && atLower) val = branching_value; else val = (atLower ? v->getLb() : v->getUb()); lf->addTerm(lam, val); ++pix; } FunctionPtr f = (FunctionPtr) new Function(lf); IntVarPtrPairConstraintMap::iterator pos; pos = xConMap_.find(IntVarPtrPair(gix, xvar)); if (pos == xConMap_.end()) { assert(0); } ConstraintPtr c = pos->second; LinConModPtr lcmod = (LinConModPtr) new LinConMod(c, lf, 0.0, 0.0); #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << "getBrMod(). Will change 'x =' constraint to have linear function "; lf->write(std::cout); std::cout << std::endl; #endif linmods->insert(lcmod); } } // This will change the z_t = sum \sum_{k=1}^{2|V_g} \lambda_k^g \chi^{k,g}. // Probably not very efficient way to do this... for(ConstTermIterator it = termsR_.begin(); it != termsR_.end(); ++it) { SetOfVars const &jt = it->second; for (UInt gix = 0; gix < groups_.size(); ++gix) { SetOfVars &vg = groups_[gix]; std::set<ConstVariablePtr>::iterator pos1; pos1 = jt.find(v); if (pos1 == jt.end()) continue; // J_t does not contain v, go to next group // J_t is not in V_g, go to next group if (! std::includes(vg.begin(), vg.end(), jt.begin(), jt.end())) continue; ConstVariablePtr zvar = it->first; LinearFunctionPtr lf = (LinearFunctionPtr) new LinearFunction(); lf->addTerm(zvar, -1.0); // Get ConstraintToChange IntVarPtrPairConstraintMap::iterator pos2; pos2 = zConMap_.find(IntVarPtrPair(gix, zvar)); if (pos2 == zConMap_.end()) { assert(0); } ConstraintPtr c = pos2->second; UInt pix = 0; for (std::set<SetOfVars>::iterator it2 = points_[gix].begin(); it2 != points_[gix].end(); ++it2) { double prodval = 1.0; VariablePtr lam = lambdavars_[gix][pix]; // Compute new extreme point value for this lambda for(SetOfVars::const_iterator jt_it = jt.begin(); jt_it != jt.end(); ++jt_it) { ConstVariablePtr xvar = *jt_it; double val = 0.0; bool atLower = varIsAtLowerBoundAtPoint_(xvar, *it2); bool atUpper = !atLower; if (xvar == v) { if (lu == Upper && atUpper) val = branching_value; else if (lu == Lower && atLower) val = branching_value; else val = (atLower ? xvar->getLb() : xvar->getUb()); } else { val = atLower ? xvar->getLb() : xvar->getUb(); } prodval *= val; } lf->addTerm(lam, prodval); ++pix; } // Add new mod LinConModPtr lcmod = (LinConModPtr) new LinConMod(c, lf, 0.0, 0.0); #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << "getBrMod(): Will change 'zt = ' constraint to have linear function: "; lf->write(std::cout); std::cout << std::endl; #endif linmods->insert(lcmod); } } return linmods; return ModificationPtr(); }