示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
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;
  }
}
示例#4
0
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);
      }      
    }
  }  
  
}
示例#8
0
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;
}
示例#9
0
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;
}
示例#10
0
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));
  }
  
}
示例#12
0
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;
}
示例#13
0
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();
}
示例#22
0
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;
}
示例#23
0
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;
}
示例#24
0
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));    
  

}
示例#26
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;
}
示例#27
0
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));    
  

}