void ParQGHandler::linearizeObj_() { ObjectivePtr o = minlp_->getObjective(); FunctionType fType = o->getFunctionType(); if (!o) { assert(!"need objective in QG!"); } else if (fType != Linear && fType != Constant) { oNl_ = true; FunctionPtr f; VariablePtr vPtr; ObjectiveType objType = o->getObjectiveType(); LinearFunctionPtr lf = (LinearFunctionPtr) new LinearFunction(); for (VariableConstIterator viter=rel_->varsBegin(); viter!=rel_->varsEnd(); ++viter) { vPtr = *viter; if (vPtr->getName() == "eta") { assert(o->getObjectiveType()==Minimize); rel_->removeObjective(); lf->addTerm(vPtr, 1.0); f = (FunctionPtr) new Function(lf); rel_->newObjective(f, 0.0, objType); objVar_ = vPtr; break; } } } return; }
VariablePtr Transformer::newVar_(LinearFunctionPtr lf, double d, ProblemPtr newp) { VariablePtr ov; FunctionPtr f; ConstraintPtr cnew; ov = yLfs_->findY(lf, d); if (!ov) { LinearFunctionPtr lf2 = lf->clone(); ov = newp->newVariable(VarTran); yLfs_->insert(ov, lf2, d); lf->addTerm(ov, -1.0); f = (FunctionPtr) new Function(lf); cnew = newp->newConstraint(f, -d, -d); #if SPEW logger_->msgStream(LogDebug) << me_ << "added new constraint " << std::endl; cnew->write(logger_->msgStream(LogDebug)); #endif lHandler_->addConstraint(cnew); } return ov; }
VariablePtr Transformer::newVar_(VariablePtr iv, double d, ProblemPtr newp) { if (fabs(d)<zTol_) { return iv; } else { LinearFunctionPtr lf = (LinearFunctionPtr) new LinearFunction(); VariablePtr ov; FunctionPtr f; ConstraintPtr cnew; ov = yVars_->findY(iv, d); if (!ov) { ov = newp->newVariable(VarTran); yVars_->insert(ov, iv, d); lf->addTerm(iv, 1.0); lf->addTerm(ov, -1.0); f = (FunctionPtr) new Function(lf); cnew = newp->newConstraint(f, -d, -d); #if SPEW logger_->msgStream(LogDebug) << me_ << "added new constraint " << std::endl; cnew->write(logger_->msgStream(LogDebug)); #endif lHandler_->addConstraint(cnew); } return ov; } }
VariablePtr Transformer::newVar_(CGraphPtr cg, ProblemPtr newp) { VariablePtr iv; VariablePtr ov = VariablePtr(); // NULL FunctionPtr f; LinearFunctionPtr lf; ConstraintPtr cnew; assert(cg); if (OpSumList!=cg->getOut()->getOp()) { ov = yUniExprs_->findY(cg); } if (!ov) { ov = newp->newVariable(VarTran); lf = (LinearFunctionPtr) new LinearFunction(); lf->addTerm(ov, -1.0); f = (FunctionPtr) new Function(lf, cg); cnew = newp->newConstraint(f, 0.0, 0.0); #if SPEW logger_->msgStream(LogDebug) << me_ << "added new constraint " << std::endl; cnew->write(logger_->msgStream(LogDebug)); #endif assignHandler_(cg, cnew); yUniExprs_->insert(ov, cg); } return ov; }
// 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 ParQGHandler::addCut_(const double *nlpx, const double *lpx, ConstraintPtr con, CutManager *cutman, SeparationStatus *status) { int error=0; ConstraintPtr newcon; std::stringstream sstm; double c, lpvio, act, cUb; FunctionPtr f = con->getFunction(); LinearFunctionPtr lf = LinearFunctionPtr(); act = con->getActivity(nlpx, &error); if (error == 0) { linearAt_(f, act, nlpx, &c, &lf, &error); if (error==0) { cUb = con->getUb(); lpvio = std::max(lf->eval(lpx)-cUb+c, 0.0); if ((lpvio>solAbsTol_) && ((cUb-c)==0 || (lpvio>fabs(cUb-c)*solRelTol_))) { #if SPEW logger_->msgStream(LogDebug) << me_ << " linearization of constraint " << con->getName() << " violated at LP solution with violation = " << lpvio << ". OA cut added." << std::endl; #endif ++(stats_->cuts); sstm << "_OAcut_"; sstm << stats_->cuts; *status = SepaResolve; f = (FunctionPtr) new Function(lf); newcon = rel_->newConstraint(f, -INFINITY, cUb-c, sstm.str()); CutPtr cut = (CutPtr) new Cut(minlp_->getNumVars(),f, -INFINITY, cUb-c, false,false); cut->setCons(newcon); cutman->addCutToPool(cut); return; } } } else { logger_->msgStream(LogError) << me_ << "Constraint not defined at" << " this point. "<< std::endl; #if SPEW logger_->msgStream(LogDebug) << me_ << "constraint " << con->getName() << " not defined at this point." << std::endl; #endif } return; }
bool SOS1Handler::isGUB(SOS *sos) { VariablePtr var; int nz = sos->getNz(); ConstConstraintPtr c; FunctionPtr f; LinearFunctionPtr lf; bool isgub = false; for (VariableConstIterator viter = sos->varsBegin(); viter!=sos->varsEnd(); ++viter) { var = *viter; if (Binary!=var->getType() || ImplBin!=var->getType()) { return false; } } // If we are here, then it means all variables are binary. Check if their sum // is <= 1. var = *(sos->varsBegin()); for (ConstrSet::iterator it=var->consBegin(); it!=var->consEnd() && false==isgub; ++it) { c = *it; f = c->getFunction(); isgub = true; if (Linear!=f->getType()) { isgub = false; } else if ((UInt) nz==f->getNumVars()) { isgub = false; } else if (fabs(c->getUb()-1.0)>zTol_) { isgub = false; } else { lf = f->getLinearFunction(); for (VariableConstIterator viter = sos->varsBegin(); viter!=sos->varsEnd(); ++viter) { if ((lf->getWeight(*viter)-1.0)>zTol_) { isgub = false; break; } } } } return isgub; }
void Transformer::makeObjLin_() { ObjectivePtr obj; assert(p_); assert(newp_); obj = p_->getObjective(); if (!obj) { return; } if (obj->getFunctionType() != Linear && obj->getFunctionType() != Constant) { VariablePtr eta = newp_->newVariable(VarTran); FunctionPtr etaf; FunctionPtr f = obj->getFunction(); LinearFunctionPtr lz = LinearFunctionPtr(new LinearFunction()); LinearFunctionPtr lz2; ObjectiveType otype = obj->getObjectiveType(); ConstraintPtr objcon; lz->addTerm(eta, -1.0); f->add(lz); if (otype == Minimize) { //XXX Do you want to keep track of the objective constraint? objcon = newp_->newConstraint(f, -INFINITY, 0.0); if (lHandler_) { lHandler_->addConstraint(objcon); } } else { objcon = newp_->newConstraint(f, 0.0, INFINITY); if (lHandler_) { lHandler_->addConstraint(objcon); } } lz2 = (LinearFunctionPtr) new LinearFunction(); lz2->addTerm(eta, 1.0); etaf = (FunctionPtr) new Function(lz2); newp_->newObjective(etaf, obj->getConstant(), otype); } }
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 ParQGHandler::oaCutEngLim_(const double *lpx, CutManager *, SeparationStatus *status) { int error=0; FunctionPtr f; LinearFunctionPtr lf; std::stringstream sstm; ConstraintPtr con, newcon; double c, lpvio, nlpact, cUb; for (CCIter it = nlCons_.begin(); it != nlCons_.end(); ++it) { con = *it; f = con->getFunction(); lf = LinearFunctionPtr(); nlpact = con->getActivity(lpx, &error); if (error == 0) { cUb = con->getUb(); if ((nlpact > cUb + solAbsTol_) && (cUb == 0 || nlpact > cUb+fabs(cUb)*solRelTol_)) { linearAt_(f, nlpact, lpx, &c, &lf, &error); if (error==0) { lpvio = std::max(lf->eval(lpx)-cUb+c, 0.0); if ((lpvio>solAbsTol_) && ((cUb-c)==0 || (lpvio>fabs(cUb-c)*solRelTol_))) { ++(stats_->cuts); sstm << "_OAcut_"; sstm << stats_->cuts; *status = SepaResolve; f = (FunctionPtr) new Function(lf); newcon = rel_->newConstraint(f, -INFINITY, cUb-c, sstm.str()); return; } } } } else { logger_->msgStream(LogError) << me_ << " constraint not defined at" << " this point. "<< std::endl; } } return; }
void Transformer::assignHandler_(CGraphPtr cg, ConstraintPtr c) { switch (cg->getOut()->getOp()) { case OpMult: case OpSqr: qHandler_->addConstraint(c); break; default: { VariablePtr iv; VariablePtr ov = VariablePtr(); LinearFunctionPtr lf = c->getFunction()->getLinearFunction(); if (lf) { assert(lf->getNumTerms()==1); ov = lf->termsBegin()->first; } iv = *(c->getFunction()->getNonlinearFunction()->varsBegin()); uHandler_->addConstraint(c, iv, ov, 'E'); } } }
void PolynomialFunction::removeLinear(LinearFunctionPtr lf) { for (MonomialIter it = terms_.begin(); it!=terms_.end(); ) { if ((*it)->getDegree() == 1) { VarIntMapConstIterator it2 = (*it)->termsBegin(); lf->incTerm(it2->first, (*it)->getCoeff()); it = terms_.erase(it); } else { ++it; } } }
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 MultilinearFormulation::makeTermByTerm() { // First we do some processing of the instance to determine how many // multilinear or quadratic constraints, and we store the indicies // in the instance for later vector<int> lcid; vector<int> mlcid; for(ConstConstraintIterator it = originalInstance_->consBegin(); it != originalInstance_->consEnd(); ++it) { FunctionType ft = (*it)->getFunctionType(); if (ft == Multilinear) { mlcid.push_back((*it)->getId()); } else if (ft == Bilinear) { mlcid.push_back((*it)->getId()); } else if (ft == Linear) { lcid.push_back((*it)->getId()); } } // add x variables vector<double> lb; vector<double> ub; vector<VariablePtr> xvars; int nv = 0; for (ConstVariableIterator it = originalInstance_->varsBegin(); it != originalInstance_->varsEnd(); ++it) { VariablePtr v = *it; VariablePtr vnew = VariablePtr(new Variable(nv, v->getLb(), v->getUb(), v->getType())); lb.push_back(v->getLb()); ub.push_back(v->getUb()); variableMapping_.insert(make_pair(vnew,v)); variables_.push_back(vnew); xvars.push_back(vnew); nv++; } // Add the linear constraints for(int i = 0; i < lcid.size(); i++) { const ConstraintPtr mlc = originalInstance_->getConstraint(lcid[i]); const LinearFunctionPtr olf = mlc->getLinearFunction(); LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); for(ConstVariableGroupIterator it = olf->varsBegin(); it != olf->varsEnd(); ++it) { lf->addTerm(xvars[it->first->getId()], it->second); } FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, mlc->getLb(), mlc->getUb()); constraints_.push_back(c); #if defined(DEBUG_TERM_BY_TERM) c->display(); #endif } // The w variables vector<VariablePtr> wvars; // This holds a map between the 'w' variable added and indices of x vars in multilinear product map <VariablePtr, vector<int> > mlterms; // Go through multilinear rows. Add constraints, and create maps for(int i = 0; i < mlcid.size(); i++) { const ConstraintPtr omlc = originalInstance_->getConstraint(mlcid[i]); const LinearFunctionPtr olf = omlc->getLinearFunction(); const QuadraticFunctionPtr oqf = omlc->getQuadraticFunction(); const NonlinearFunctionPtr onlf = omlc->getNonlinearFunction(); //!!! Don't make this shared by boost, it will get confused in counting MultilinearFunction *omlf = dynamic_cast<MultilinearFunction *>(onlf.get()); LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); // Linear part of constraint remains the same for(ConstVariableGroupIterator it = olf->varsBegin(); it != olf->varsEnd(); ++it) { lf->addTerm(xvars[it->first->getId()], it->second); } // Quadratic part gets a new variable for every term for(ConstVariablePairGroupIterator it = oqf->begin(); it != oqf->end(); ++it) { vector<int> mlix; mlix.push_back(it->first.first->getId()); mlix.push_back(it->first.second->getId()); VariablePtr w = VariablePtr(new Variable(nv, -INFINITY,INFINITY, Continuous)); nv++; variables_.push_back(w); wvars.push_back(w); //XXX Need to store term for evaluation mlterms.insert(make_pair(w,mlix)); lf->addTerm(w,it->second); } // Multilinear part gets a new var for every term for(constMultilinearTermContainerIterator it = omlf->termsBegin(); it != omlf->termsEnd(); ++it) { vector<int> mlix; for(set<ConstVariablePtr>::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { mlix.push_back((*it2)->getId()); } VariablePtr w = VariablePtr(new Variable(nv, -INFINITY, INFINITY, Continuous)); nv++; variables_.push_back(w); wvars.push_back(w); mlterms.insert(make_pair(w,mlix)); lf->addTerm(w,it->first); } FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, omlc->getLb(), omlc->getUb()); constraints_.push_back(c); #if defined(DEBUG_TERM_BY_TERM) c->display(); #endif } // Now add all the constraints for each new bilinear/multilinear term for(map<VariablePtr, vector<int> >::iterator it = mlterms.begin(); it != mlterms.end(); ++it) { ConstVariablePtr w = it->first; vector<int> &mlix = it->second; #if defined(DEBUG_TERM_BY_TERM) cout << "mlix: "; copy(mlix.begin(), mlix.end(), ostream_iterator<int>(cout, " ")); cout << endl; #endif // Enumerate extreme points vector<vector<double> > V; vector<VariablePtr> lambdavars; allExtreme(mlix, lb, ub, V); // Add lambda vars for(UInt j = 0; j < V.size(); j++) { VariablePtr vnew = VariablePtr(new Variable(nv,0.0,1.0,Continuous)); variables_.push_back(vnew); nv++; lambdavars.push_back(vnew); } // Write x as convex combination of lambda (for each component) for(UInt k = 0; k < mlix.size(); k++) { LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); lf->addTerm(xvars[mlix[k]], -1.0); for(UInt j = 0; j < V.size(); j++) { lf->addTerm(lambdavars[j], V[j][k]); } FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, 0.0, 0.0); constraints_.push_back(c); #if defined(DEBUG_TERM_BY_TERM) c->display(); #endif } // Write w (term) as convex combination of function values at extreme points LinearFunctionPtr wlf = LinearFunctionPtr(new LinearFunction()); wlf->addTerm(w, -1.0); for(int j = 0; j < V.size(); j++) { // Evaluation at extreme point is just the product double product = 1.0; for(int k = 0; k < V[j].size(); k++) { product *= V[j][k]; } if (product > 1.0e-9 || product < -1.0e-9) { wlf->addTerm(lambdavars[j], product); } } FunctionPtr wf = (FunctionPtr) new Function(wlf); ConstraintPtr wc = (ConstraintPtr) new Constraint(wf, 0.0, 0.0); constraints_.push_back(wc); #if defined(DEBUG_TERM_BY_TERM) wc->display(); #endif // Also add sum (lambda) = 1 LinearFunctionPtr convex_lf = LinearFunctionPtr(new LinearFunction()); for(int j = 0; j < V.size(); j++) { convex_lf->addTerm(lambdavars[j], 1.0); } FunctionPtr convex_f = (FunctionPtr) new Function(convex_lf); ConstraintPtr convex_c = (ConstraintPtr) new Constraint(convex_f, 1.0, 1.0); constraints_.push_back(convex_c); #if defined(DEBUG_TERM_BY_TERM) convex_c->display(); #endif } LinearFunctionPtr olf = LinearFunctionPtr(new LinearFunction()); const LinearFunctionPtr originalInstance_olf = originalInstance_->getObjective()->getLinearFunction(); for (ConstVariableGroupIterator it = originalInstance_olf->varsBegin(); it != originalInstance_olf->varsEnd(); ++it) { olf->addTerm(xvars[it->first->getId()], it->second); } FunctionPtr of = (FunctionPtr) new Function(olf); objective_ = ObjectivePtr(new Objective(of, 0)); }
void MultilinearFormulation::makeConvexHull() { // First we do some processing of the instance to determine how many // multilinear or quadratic constraints, and we store the indicies // in the instance for later vector<int> lcid; vector<int> mlcid; for(ConstConstraintIterator it = originalInstance_->consBegin(); it != originalInstance_->consEnd(); ++it) { FunctionType ft = (*it)->getFunctionType(); if (ft == Multilinear) { mlcid.push_back((*it)->getId()); } else if (ft == Bilinear) { mlcid.push_back((*it)->getId()); } else if (ft == Linear) { lcid.push_back((*it)->getId()); } } // add x variables vector<double> lb; vector<double> ub; vector<VariablePtr> xvars; int nv = 0; for (ConstVariableIterator it = originalInstance_->varsBegin(); it != originalInstance_->varsEnd(); ++it) { VariablePtr v = *it; VariablePtr vnew = VariablePtr(new Variable(nv, v->getLb(), v->getUb(), v->getType())); lb.push_back(v->getLb()); ub.push_back(v->getUb()); variableMapping_.insert(make_pair(vnew,v)); variables_.push_back(vnew); xvars.push_back(vnew); nv++; } // Add z vars vector<VariablePtr> zvars; for(UInt i = 0; i < mlcid.size(); i++) { const ConstraintPtr mlc = originalInstance_->getConstraint(mlcid[i]); VariablePtr vnew = VariablePtr(new Variable(nv,mlc->getLb(),mlc->getUb(),Continuous)); variables_.push_back(vnew); zvars.push_back(vnew); nv++; } // Enumerate all extreme points int origNumVars = originalInstance_->getNumVars(); vector<int> S(origNumVars); for(int i = 0; i < origNumVars; i++) { S[i] = i; } vector<vector<double> > V; allExtreme(S, lb, ub, V); // Add lambda variables vector<VariablePtr> lambdavars; for(UInt i = 0; i < V.size(); i++) { VariablePtr vnew = VariablePtr(new Variable(nv,0.0,1.0,Continuous)); variables_.push_back(vnew); lambdavars.push_back(vnew); nv++; } // Add the original linear constraints (on x) for(int i = 0; i < lcid.size(); i++) { const ConstraintPtr mlc = originalInstance_->getConstraint(lcid[i]); const LinearFunctionPtr olf = mlc->getLinearFunction(); LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); for(ConstVariableGroupIterator it = olf->varsBegin(); it != olf->varsEnd(); ++it) { lf->addTerm(xvars[it->first->getId()], it->second); } FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, mlc->getLb(), mlc->getUb()); constraints_.push_back(c); #if defined(DEBUG_CONVEX_HULL) c->display(); #endif } // Write x in terms of extreme points for(int i = 0; i < origNumVars; i++) { LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); lf->addTerm(xvars[i], -1.0); for(int j = 0; j < V.size(); j++) { lf->addTerm(lambdavars[j], V[j][i]); } //lf->display(); FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, 0.0, 0.0); constraints_.push_back(c); //XXX Should I set the ID? #if defined(DEBUG_CONVEX_HULL) c->display(); #endif } // Write z in terms of extreme points for(int i = 0; i < mlcid.size(); i++) { LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); lf->addTerm(zvars[i], -1.0); const ConstraintPtr mlc = originalInstance_->getConstraint(mlcid[i]); const FunctionPtr mlf = mlc->getFunction(); for(int j = 0; j < V.size(); j++) { double zval = mlf->eval(V[j]); //cout << "zval = " << zval << endl; lf->addTerm(lambdavars[j], zval); } //lf->display(); cout << endl << endl; FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, 0.0, 0.0); constraints_.push_back(c); #if defined(DEBUG_CONVEX_HULL) c->display(); #endif } // Add convexity constraint LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); for(int j = 0; j < V.size(); j++) { lf->addTerm(lambdavars[j], 1.0); } FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, 1.0, 1.0); constraints_.push_back(c); #if defined(DEBUG_CONVEX_HULL) c->display(); #endif LinearFunctionPtr olf = LinearFunctionPtr(new LinearFunction()); // Add objective (on x vars only) const LinearFunctionPtr originalInstance_olf = originalInstance_->getObjective()->getLinearFunction(); for (ConstVariableGroupIterator it = originalInstance_olf->varsBegin(); it != originalInstance_olf->varsEnd(); ++it) { olf->addTerm(xvars[it->first->getId()], it->second); } FunctionPtr of = (FunctionPtr) new Function(olf); objective_ = ObjectivePtr(new Objective(of, 0)); }
void MultilinearTermsHandler::relaxInitInc(RelaxationPtr relaxation, bool *) { // General notes... // Use Id to order variables // x[v->getIndex()] returns solution. /* 0) Create "terms" map using the relaxation variables, not the original problem variables 1) Create groups based on container of terms 2) Add all lambda variables based on groups. (Be sure to keep a container of which constraints are associated with which groups) */ #if defined(DEBUG_MULTILINEARTERMS_HANDLER) cout << "In MultilinearTermHandler::relaxInitInc()" << endl << " Current Relaxation: " << endl; relaxation->write(cout); cout << "And current terms: " << endl; for(ConstTermIterator it = termsO_.begin(); it != termsO_.end(); ++it) { std::cout << "zvar: "; it->first->write(std::cout); std::cout << "Contains vars: " << std::endl; for(SetOfVars::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { (*it2)->write(cout); } } #endif // Copy the original variable pointers into a data structure consisting of // relaxation variables (It just makes likfe easier to keep things in // terms of relaxation variables). for (ConstTermIterator it = termsO_.begin(); it != termsO_.end(); ++it) { ConstVariablePtr ov = it->first; SetOfVars const &ovset = it->second; ConstVariablePtr rv = relaxation->getRelaxationVar(ov); SetOfVars rvset; for(SetOfVars::const_iterator it2 = ovset.begin(); it2 != ovset.end(); ++it2) { rvset.insert( relaxation->getRelaxationVar(*it2)); } termsR_.insert(make_pair(rv, rvset)); } // First we make the groups. makeGroups_(); #if defined(DEBUG_MULTILINEARTERMS_HANDLER) cout << "After making groups: " << endl; for (ConstGroupIterator it = groups_.begin(); it != groups_.end(); ++it) { cout << "Group of: " << endl; for(set<ConstVariablePtr>::const_iterator it2 = it->begin(); it2 != it->end(); ++it2) { (*it2)->write(cout); } } // Just checking groups now. Stop here. //exit(1); #endif /* This chunk of code creates the (powerset) representation * of the extreme points in the groups, adds the lambda variables, * and adds the convexity constraints */ lambdavars_.resize(groups_.size()); for(UInt gix = 0; gix < groups_.size(); ++gix) { LinearFunctionPtr lf = (LinearFunctionPtr) new LinearFunction(); std::set<SetOfVars> p = powerset_(groups_[gix]); int pix = 0; for (std::set<SetOfVars>::iterator it2 = p.begin(); it2 != p.end(); ++it2) { std::string name; std::stringstream name_stream; name_stream << "lam_" << gix << "_" << pix; name = name_stream.str(); VariablePtr lam; lam = relaxation->newVariable(0.0, 1.0, Continuous, name); lf->addTerm(lam, 1.0); #if defined(DEBUG_MULTILINEARTERMS_HANDLER2) std::cout << "Adding: " << name << std::endl; #endif lambdavars_[gix].push_back(lam); pix++; } points_.push_back(p); FunctionPtr f = (FunctionPtr) new Function(lf); relaxation->newConstraint(f, 1.0, 1.0); } ModVector mods; // Not used in initialization handleXDefConstraints_(relaxation, relaxInit_Call, mods); handleZDefConstraints_(relaxation, relaxInit_Call, mods); #if defined(DEBUG_MULTILINEARTERMS_HANDLER) std::cout << "In MultilinearTermHandler::relaxInitInc()" << std::endl << " Final Relaxation: " << std::endl; relaxation->write(std::cout); #endif }
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(); }
void ParQGHandler::addInitLinearX_(const double *x) { int error=0; FunctionPtr f; double c, act, cUb; std::stringstream sstm; ConstraintPtr con, newcon; LinearFunctionPtr lf = LinearFunctionPtr(); for (CCIter it=nlCons_.begin(); it!=nlCons_.end(); ++it) { con = *it; act = con->getActivity(x, &error); if (error == 0) { f = con->getFunction(); linearAt_(f, act, x, &c, &lf, &error); if (error == 0) { cUb = con->getUb(); #if USE_OPENMP sstm << "Thr_" << omp_get_thread_num(); #endif ++(stats_->cuts); sstm << "_OAcut_"; sstm << stats_->cuts; sstm << "_AtRoot"; f = (FunctionPtr) new Function(lf); newcon = rel_->newConstraint(f, -INFINITY, cUb-c, sstm.str()); sstm.str(""); } } else { logger_->msgStream(LogError) << me_ << "Constraint" << con->getName() << " is not defined at this point." << std::endl; #if SPEW logger_->msgStream(LogDebug) << me_ << "constraint " << con->getName() << " is not defined at this point." << std::endl; #endif } } if (oNl_) { error = 0; ObjectivePtr o = minlp_->getObjective(); act = o->eval(x, &error); if (error==0) { ++(stats_->cuts); sstm << "_OAObjcut_"; sstm << stats_->cuts; sstm << "_AtRoot"; f = o->getFunction(); linearAt_(f, act, x, &c, &lf, &error); if (error == 0) { lf->addTerm(objVar_, -1.0); f = (FunctionPtr) new Function(lf); newcon = rel_->newConstraint(f, -INFINITY, -1.0*c, sstm.str()); } } else { logger_->msgStream(LogError) << me_ << "Objective not defined at this point." << std::endl; #if SPEW logger_->msgStream(LogDebug) << me_ << "Objective not defined at this point." << std::endl; #endif } } return; }
void ParQGHandler::oaCutToObj_(const double *nlpx, const double *lpx, CutManager *, SeparationStatus *status) { if (oNl_) { int error=0; FunctionPtr f; double c, vio, act; ConstraintPtr newcon; std::stringstream sstm; ObjectivePtr o = minlp_->getObjective(); act = o->eval(lpx, &error); if (error == 0) { vio = std::max(act-relobj_, 0.0); if ((vio > solAbsTol_) && (relobj_ == 0 || vio > fabs(relobj_)*solRelTol_)) { #if SPEW logger_->msgStream(LogDebug) << me_ << " objective violated at LP " << " solution with violation = " << vio << std::endl; #endif act = o->eval(nlpx, &error); if (error == 0) { f = o->getFunction(); LinearFunctionPtr lf = LinearFunctionPtr(); linearAt_(f, act, nlpx, &c, &lf, &error); if (error == 0) { vio = std::max(c+lf->eval(lpx)-relobj_, 0.0); if ((vio > solAbsTol_) && ((relobj_-c)==0 || vio > fabs(relobj_-c)*solRelTol_)) { #if SPEW logger_->msgStream(LogDebug) << me_ << "linearization of " "objective violated at LP solution with violation = " << vio << ". OA cut added." << std::endl; #endif ++(stats_->cuts); sstm << "_OAObjcut_"; sstm << stats_->cuts; lf->addTerm(objVar_, -1.0); *status = SepaResolve; f = (FunctionPtr) new Function(lf); newcon = rel_->newConstraint(f, -INFINITY, -1.0*c, sstm.str()); } } } } else { #if SPEW logger_->msgStream(LogDebug) << me_ << " objective feasible at LP " << " solution. No OA cut to be added." << std::endl; #endif } } else { logger_->msgStream(LogError) << me_ << " objective not defined at this solution point." << std::endl; #if SPEW logger_->msgStream(LogDebug) << me_ << " objective not defined at this " << " point." << std::endl; #endif } } return; }
int main(int argc, char** argv) { if (argc < 3) { usage(); return -1; } Minotaur::EnvPtr env1 = (Minotaur::EnvPtr) new Minotaur::Environment(); MINOTAUR_AMPL::AMPLInterfacePtr iface = new MINOTAUR_AMPL::AMPLInterface(env1); ProblemPtr inst, newInst; inst = iface->readInstance(argv[1]); newInst = iface->readInstance(argv[1]); int rltDegree = atoi(argv[2]); std::vector<FunctionPtr> v; std::vector<FunctionPtr> temp_v; std::vector<double> v_up; std::vector<double> v_lo; std::vector<double> temp_v_up; std::vector<double> temp_v_lo; for(ConstraintConstIterator con_it = inst->consBegin(); con_it != inst->consEnd(); ++con_it) { FunctionType con_typ = (*con_it)->getFunctionType(); if(con_typ == Linear || con_typ == Quadratic || con_typ == Bilinear || con_typ == Polynomial) { FunctionPtr cf = (*con_it)->getFunction(); v.push_back(cf); v_up.push_back((*con_it)->getUb()); v_lo.push_back((*con_it)->getLb()); } } int round = 1; while(round < rltDegree) { // we use these two integers to make sure that for the first // round the same constraint doesn't get built twice int con_cntr = -1; int v_cntr = -1; for(ConstraintConstIterator con_it = inst->consBegin(); con_it != inst->consEnd(); ++con_it) { con_cntr++; v_cntr = -1; // if the constraint is =, then just skip multiplying it with another constraint if((*con_it)->getUb() - (*con_it)->getLb() > 1e-6) { for(std::vector<FunctionPtr>::iterator vr_it = v.begin(); vr_it != v.end(); ++vr_it) { v_cntr++; if(v_up[v_cntr] - v_lo[v_cntr] > 1e-6) { // if it is the first round, two constraints should be multiplied against eachother only once if((round == 1 && v_cntr >= con_cntr) || round > 1) { FunctionPtr cf = (*con_it)->getFunction(); FunctionPtr vf = *vr_it; FunctionType cf_typ = cf->getType(); FunctionType vf_typ = vf->getType(); if((cf_typ == Linear || cf_typ == Quadratic || cf_typ == Polynomial) && (vf_typ == Linear || vf_typ == Quadratic || vf_typ == Polynomial)) { // Break down the constraint function LinearFunctionPtr lcf = cf->getLinearFunction(); QuadraticFunctionPtr qcf = cf->getQuadraticFunction(); NonlinearFunctionPtr ncf = cf->getNonlinearFunction(); PolyFunPtr pcf; if(ncf) pcf = boost::dynamic_pointer_cast <PolynomialFunction> (ncf); // Break down the v function LinearFunctionPtr lvf = vf->getLinearFunction(); QuadraticFunctionPtr qvf = vf->getQuadraticFunction(); NonlinearFunctionPtr nvf = vf->getNonlinearFunction(); PolyFunPtr pvf; if(nvf) pvf = boost::dynamic_pointer_cast <PolynomialFunction> (nvf); // Multiply parts of the two functions against eachother QuadraticFunctionPtr q_lcf_lvf; PolyFunPtr p_lcf_qvf; PolyFunPtr p_lcf_pvf; PolyFunPtr p_qcf_lvf; PolyFunPtr p_qcf_qvf; PolyFunPtr p_qcf_pvf; PolyFunPtr p_pcf_lvf; PolyFunPtr p_pcf_qvf; PolyFunPtr p_pcf_pvf; // Multiply the linear part of cf to the linear part of vf if(lcf && lvf) q_lcf_lvf = lcf * lvf; // Multiply the linear part of cf to the quadratic part of vf if(lcf && qvf) p_lcf_qvf = qvf * lcf; // Multiply the linear part of cf to the polynomial part of vf if(lcf && nvf) p_lcf_pvf = pvf * lcf; // Multiply the quadratic part of cf to the linear part of vf if(qcf && lvf) p_qcf_lvf = qcf * lvf; // Multiply the quadratic part of cf to the quadratic part of vf if(qcf && qvf) p_qcf_qvf = qcf * qvf; // Multiply the quadratic part of cf to the polynomial part of vf if(qcf && nvf) p_qcf_pvf = pvf * qcf; // Multiply the polynomial part of cf to the linear part of vf if(ncf && lvf) p_pcf_lvf = pcf * lvf; // Multiply the polynomial part of cf to the quadratic part of vf if(ncf && qvf) p_pcf_qvf = pcf * qvf; // Multiply the polynomial part of cf to the polynomial part of vf if(ncf && nvf) p_pcf_pvf = pcf * pvf; // Now add them up // - Polynomial part PolyFunPtr p_mult = p_lcf_qvf + p_lcf_pvf + p_qcf_lvf + p_qcf_qvf + p_qcf_pvf + p_pcf_lvf + p_pcf_qvf + p_pcf_pvf; NonlinearFunctionPtr n_mult = boost::dynamic_pointer_cast <NonlinearFunction> (p_mult); LinearFunctionPtr dummy; FunctionPtr mult = (FunctionPtr) new Function(dummy, q_lcf_lvf, n_mult); // If both the constraint and v have lower bound if((*con_it)->getLb() > -1e10 && v_lo[v_cntr] > -1e10) { // Find c * cf LinearFunctionPtr lcf_constant = -v_lo[v_cntr] * lcf; QuadraticFunctionPtr qcf_constant = -v_lo[v_cntr] * qcf; PolyFunPtr pcf_constant = -v_lo[v_cntr] * pcf; // Find d * vf LinearFunctionPtr lvf_constant = -(*con_it)->getLb() * lvf; QuadraticFunctionPtr qvf_constant = -(*con_it)->getLb() * qvf; PolyFunPtr pvf_constant = -(*con_it)->getLb() * pvf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; if(p_mult || pcf_constant || pvf_constant) { p_rltf = p_mult + pcf_constant + pvf_constant; q_rltf = q_lcf_lvf + qvf_constant + qcf_constant; l_rltf = lcf_constant + lvf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = q_lcf_lvf + qcf_constant + qvf_constant; l_rltf = lcf_constant + lvf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back(-1 * (*con_it)->getLb() * v_lo[v_cntr]); temp_v_up.push_back(INFINITY); } // If constraint has a lower bound and v has an upper bound if((*con_it)->getLb() > -1e10 && v_up[v_cntr] < 1e10) { // Find c * cf LinearFunctionPtr lcf_constant = v_up[v_cntr] * lcf; QuadraticFunctionPtr qcf_constant = v_up[v_cntr] * qcf; PolyFunPtr pcf_constant = v_up[v_cntr] * pcf; // Find d * vf LinearFunctionPtr lvf_constant = (*con_it)->getLb() * lvf; QuadraticFunctionPtr qvf_constant = (*con_it)->getLb() * qvf; PolyFunPtr pvf_constant = (*con_it)->getLb() * pvf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; QuadraticFunctionPtr neg_q_lcf_lvf = -1 * q_lcf_lvf; if(p_mult || pcf_constant || pvf_constant) { PolyFunPtr neg_p_mult = -1 * p_mult; p_rltf = neg_p_mult + pcf_constant + pvf_constant; q_rltf = neg_q_lcf_lvf + qvf_constant + qcf_constant; l_rltf = lvf_constant + lcf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = neg_q_lcf_lvf + qcf_constant + qvf_constant; l_rltf = lcf_constant + lvf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back((*con_it)->getLb() * v_up[v_cntr]); temp_v_up.push_back(INFINITY); } // If constraint has an upper bound and v has a lower bound if((*con_it)->getUb() < 1e10 && v_lo[v_cntr] > -1e10) { // Find c * cf LinearFunctionPtr lcf_constant = v_lo[v_cntr] * lcf; QuadraticFunctionPtr qcf_constant = v_lo[v_cntr] * qcf; PolyFunPtr pcf_constant = v_lo[v_cntr] * pcf; // Find d * vf LinearFunctionPtr lvf_constant = (*con_it)->getUb() * lvf; QuadraticFunctionPtr qvf_constant = (*con_it)->getUb() * qvf; PolyFunPtr pvf_constant = (*con_it)->getUb() * pvf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; QuadraticFunctionPtr neg_q_lcf_lvf = -1 * q_lcf_lvf; if(p_mult || pcf_constant || pvf_constant) { PolyFunPtr neg_p_mult = -1 * p_mult; p_rltf = neg_p_mult + pcf_constant + pvf_constant; q_rltf = neg_q_lcf_lvf + qvf_constant + qcf_constant; l_rltf = lcf_constant + lvf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = neg_q_lcf_lvf + qcf_constant + qvf_constant; l_rltf = lcf_constant + lvf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back((*con_it)->getUb() * v_lo[v_cntr]); temp_v_up.push_back(INFINITY); } // If constraint has an upper bound and v has an upper bound if((*con_it)->getUb() < 1e10 && v_up[v_cntr] < 1e10) { // Find c * cf LinearFunctionPtr lcf_constant = -v_up[v_cntr] * lcf; QuadraticFunctionPtr qcf_constant = -v_up[v_cntr] * qcf; PolyFunPtr pcf_constant = -v_up[v_cntr] * pcf; // Find d * vf LinearFunctionPtr lvf_constant = -(*con_it)->getUb() * lvf; QuadraticFunctionPtr qvf_constant = -(*con_it)->getUb() * qvf; PolyFunPtr pvf_constant = -(*con_it)->getUb() * pvf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; if(p_mult || pcf_constant || pvf_constant) { p_rltf = p_mult + pcf_constant + pvf_constant; q_rltf = q_lcf_lvf + qvf_constant + qcf_constant; l_rltf = lvf_constant + lcf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = q_lcf_lvf + qcf_constant + qvf_constant; l_rltf = lcf_constant + lvf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back(-1 * (*con_it)->getUb() * v_up[v_cntr]); temp_v_up.push_back(INFINITY); } } } } } } } // multiply variable bound constraints against regular constraints for(VariableConstIterator var_it = inst->varsBegin(); var_it != inst->varsEnd(); ++var_it) { v_cntr = -1; // If the variable has a lower bound if((*var_it)->getLb() > -1e-10) { LinearFunctionPtr lbf = LinearFunctionPtr(new LinearFunction()); lbf->addTerm(*var_it, 1); // Iterate through the functions in v for(std::vector<FunctionPtr>::iterator vr_it = v.begin(); vr_it != v.end(); ++vr_it) { v_cntr++; // If v is = then skip it for now if(v_up[v_cntr] - v_lo[v_cntr] > 1e-6) { FunctionPtr vf = *vr_it; // Break down the v function LinearFunctionPtr lvf = vf->getLinearFunction(); QuadraticFunctionPtr qvf = vf->getQuadraticFunction(); NonlinearFunctionPtr nvf = vf->getNonlinearFunction(); PolyFunPtr pvf; if(nvf) pvf = boost::dynamic_pointer_cast <PolynomialFunction> (nvf); // Multiply parts of the two functions against eachother QuadraticFunctionPtr q_lbf_lvf; PolyFunPtr p_lbf_qvf; PolyFunPtr p_lbf_pvf; // Multiply the linear part of lbf to the linear part of vf if(lbf && lvf) q_lbf_lvf = lbf * lvf; // Multiply the linear part of lbf to the quadratic part of vf if(lbf && qvf) p_lbf_qvf = qvf * lbf; // Multiply the linear part of lbf to the polynomial part of vf if(lbf && pvf) p_lbf_pvf = pvf * lbf; // Now add them up // - Polynomial part PolyFunPtr p_mult = p_lbf_qvf + p_lbf_pvf; // If v has a lower bound if(v_lo[v_cntr] > -1e10) { // Find c * lbf LinearFunctionPtr lbf_constant = -v_lo[v_cntr] * lbf; // Find lb * vf LinearFunctionPtr lvf_constant = -(*var_it)->getLb() * lvf; QuadraticFunctionPtr qvf_constant = -(*var_it)->getLb() * qvf; PolyFunPtr pvf_constant = -(*var_it)->getLb() * pvf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; if(p_mult || pvf_constant) { p_rltf = p_mult + pvf_constant; q_rltf = q_lbf_lvf + qvf_constant; l_rltf = lvf_constant + lbf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = q_lbf_lvf + qvf_constant; l_rltf = lbf_constant + lvf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back(-1 * (*var_it)->getLb() * v_lo[v_cntr]); temp_v_up.push_back(INFINITY); } // If v has a upper bound if(v_up[v_cntr] < 1e10) { // Find c * lbf LinearFunctionPtr lbf_constant = v_up[v_cntr] * lbf; // Find lb * vf LinearFunctionPtr lvf_constant = (*var_it)->getLb() * lvf; QuadraticFunctionPtr qvf_constant = (*var_it)->getLb() * qvf; PolyFunPtr pvf_constant = (*var_it)->getLb() * pvf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; QuadraticFunctionPtr neg_q_lbf_lvf = -1 * q_lbf_lvf; if(p_mult || pvf_constant) { PolyFunPtr neg_p_mult = -1 * p_mult; p_rltf = neg_p_mult + pvf_constant; q_rltf = neg_q_lbf_lvf + qvf_constant; l_rltf = lvf_constant + lbf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = neg_q_lbf_lvf + qvf_constant; l_rltf = lbf_constant + lvf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back((*var_it)->getLb() * v_up[v_cntr]); temp_v_up.push_back(INFINITY); } } // If v is a = constraint just multiply it with the variable else { FunctionPtr vf = *vr_it; // Break down the v function LinearFunctionPtr lvf = vf->getLinearFunction(); QuadraticFunctionPtr qvf = vf->getQuadraticFunction(); NonlinearFunctionPtr nvf = vf->getNonlinearFunction(); PolyFunPtr pvf; if(nvf) pvf = boost::dynamic_pointer_cast <PolynomialFunction> (nvf); // XXX check to see if pvf has a linear and quadratic part // if so remove them // Multiply parts of the two functions against eachother QuadraticFunctionPtr q_lbf_lvf; PolyFunPtr p_lbf_qvf; PolyFunPtr p_lbf_pvf; // Multiply the linear part of lbf to the linear part of vf if(lbf && lvf) q_lbf_lvf = lbf * lvf; // Multiply the linear part of lbf to the quadratic part of vf if(lbf && qvf) p_lbf_qvf = qvf * lbf; // Multiply the linear part of lbf to the polynomial part of vf if(lbf && pvf) p_lbf_pvf = pvf * lbf; // Now add them up // - Polynomial part PolyFunPtr p_mult = p_lbf_qvf + p_lbf_pvf; // Find c * lbf LinearFunctionPtr lbf_constant = -v_lo[v_cntr] * lbf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; if(p_mult) { p_rltf = p_mult; q_rltf = q_lbf_lvf; l_rltf = lbf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = q_lbf_lvf; l_rltf = lbf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back(0); temp_v_up.push_back(0); } } } // if the variable has an upper bound v_cntr = -1; if((*var_it)->getUb() < 1e10) { LinearFunctionPtr ubf = LinearFunctionPtr(new LinearFunction()); ubf->addTerm(*var_it, -1); // Iterate through the functions in v for(std::vector<FunctionPtr>::iterator vr_it = v.begin(); vr_it != v.end(); ++vr_it) { v_cntr++; // If v is = then skip it for now if(v_up[v_cntr] - v_lo[v_cntr] > 1e-6) { FunctionPtr vf = *vr_it; // Break down the v function LinearFunctionPtr lvf = vf->getLinearFunction(); QuadraticFunctionPtr qvf = vf->getQuadraticFunction(); NonlinearFunctionPtr nvf = vf->getNonlinearFunction(); PolyFunPtr pvf; if(nvf) pvf = boost::dynamic_pointer_cast <PolynomialFunction> (nvf); // Multiply parts of the two functions against eachother QuadraticFunctionPtr q_ubf_lvf; PolyFunPtr p_ubf_qvf; PolyFunPtr p_ubf_pvf; // Multiply the linear part of ubf to the linear part of vf if(ubf && lvf) q_ubf_lvf = ubf * lvf; // Multiply the linear part of ubf to the quadratic part of vf if(ubf && qvf) p_ubf_qvf = qvf * ubf; // Multiply the linear part of ubf to the polynomial part of vf if(ubf && pvf) p_ubf_pvf = pvf * ubf; // Now add them up // - Polynomial part PolyFunPtr p_mult = p_ubf_qvf + p_ubf_pvf; // If v has a lower bound if(v_lo[v_cntr] > -1e10) { // Find c * ubf LinearFunctionPtr ubf_constant = -v_lo[v_cntr] * ubf; // Find ub * vf LinearFunctionPtr lvf_constant = (*var_it)->getUb() * lvf; QuadraticFunctionPtr qvf_constant = (*var_it)->getUb() * qvf; PolyFunPtr pvf_constant = (*var_it)->getUb() * pvf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; if(p_mult || pvf_constant) { p_rltf = p_mult + pvf_constant; q_rltf = q_ubf_lvf + qvf_constant; l_rltf = lvf_constant + ubf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = q_ubf_lvf + qvf_constant; l_rltf = ubf_constant + lvf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back((*var_it)->getUb() * v_lo[v_cntr]); temp_v_up.push_back(INFINITY); } // If v has a upper bound if(v_up[v_cntr] < 1e10) { // Find c * ubf LinearFunctionPtr ubf_constant = v_up[v_cntr] * ubf; // Find ub * vf LinearFunctionPtr lvf_constant = -1 * (*var_it)->getUb() * lvf; QuadraticFunctionPtr qvf_constant = -1 * (*var_it)->getUb() * qvf; PolyFunPtr pvf_constant = -1 * (*var_it)->getUb() * pvf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; QuadraticFunctionPtr neg_q_ubf_lvf = -1 * q_ubf_lvf; if(p_mult || pvf_constant) { PolyFunPtr neg_p_mult = -1 * p_mult; p_rltf = neg_p_mult + pvf_constant; q_rltf = neg_q_ubf_lvf + qvf_constant; l_rltf = lvf_constant + ubf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = neg_q_ubf_lvf + qvf_constant; l_rltf = ubf_constant + lvf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back(-1 * (*var_it)->getUb() * v_up[v_cntr]); temp_v_up.push_back(INFINITY); } } /* // If v is a = constraint else { FunctionPtr vf = *vr_it; // Break down the v function LinearFunctionPtr lvf = vf->getLinearFunction(); QuadraticFunctionPtr qvf = vf->getQuadraticFunction(); NonlinearFunctionPtr nvf = vf->getNonlinearFunction(); PolyFunPtr pvf; if(nvf) pvf = boost::dynamic_pointer_cast <PolynomialFunction> (nvf); // Multiply parts of the two functions against eachother QuadraticFunctionPtr q_ubf_lvf; PolyFunPtr p_ubf_qvf; PolyFunPtr p_ubf_pvf; // Multiply the linear part of ubf to the linear part of vf if(ubf && lvf) q_ubf_lvf = ubf * lvf; // Multiply the linear part of ubf to the quadratic part of vf if(ubf && qvf) p_ubf_qvf = qvf * ubf; // Multiply the linear part of ubf to the polynomial part of vf if(ubf && pvf) p_ubf_pvf = pvf * ubf; // Now add them up // - Polynomial part PolyFunPtr p_mult = p_ubf_qvf + p_ubf_pvf; // Find c * ubf LinearFunctionPtr ubf_constant = -v_lo[v_cntr] * ubf; // Sum them up PolyFunPtr p_rltf; QuadraticFunctionPtr q_rltf; LinearFunctionPtr l_rltf; FunctionPtr rltf; if(p_mult) { p_rltf = p_mult; q_rltf = q_ubf_lvf; l_rltf = ubf_constant; NonlinearFunctionPtr n_rltf = boost::dynamic_pointer_cast <NonlinearFunction> (p_rltf); rltf = (FunctionPtr) new Function(l_rltf, q_rltf, n_rltf); } else { q_rltf = q_ubf_lvf; l_rltf = ubf_constant; rltf = (FunctionPtr) new Function(l_rltf, q_rltf); } temp_v.push_back(rltf); temp_v_lo.push_back(0); temp_v_up.push_back(0); } */ } } } v.clear(); v_up.clear(); v_lo.clear(); for(std::vector<FunctionPtr>::iterator temp_v_it = temp_v.begin(); temp_v_it != temp_v.end(); ++temp_v_it) v.push_back(*temp_v_it); for(int i = 0; i < temp_v_up.size(); i++) { v_up.push_back(temp_v_up[i]); v_lo.push_back(temp_v_lo[i]); } // Add the new RLT constraints to the problem for(int i = 0; i < v.size(); i++) { ConstraintPtr rltCon = newInst->newConstraint(v[i], v_lo[i], v_up[i]); } // clear the temp_v vectors temp_v.clear(); temp_v_up.clear(); temp_v_lo.clear(); round++; } //********************************************************* //********************************************************* // Up to this point the problem is RLTized // Next is to build the relaxation for the problem //********************************************************* //********************************************************* newInst->write(std::cout); LPRelaxationPtr lpr = LPRelaxationPtr(new LPRelaxation()); MultilinearHandlerPtr mhandler = MultilinearHandlerPtr(new MultilinearHandler(newInst)); bool isFeasible; int nCons = newInst->getNumCons(); int nVars = newInst->getNumVars(); vector<bool> c_list(nCons); mhandler->relax(lpr, isFeasible, c_list); Minotaur::EnvPtr env = (Minotaur::EnvPtr) new Minotaur::Environment(); OsiLPEnginePtr lpE = OsiLPEnginePtr(new OsiLPEngine(env)); int nv = lpr->getNumVars(); lpE->load(lpr); lpE->solve(); string status = lpE->getStatusString(); // lpE->writeLP("blah"); cout << "After solve : "; cout << lpE->getStatusString(); cout << " , " <<lpE->getStatus(); cout << " , " << lpr->getNumVars(); cout << " , " << lpr->getNumCons(); cout << " , " << lpE->getSolutionValue() << endl; /* Const Double *sol = lpE->getSolution(); /* for(int i=0; i<nv; i++) cout << " , " << sol[i]; // cout <<"var["<<i<<"] = " << sol[i]<<endl; cout << endl; */ }
void MultilinearFormulation::makeRowByRow() { // First we do some processing of the instance to determine how many // multilinear or quadratic constraints, and we store the indicies // for later vector<int> lcid; vector<int> mlcid; for(ConstConstraintIterator it = originalInstance_->consBegin(); it != originalInstance_->consEnd(); ++it) { FunctionType ft = (*it)->getFunctionType(); if (ft == Multilinear) { mlcid.push_back((*it)->getId()); } else if (ft == Bilinear) { mlcid.push_back((*it)->getId()); } else if (ft == Linear) { lcid.push_back((*it)->getId()); } } // add x variables vector<double> lb; vector<double> ub; vector<VariablePtr> xvars; int nv = 0; for (ConstVariableIterator it = originalInstance_->varsBegin(); it != originalInstance_->varsEnd(); ++it) { VariablePtr v = *it; VariablePtr vnew = VariablePtr(new Variable(nv, v->getLb(), v->getUb(), v->getType())); lb.push_back(v->getLb()); ub.push_back(v->getUb()); variableMapping_.insert(make_pair(vnew,v)); variables_.push_back(vnew); xvars.push_back(vnew); nv++; } // Add the linear constraints for(int i = 0; i < lcid.size(); i++) { const ConstraintPtr mlc = originalInstance_->getConstraint(lcid[i]); const LinearFunctionPtr olf = mlc->getLinearFunction(); LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); for(ConstVariableGroupIterator it = olf->varsBegin(); it != olf->varsEnd(); ++it) { lf->addTerm(xvars[it->first->getId()], it->second); } FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, mlc->getLb(), mlc->getUb()); constraints_.push_back(c); } vector<VariablePtr> zvars; vector<vector< VariablePtr> > lambdavars(mlcid.size()); for(UInt i = 0; i < mlcid.size(); i++) { // One 'z' var per row VariablePtr zvar = VariablePtr(new Variable(nv, -INFINITY, INFINITY, Continuous)); variables_.push_back(zvar); zvars.push_back(zvar); nv++; // Determine what variables appear nonlinearly... const ConstraintPtr mlc = originalInstance_->getConstraint(mlcid[i]); vector<int> nlvars = nonlinearVarsInConstraint(mlc); #if defined(DEBUG_ROW_BY_ROW) cout << "Vars in ml constraint " << i << " have ix: "; for(vector<int>::iterator it = nlvars.begin(); it != nlvars.end(); ++it) { cout << (*it) << " "; } cout << endl; #endif // Add lambda vars for this row vector<vector<double> > V; allExtreme(nlvars, lb, ub, V); for(UInt j = 0; j < V.size(); j++) { VariablePtr vnew = VariablePtr(new Variable(nv,0.0,1.0,Continuous)); variables_.push_back(vnew); lambdavars[i].push_back(vnew); nv++; } for(UInt k = 0; k < nlvars.size(); k++) { // Create 'x' portion of this constraint LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); lf->addTerm(xvars[nlvars[k]], -1.0); for(UInt j = 0; j < V.size(); j++) { lf->addTerm(lambdavars[i][j], V[j][k]); } FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, 0.0, 0.0); constraints_.push_back(c); #if defined(DEBUG_ROW_BY_ROW) c->display(); #endif } // Now add the 'z' var definition LinearFunctionPtr tlf = LinearFunctionPtr(new LinearFunction()); tlf->addTerm(zvar, -1.0); const FunctionPtr mlf = mlc->getFunction(); const LinearFunctionPtr mlf_lf = mlf->getLinearFunction(); for(int j = 0; j < V.size(); j++) { //XXX Kludgy, but just create a vector for the (full) point int onv = originalInstance_->getNumVars(); vector<double> xe(onv,0.0); for(UInt k = 0; k < nlvars.size(); k++) { xe[nlvars[k]] = V[j][k]; } double zval = mlf->eval(xe); // Need to subtract off linear part, since yuo keep those variables in zval -= mlf_lf->eval(xe); tlf->addTerm(lambdavars[i][j], zval); } FunctionPtr tf = (FunctionPtr) new Function(tlf); ConstraintPtr tc = (ConstraintPtr) new Constraint(tf, 0.0, 0.0); constraints_.push_back(tc); #if defined(DEBUG_ROW_BY_ROW) tc->display(); #endif // Now add the linear constraint involving linear x and t LinearFunctionPtr xtlf = LinearFunctionPtr(new LinearFunction()); for(ConstVariableGroupIterator it = mlf_lf->varsBegin(); it != mlf_lf->varsEnd(); ++it) { xtlf->addTerm(xvars[it->first->getId()], it->second); } xtlf->addTerm(zvar,1.0); FunctionPtr xtf = (FunctionPtr) new Function(xtlf); ConstraintPtr xtc = (ConstraintPtr) new Constraint(xtf, mlc->getLb(), mlc->getUb()); constraints_.push_back(xtc); #if defined(DEBUG_ROW_BY_ROW) xtc->display(); #endif // Also add sum (lambda) = 1 LinearFunctionPtr convex_lf = LinearFunctionPtr(new LinearFunction()); for(int j = 0; j < V.size(); j++) { convex_lf->addTerm(lambdavars[i][j], 1.0); } FunctionPtr convex_f = (FunctionPtr) new Function(convex_lf); ConstraintPtr convex_c = (ConstraintPtr) new Constraint(convex_f, 1.0, 1.0); constraints_.push_back(convex_c); #if defined(DEBUG_ROW_BY_ROW) convex_c->display(); #endif } LinearFunctionPtr olf = LinearFunctionPtr(new LinearFunction()); const LinearFunctionPtr originalInstance_olf = originalInstance_->getObjective()->getLinearFunction(); for (ConstVariableGroupIterator it = originalInstance_olf->varsBegin(); it != originalInstance_olf->varsEnd(); ++it) { olf->addTerm(xvars[it->first->getId()], it->second); } FunctionPtr of = (FunctionPtr) new Function(olf); objective_ = ObjectivePtr(new Objective(of, 0)); }
Bool logobj(LinearFunctionPtr lf, CGraphPtr nlf) { UInt numvars = lf->getNumTerms(); // VariableSet vars; // lf->getVars(&vars); VariableGroup::const_iterator it; VariableGroup::const_iterator begin = lf->termsBegin(); VariableGroup::const_iterator end = lf->termsEnd(); // Variable nodes. std::map<UInt,CNode*> varnodes; std::map<CNode*, CNode*> lognodes; std::map<UInt, CNode*> logidnodes; std::map<CNode*, CNode*> numnodes; std::map<UInt, CNode*> numidnodes; std::map<CNode*, CNode*> mulnodes; std::map<UInt, CNode*> mulidnodes; std::set<CNode*> multnodes; std::map<UInt, CNode*> multidnodes; CNode** multnodesvec = new CNode*[numvars]; // Iterate through variables. CNode* tempnode; CNode* lognode; CNode* numnode; CNode* mulnode; CNode* onenode; CNode* sumnode; // Create numnode for one. UInt index = 0; for(it=begin; it!=end; ++it) { VariablePtr var = it->first; Double varlb = var->getLb(); if (varlb >= 0) { UInt varid = var->getId(); Double coeff = it->second; // Create variable node and add it to a set. tempnode = nlf->newNode(var); varnodes.insert(std::pair<UInt,CNode*>(varid,tempnode)); onenode = nlf->newNode(1.0); // Create sumnode. sumnode = nlf->newNode(OpPlus, onenode, tempnode); // Create log nodes. lognode = nlf->newNode(OpLog, &sumnode, 1); lognodes.insert(std::pair<CNode* , CNode*>(tempnode, lognode)); logidnodes.insert(std::pair<UInt, CNode*>(varid, lognode)); // Create num nodes. numnode = nlf->newNode(coeff); numnodes.insert(std::pair<CNode*, CNode*>(tempnode, numnode)); numidnodes.insert(std::pair<UInt, CNode*>(varid, numnode)); // Create mul nodes. mulnode = nlf->newNode(OpMult, numnode, lognode); multnodes.insert(mulnode); multidnodes.insert(std::pair<UInt, CNode*>(varid,mulnode)); multnodesvec[index] = mulnode; index++; } } // This is the root node. CNode* sumlistnode = nlf->newNode(OpSumList, multnodesvec, index); nlf->setOut(sumlistnode); nlf->finalize(); return true; }
int main(int argc, char** argv) { if (argc < 2) { usage(); return -1; } // build the name of the output file string fileName = argv[1]; fileName.erase(fileName.size()-1); fileName.erase(fileName.size()-1); fileName.erase(fileName.size()-1); fileName += ".txt"; char *outFileName = (char*)fileName.c_str(); FILE *pFile; FILE *qFile; qFile = fopen("nameList.txt", "a"); fprintf(qFile, "%s\n", outFileName); fclose(qFile); pFile = fopen(outFileName, "w"); Minotaur::EnvPtr env = (Minotaur::EnvPtr) new Minotaur::Environment(); MINOTAUR_AMPL::AMPLInterfacePtr iface = new MINOTAUR_AMPL::AMPLInterface(env); ProblemPtr inst, newInst; inst = iface->readInstance(argv[1]); int numVars = inst->getNumVars(); int numCons = inst->getNumCons(); fprintf(pFile,"%d\n", numVars); // find the number of linear constraints int numLinCons = 0; for(ConstraintConstIterator cIter=inst->consBegin(); cIter!=inst->consEnd(); ++cIter) { FunctionType ct = (*cIter)->getFunctionType(); if(ct == Linear) { numLinCons++; } } // find the number of quadratic constraints int numQuadCons = 0; for(ConstraintConstIterator cIter=inst->consBegin(); cIter!=inst->consEnd(); ++cIter) { FunctionType ct = (*cIter)->getFunctionType(); if(ct == Quadratic) { numQuadCons++; } } fprintf(pFile, "%d\n", numQuadCons); fprintf(pFile, "%d\n", numLinCons); ObjectivePtr obj = inst->getObjective(0); FunctionPtr objF = obj->getFunction(); LinearFunctionPtr objLF = objF->getLinearFunction(); QuadraticFunctionPtr objQF = objF->getQuadraticFunction(); double **objQ = new double* [numVars]; for(int i = 0; i < numVars; i++) objQ[i] = new double[numVars]; for(int i = 0; i < numVars; i++){ for(int j = 0; j < numVars; j++) { objQ[i][j] = 0; } } double *objA = new double [numVars]; for(int i = 0; i < numVars; i++) objA[i] = 0; //find objQ if(objQF) { for(VariableConstIterator varit1 = inst->varsBegin(); varit1 != inst->varsEnd(); ++varit1) { for(VariableConstIterator varit2 = inst->varsBegin(); varit2 != inst->varsEnd(); ++varit2) { for(VariablePairGroupConstIterator it = objQF->begin(); it != objQF->end(); ++it) { if(((it->first).first)->getId() == (*varit1)->getId() && ((it->first).second)->getId() == (*varit2)->getId()){ int var1Id = (*varit1)->getId(); int var2Id = (*varit2)->getId(); objQ[var1Id][var2Id] = it->second; } } } } } double ij; double ji; for(int i = 0; i < numVars; i++) { for(int j = i+1; j < numVars; j++) { ij = objQ[i][j]; ji = objQ[j][i]; objQ[i][j] = (ij+ji)/2; objQ[j][i] = (ij+ji)/2; } } for(int i = 0; i < numVars; i++) { for(int j = 0; j < numVars; j++) { fprintf(pFile, "%f\t", objQ[i][j]); } fprintf(pFile, "\n"); } fprintf(pFile, "\n\n"); //find objA if(objLF) { for(VariableConstIterator varit = inst->varsBegin(); varit != inst->varsEnd(); ++varit) { for(VariableGroupConstIterator it = objLF->termsBegin(); it != objLF->termsEnd(); ++it) { if((*varit)->getId() == (it->first)->getId()) { objA[(*varit)->getId()] = it->second; } } } } for(int i = 0; i < numVars; i++) fprintf(pFile, "%f\t", objA[i]); fprintf(pFile, "\n"); fprintf(pFile, "\n\n"); //take care of the quadratic constraints for(ConstraintConstIterator cIter=inst->consBegin(); cIter!=inst->consEnd(); ++cIter) { FunctionType ct = (*cIter)->getFunctionType(); if(ct == Quadratic) { // if it's an equality constraint if((*cIter)->getUb() - (*cIter)->getLb() >= -1e-6 && (*cIter)->getUb() - (*cIter)->getLb() <= 1e-6) { fprintf(pFile, "%d\n", 1); fprintf(pFile, "%f\n\n", (*cIter)->getUb()); } // if it's a <= constraint else if((*cIter)->getUb() <= 1e6) { fprintf(pFile, "%d\n", 2); fprintf(pFile, "%f\n\n", (*cIter)->getUb()); } else if ((*cIter)->getLb() >= -1e6) { fprintf(pFile, "%d\n", 3); fprintf(pFile, "%f\n\n", (*cIter)->getLb()); } FunctionPtr F = (*cIter)->getFunction(); LinearFunctionPtr LF = F->getLinearFunction(); QuadraticFunctionPtr QF = F->getQuadraticFunction(); double **Q = new double* [numVars]; for(int i = 0; i < numVars; i++) Q[i] = new double[numVars]; for(int i = 0; i < numVars; i++){ for(int j = 0; j < numVars; j++) { Q[i][j] = 0; } } double *A = new double [numVars]; for(int i = 0; i < numVars; i++) A[i] = 0; //find Q if(QF) { for(VariableConstIterator varit1 = inst->varsBegin(); varit1 != inst->varsEnd(); ++varit1) { for(VariableConstIterator varit2 = inst->varsBegin(); varit2 != inst->varsEnd(); ++varit2) { for(VariablePairGroupConstIterator it = QF->begin(); it != QF->end(); ++it) { if(((it->first).first)->getId() == (*varit1)->getId() && ((it->first).second)->getId() == (*varit2)->getId()){ int var1Id = (*varit1)->getId(); int var2Id = (*varit2)->getId(); Q[var1Id][var2Id] = it->second; } } } } } double ij; double ji; for(int i = 0; i < numVars; i++) { for(int j = i+1; j < numVars; j++) { ij = Q[i][j]; ji = Q[j][i]; Q[i][j] = (ij+ji)/2; Q[j][i] = (ij+ji)/2; } } for(int i = 0; i < numVars; i++) { for(int j = 0; j < numVars; j++) { fprintf(pFile, "%f\t", Q[i][j]); } fprintf(pFile, "\n"); } fprintf(pFile, "\n\n"); //find A if(LF) { for(VariableConstIterator varit = inst->varsBegin(); varit != inst->varsEnd(); ++varit) { for(VariableGroupConstIterator it = LF->termsBegin(); it != LF->termsEnd(); ++it) { if((*varit)->getId() == (it->first)->getId()) { A[(*varit)->getId()] = it->second; } } } } for(int i = 0; i < numVars; i++) fprintf(pFile, "%f\t", A[i]); fprintf(pFile, "\n"); fprintf(pFile, "\n\n"); } } //take care of the linear constraints for(ConstraintConstIterator cIter=inst->consBegin(); cIter!=inst->consEnd(); ++cIter) { FunctionType ct = (*cIter)->getFunctionType(); if(ct == Linear) { // if it's an equality constraint if((*cIter)->getUb() - (*cIter)->getLb() >= -1e-6 && (*cIter)->getUb() - (*cIter)->getLb() <= 1e-6) { fprintf(pFile, "%d\n", 1); fprintf(pFile, "%f\n\n", (*cIter)->getUb()); } // if it's a <= constraint else if((*cIter)->getUb() <= 1e6) { fprintf(pFile, "%d\n", 2); fprintf(pFile, "%f\n\n", (*cIter)->getUb()); } else if ((*cIter)->getLb() >= -1e6) { fprintf(pFile, "%d\n", 3); fprintf(pFile, "%f\n\n", (*cIter)->getLb()); } FunctionPtr F = (*cIter)->getFunction(); LinearFunctionPtr LF = F->getLinearFunction(); double *A = new double [numVars]; for(int i = 0; i < numVars; i++) A[i] = 0; if(LF) { for(VariableConstIterator varit = inst->varsBegin(); varit != inst->varsEnd(); ++varit) { for(VariableGroupConstIterator it = LF->termsBegin(); it != LF->termsEnd(); ++it) { if((*varit)->getId() == (it->first)->getId()) { A[(*varit)->getId()] = it->second; } } } } for(int i = 0; i < numVars; i++) fprintf(pFile, "%f\t", A[i]); fprintf(pFile, "\n"); fprintf(pFile, "\n\n"); } } // get the bound matrices double **lb = new double *[numVars+1]; for(int i=0; i<numVars+1; i++) lb[i] = new double [numVars+1]; double **ub = new double *[numVars+1]; for(int i=0; i<numVars+1; i++) ub[i] = new double [numVars+1]; lb[0][0]=1; ub[0][0]=1; for(VariableConstIterator varit1 = inst->varsBegin(); varit1 != inst->varsEnd(); ++varit1) { int var1Id = (*varit1)->getId(); int var1Lb = (*varit1)->getLb(); int var1Ub = (*varit1)->getUb(); lb[0][var1Id+1] = var1Lb; ub[0][var1Id+1] = var1Ub; lb[var1Id+1][0] = var1Lb; ub[var1Id+1][0] = var1Ub; for(VariableConstIterator varit2 = inst->varsBegin(); varit2 != inst->varsEnd(); ++varit2) { int var2Id = (*varit2)->getId(); int var2Lb = (*varit2)->getLb(); int var2Ub = (*varit2)->getUb(); if(var2Id >= var1Id) { double prodLb; double prodUb; BoundsOnProduct(var1Lb, var1Ub, var2Lb, var2Ub, prodLb, prodUb); lb[var1Id+1][var2Id+1] = prodLb; ub[var1Id+1][var2Id+1] = prodUb; lb[var2Id+1][var1Id+1] = prodLb; ub[var2Id+1][var1Id+1] = prodUb; } } } //print lb for(int i = 0; i < numVars+1; i++) { for(int j = 0; j < numVars+1; j++) { fprintf(pFile, "%f\t", lb[i][j]); } fprintf(pFile, "\n"); } fprintf(pFile, "\n\n"); //print ub for(int i = 0; i < numVars+1; i++) { for(int j = 0; j < numVars+1; j++) { fprintf(pFile, "%f\t", ub[i][j]); } fprintf(pFile, "\n"); } fprintf(pFile, "\n\n"); /* /// int newObjVarCnt; if(obj->getFunctionType() == Linear) newObjVarCnt = inst->getNumVars(); else newObjVarCnt = inst->getNumVars() + 1; printf("newObjVarCnt = %d\n", newObjVarCnt); printf("inst num vars = %d\n", inst->getNumVars()); printf("inst num cons = %d\n", inst->getNumCons()); LPRelaxationPtr lpr = LPRelaxationPtr(new LPRelaxation()); MultilinearHandlerPtr mhandler = MultilinearHandlerPtr(new MultilinearHandler(inst)); bool isFeasible; int nCons = inst->getNumCons(); int nVars = inst->getNumVars(); vector<bool> c_list(nCons); */ }
void MultilinearFormulation::makeMcCormick() { // First we do some processing of the instance to determine how many // multilinear or quadratic constraints, and we store the indicies // in the instance for later vector<int> lcid; vector<int> mlcid; for(ConstConstraintIterator it = originalInstance_->consBegin(); it != originalInstance_->consEnd(); ++it) { FunctionType ft = (*it)->getFunctionType(); if (ft == Multilinear) { mlcid.push_back((*it)->getId()); } else if (ft == Bilinear) { mlcid.push_back((*it)->getId()); } else if (ft == Linear) { lcid.push_back((*it)->getId()); } } // add x variables vector<double> lb; vector<double> ub; vector<VariablePtr> xvars; int nv = 0; for (ConstVariableIterator it = originalInstance_->varsBegin(); it != originalInstance_->varsEnd(); ++it) { VariablePtr v = *it; VariablePtr vnew = VariablePtr(new Variable(nv, v->getLb(), v->getUb(), v->getType())); lb.push_back(v->getLb()); ub.push_back(v->getUb()); variableMapping_.insert(make_pair(vnew,v)); variables_.push_back(vnew); xvars.push_back(vnew); nv++; } // Add the linear constraints for(int i = 0; i < lcid.size(); i++) { const ConstraintPtr mlc = originalInstance_->getConstraint(lcid[i]); const LinearFunctionPtr olf = mlc->getLinearFunction(); LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); for(ConstVariableGroupIterator it = olf->varsBegin(); it != olf->varsEnd(); ++it) { lf->addTerm(xvars[it->first->getId()], it->second); } FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, mlc->getLb(), mlc->getUb()); constraints_.push_back(c); } // The w variables vector<VariablePtr> wvars; // The z vars: These are what you put in the objective vector<ConstVariablePtr> zvars; // The bilinear terms map <VariablePtr, ConstVariablePair> blterms; // Go through multilinear rows. Add constraints, and create maps // for mccormick vars for(int i = 0; i < mlcid.size(); i++) { const ConstraintPtr omlc = originalInstance_->getConstraint(mlcid[i]); const LinearFunctionPtr olf = omlc->getLinearFunction(); const QuadraticFunctionPtr oqf = omlc->getQuadraticFunction(); const NonlinearFunctionPtr onlf = omlc->getNonlinearFunction(); //!!! Don't make this shared by boost, it will get confused in counting MultilinearFunction *omlf = dynamic_cast<MultilinearFunction *>(onlf.get()); LinearFunctionPtr lf = LinearFunctionPtr(new LinearFunction()); // Linear part of constraint remains the same for(ConstVariableGroupIterator it = olf->varsBegin(); it != olf->varsEnd(); ++it) { lf->addTerm(xvars[it->first->getId()], it->second); } // Quadratic part gets a new variable for every term for(ConstVariablePairGroupIterator it = oqf->begin(); it != oqf->end(); ++it) { ConstVariablePtr x1 = it->first.first; ConstVariablePtr x2 = it->first.second; //Bounds on product depend on whether variable bounds are < 0, > 0 double lb = 0.0; double ub = 0.0; boundsOnProduct(x1,x2,lb,ub); VariablePtr w = VariablePtr(new Variable(nv, lb, ub, Continuous)); nv++; variables_.push_back(w); wvars.push_back(w); blterms.insert(make_pair(w,ConstVariablePair(x1,x2))); lf->addTerm(w,it->second); } // Multilinear part gets d-1 new vars. // We do mccormick (for now) in the FIFO way for(constMultilinearTermContainerIterator it = omlf->termsBegin(); it != omlf->termsEnd(); ++it) { set<ConstVariablePtr>::const_iterator it2 = it->second.begin(); ConstVariablePtr x1 = *it2; ++it2; for( ; it2 != it->second.end(); ++it2) { ConstVariablePtr x2 = *it2; double lb = 0.0; double ub = 0.0; boundsOnProduct(x1,x2,lb,ub); VariablePtr w = VariablePtr(new Variable(nv, lb, ub, Continuous)); nv++; variables_.push_back(w); wvars.push_back(w); blterms.insert(make_pair(w,ConstVariablePair(x1,x2))); x1 = w; } // Now x1 is the var you should add to the linear constraint lf->addTerm(x1,it->first); zvars.push_back(x1); } FunctionPtr f = (FunctionPtr) new Function(lf); ConstraintPtr c = (ConstraintPtr) new Constraint(f, omlc->getLb(), omlc->getUb()); constraints_.push_back(c); } // Now add all the constraints for each new bilinear term for(map<VariablePtr, ConstVariablePair>::iterator it = blterms.begin(); it != blterms.end(); ++it) { ConstVariablePtr w = it->first; ConstVariablePtr x1 = it->second.first; ConstVariablePtr x2 = it->second.second; LinearFunctionPtr lf1 = LinearFunctionPtr(new LinearFunction()); LinearFunctionPtr lf2 = LinearFunctionPtr(new LinearFunction()); LinearFunctionPtr lfw = LinearFunctionPtr(new LinearFunction()); // Create new lambda variables VariablePtr lamll = VariablePtr(new Variable(nv, 0.0, 1.0, Continuous)); nv++; variables_.push_back(lamll); VariablePtr lamul = VariablePtr(new Variable(nv, 0.0, 1.0, Continuous)); nv++; variables_.push_back(lamul); VariablePtr lamuu = VariablePtr(new Variable(nv, 0.0, 1.0, Continuous)); nv++; variables_.push_back(lamuu); VariablePtr lamlu = VariablePtr(new Variable(nv, 0.0, 1.0, Continuous)); nv++; variables_.push_back(lamlu); // Just enumerate extreme points yourself lf1->addTerm(x1,-1.0); lf1->addTerm(lamll, x1->getLb()); lf1->addTerm(lamul, x1->getUb()); lf1->addTerm(lamuu, x1->getUb()); lf1->addTerm(lamlu, x1->getLb()); // Just enumerate extreme points yourself lf2->addTerm(x2,-1.0); lf2->addTerm(lamll, x2->getLb()); lf2->addTerm(lamul, x2->getLb()); lf2->addTerm(lamuu, x2->getUb()); lf2->addTerm(lamlu, x2->getUb()); lfw->addTerm(w, -1.0); lfw->addTerm(lamll, x1->getLb()*x2->getLb()); lfw->addTerm(lamul, x1->getUb()*x2->getLb()); lfw->addTerm(lamuu, x1->getUb()*x2->getUb()); lfw->addTerm(lamlu, x1->getLb()*x2->getUb()); // Add the x1,x2,and w rows FunctionPtr f1 = (FunctionPtr) new Function(lf1); ConstraintPtr c1 = (ConstraintPtr) new Constraint(f1, 0.0, 0.0); constraints_.push_back(c1); FunctionPtr f2 = (FunctionPtr) new Function(lf2); ConstraintPtr c2 = (ConstraintPtr) new Constraint(f2, 0.0, 0.0); constraints_.push_back(c2); FunctionPtr fw = (FunctionPtr) new Function(lfw); ConstraintPtr cw = (ConstraintPtr) new Constraint(fw, 0.0, 0.0); constraints_.push_back(cw); // Add the convexity constraint LinearFunctionPtr convex_lf = LinearFunctionPtr(new LinearFunction()); convex_lf->addTerm(lamll, 1.0); convex_lf->addTerm(lamul, 1.0); convex_lf->addTerm(lamuu, 1.0); convex_lf->addTerm(lamlu, 1.0); FunctionPtr convex_f = (FunctionPtr) new Function(convex_lf); ConstraintPtr convex_c = (ConstraintPtr) new Constraint(convex_f, 1.0, 1.0); constraints_.push_back(convex_c); } LinearFunctionPtr olf = LinearFunctionPtr(new LinearFunction()); // Add objective (on x vars only) const LinearFunctionPtr originalInstance_olf = originalInstance_->getObjective()->getLinearFunction(); for (ConstVariableGroupIterator it = originalInstance_olf->varsBegin(); it != originalInstance_olf->varsEnd(); ++it) { olf->addTerm(xvars[it->first->getId()], it->second); } FunctionPtr of = (FunctionPtr) new Function(olf); objective_ = ObjectivePtr(new Objective(of, 0)); }