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 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)); }