void PerspCutGenerator::generateCut()
{
  const double * x = s_->getPrimal();
 
  UInt binindex;
  binindex = bp_->getIndex();
 
 FunctionPtr f = cp_->getFunction();
 UInt indexvar = 0;
 ConstVariablePtr cvp;
 double sb = x[binindex];
 double vsol = 0.0;

 // Generate solution y=(x/z,1), x are continuous and z is binary variable
 double * y = new double[rnv_];
 std::fill(y, y + rnv_, 0);
 for (VarSetConstIterator it=f->varsBegin(); it!=f->varsEnd(); ++it) {
   cvp = *it;
   indexvar = cvp->getIndex();
   //std::cout << cvp->getName() << " " << x[indexvar] << std::endl;
   if (indexvar != binindex) {
     vsol = x[indexvar];
     y[indexvar] = vsol/sb;  
     //std::cout << "corresponding y " << y[indexvar] << std::endl;
   } 
 } 

 y[binindex] = 1;
 gPCut(f,y);
 delete [] y;
 return;
}
bool
MultilinearTermsHandler::isFeasible(ConstSolutionPtr sol, RelaxationPtr ,
                                    bool &, double &)
{
  const double *x = sol->getPrimal();
  bool is_feas = true;

#if defined(DEBUG_MULTILINEARTERMS_HANDLER)
  std::cout << "Checking feasibility: " << std::endl;
#endif

  for (ConstTermIterator it = termsR_.begin(); it != termsR_.end(); ++it) {
    ConstVariablePtr zt = it->first;
    SetOfVars const &jt = it->second;

    if (allVarsBinary_(jt)) continue;

    double zval = x[zt->getIndex()];
    double xval = 1.0;
    for(SetOfVars::const_iterator jt_it = jt.begin(); jt_it != jt.end(); ++jt_it) {
      xval *= x[(*jt_it)->getIndex()];
    }
#if defined(DEBUG_MULTILINEARTERMS_HANDLER)
    std::cout << "Term for variable: " << std::endl;
    zt->write(std::cout);
    std::cout << " has error: " << fabs(zval - xval) << std::endl;
#endif
    if (fabs(zval - xval) > eTol_) {
      is_feas = false;
      break;
    }
  }
  
  return(is_feas);
}
예제 #3
0
void KnapCovHandler::separate(ConstSolutionPtr sol, NodePtr,
                              RelaxationPtr rel, CutManager * cmanager,
                              SolutionPoolPtr , bool * ,
                              SeparationStatus * status)
{
  // Check integer feasibility of sol, must add cuts if it is not integral.
  numvars_ = minlp_->getNumVars();
  VariableType type;
  const double * x = sol->getPrimal();
  // Is the relaxation solution is integer feasible.
  bool isintfeas = true;
  // Iterators for variables.
  VariableConstIterator it;
  VariableConstIterator begin = rel->varsBegin();
  VariableConstIterator end   = rel->varsEnd();
  // Temporary variable holder.
  ConstVariablePtr var; 
  // Value of variable.
  double value;
  bool separated = false;
  UInt n_added = 0;

  // Check if integrality is satisfied for each integer variable. 
  for (it=begin; it!=end; ++it) {
    var = *it;
    type = var->getType();
    if (type==Binary || type==Integer) {
      value = x[var->getIndex()];
      if (fabs(value - floor(value + 0.5)) > intTol_) {
        isintfeas = false;
        break;
      }
    }
  }

  if (isintfeas ==  false) {
    // We do another check in CoverCutGneerator for integrality, may be we
    // should eliminate it and use the one above.
    // Generate cover cuts from current relaxation.
    CoverCutGeneratorPtr cover = (CoverCutGeneratorPtr) new CoverCutGenerator(rel,sol, env_);
    // Add cuts to the relaxation by using cut manager.
    CutVector violatedcuts = cover->getViolatedCutList();
    CutIterator itc;
    CutIterator beginc = violatedcuts.begin();
    CutIterator endc   = violatedcuts.end();
    
    // Serdar I am not sure if we should add the constraints generated by
    // addCuts to the constraint vector of knapsack cover handler.
    // Currently CutMan2::addCuts does not add the cuts to the relaxation formulation.
    cmanager->addCuts(beginc, endc);
    cmanager->separate(rel, sol, &separated, &n_added);
    if (n_added>0) {
      *status = SepaResolve;
    }
    
    // Update statistics by using return from cover cut generator.
    ConstCovCutGenStatsPtr covstats = cover->getStats();
    // Later put the code below to updateStats function.
    stats_->knaps += covstats->knaps;
    stats_->cuts += covstats->cuts;
    stats_->extended += covstats->extended;
    stats_->simple += covstats->simple;
    stats_->gns += covstats->gns;
    stats_->singlectwo += covstats->singlectwo;    
  }

  
}
void PerspCutGenerator::gPCut(FunctionPtr f, double * y)
{
  int  error = 0, errorgr = 0;
  //NonlinearFunctionPtr nlf = cp_->getNonlinearFunction();
  LinearFunctionPtr lf = cp_->getLinearFunction();
  double conseval = f->eval(y, &error);
  double * cgrad = new double[rnv_];
  std::fill(cgrad, cgrad + rnv_, 0);
  f->evalGradient(y, cgrad, &errorgr);
  lf_ = (LinearFunctionPtr) new LinearFunction();

  if (errorgr == 0 && error ==0) {
    double gradu =0.0 ;
    // Gradient of continuous variables in the constraint.
    double gradfi = 0.0;
    // Index of current variable considered.
     UInt varindex = 0;
    // Soluion of variable at vector y.
    double ysolvar = 0.0;
    ConstVariablePtr var ;
    ConstraintPtr newc;
    for (VarSetConstIterator it = f->varsBegin(); it!= f->varsEnd(); ++it) {
      var = *it; 
      varindex = var->getIndex();
      //std::cout << var->getName() << " " << y[varindex] << std::endl;
      if(varindex!=bp_->getIndex()){
        gradfi =cgrad[varindex];
        //std::cout << var->getName() << " Gradient:  " << gradfi << std::endl;

        // Add terms for each variable.
        lf_->addTerm(var, gradfi);
        // Solution value of variable.
        ysolvar = y[varindex];
        // gradient for variable u is calculated.
        gradu -= (gradfi * ysolvar); 
      } 
      //else {
        //gradu +=lf->getWeight(bp_);
      //}
    }
    // In perspective reformulated constraint coefficient of binary variable is
    // included in conseval
    // its coefficient in original constraint minus the upper bound of the constraint
    if(cp_->getUb() != +INFINITY){
      gradu-=(cp_->getUb());
    } else {
      gradu+=(cp_->getLb());
    }
    gradu+=conseval;
    // We can add binary variable to linearization, when we considered all
    // variables except the binary variable so that the linearization
    // coefficient of binary variable is calculated.
    lf_->addTerm(bp_, gradu);
    return;
  } else {
    logger_->msgStream(LogError) << me_ <<" Gradient"
     <<  " or nonlinear part of the function is not defined at the current point" 
     <<std::endl;
  }
  return;
}
예제 #5
0
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;

}
예제 #6
0
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);
  }

  
}
예제 #7
0
void CxUnivarConstraintData::addLin(RelaxationPtr rel, ConstVariablePtr riv,
				    ConstVariablePtr rov, FunctionPtr fn,
                                    DoubleVector& tmpX, DoubleVector& grad,
                                    bool init, ModVector &mods)
{
 
  int error;
  ConstraintPtr cons; 
  double xlb = riv->getLb();
  double xub = riv->getUb();
  double fxlbval=0, fxubval=0, dfxlbval=0, dfxubval=0;
  double tmpxval, fxval, dfxval; 
  LinearFunctionPtr lf; 
  FunctionPtr f;

  // More sophisticated strategies hopefully could be obtained by simply
  // changing this array 
  int npts = 3;
  double xvals[] = {xlb, xub, (xub-xlb)/2.0};

#if defined(DEBUG_CXUNIVARHANDLER)
  std::cout << "Adding linearizations.  rix id: " << riv->getId() 
	    << " rix index: " << riv->getIndex() << " rov id: " << rov->getId() 
	    << " rov index: " << rov->getIndex()
	    << " xlb: " << xlb << " xub: " << xub << std::endl;
#endif
  
  for (int i = 0; i < npts; i++) {

    // Zero out tmpX and grad each time, or else bad things happen
    for (UInt j = 0; j < tmpX.size(); ++j) {
      tmpX[j] = 0.0;
      grad[j] = 0.0;
    }
    
    if (i == 2) {
      // Third linearization point taken to be where first two intersect:
      // x3 = (f'(xub)*xub - f'(xlb)*xlb + f(xlb) - f(xub))/(f'(xub) - f'(xlb))
      // Unless this would put it too close to one of the end points
      if (dfxubval - dfxlbval > 0.0001 || dfxubval - dfxlbval < -0.0001) {
        tmpxval = (dfxubval*xub - dfxlbval*xlb + fxlbval - fxubval)/
                  (dfxubval - dfxlbval);
        if (tmpxval < xlb + (xub-xlb)*0.05) {
          xvals[2] = xlb + (xub-xlb)*0.05;
        }
        else if (tmpxval > xub - (xub-xlb)*0.05) {
          xvals[2] = xub - (xub-xlb)*0.05;
        }
        else {
          xvals[2] = tmpxval;
        }
      }
    }
    tmpX[riv->getIndex()] = xvals[i];
    error = 0;
    fxval =  fn->eval(tmpX, &error);
    fn->evalGradient(&tmpX[0], &grad[0], &error);
#if defined(DEBUG_CXUNIVARHANDLER2)
    for (UInt j = 0; j < tmpX.size(); ++j) {
      std::cout << "x[" << j << "] = " << tmpX[j] << " dfdx[" << j << "] = "
                << grad[j] << std::endl;
    }
#endif
    dfxval = grad[riv->getIndex()];
    if (i == 0) {
       fxlbval = fxval;
       dfxlbval = dfxval; 
    }
    else if (i == 1) {
       fxubval = fxval;
       dfxubval = dfxval; 
    }
    // linearization:  rov >= f(xval) + f'(xval)(riv - xval) 
    //                 rov - f'(xval)*riv >= f(xval) - f'(xval)*xval
    lf = (LinearFunctionPtr) new LinearFunction();
    lf->addTerm(rov, 1.0);
    lf->addTerm(riv, -dfxval);
    if (init) {
        f = (FunctionPtr) new Function(lf);
    	cons = rel->newConstraint(f, fxval - dfxval*xvals[i], INFINITY);
	linCons_.push_back(cons);
    }
    else {
#if defined(DEBUG_CXUNIVARHANDLER)
       std::cout << "Will change 'linearization  ' constraint to have "
                 << "linear function: ";
       lf->write(std::cout);  
       std::cout << std::endl;
#endif

       rel->changeConstraint(linCons_[i], lf, fxval - dfxval*xvals[i], INFINITY); 
       LinConModPtr lcmod = (LinConModPtr) new LinConMod(linCons_[i], lf, 
                                                         fxval -
                                                         dfxval*xvals[i],
                                                         INFINITY); 
       mods.push_back(lcmod);
    }
  }
  tmpX[riv->getIndex()] = 0.0;
  grad[riv->getIndex()] = 0.0;

}
void MultilinearTermsHandler::getBranchingCandidates(RelaxationPtr, 
                                                const DoubleVector &x,
                                                ModVector &,
                                                BrVarCandSet &cands,
                                                BrCandVector &, bool &is_inf)
{
  // Implementation notes:
  //  (1) You must insert into the set cands
  //  (2) Super naive implmentation:  Just pick the variable from infeasible
  //      terms whose total 'bound product' is largest

  std::set<ConstVariablePtr> candidates;

  for (ConstTermIterator it = termsR_.begin(); it != termsR_.end(); ++it) {
    ConstVariablePtr zt = it->first;
    SetOfVars const &jt = it->second;

    if (allVarsBinary_(jt)) continue;

    double zval = x[zt->getIndex()];

#if defined(DEBUG_MULTILINEARTERMS_HANDLER)
      std::cout << "Relaxation term variable: ";
      zt->write(std::cout);
      std::cout << " Has LP value: " << zval << std::endl;
#endif

    double termval = 1.0;
    double largest_score = eTol_;
    ConstVariablePtr largest_score_var;
    for(SetOfVars::const_iterator jt_it = jt.begin(); jt_it != jt.end(); ++jt_it) {
      ConstVariablePtr termvar = *jt_it;
      termval *= x[termvar->getIndex()];
#if defined(DEBUG_MULTILINEARTERMS_HANDLER)
      std::cout << "Term variable: ";
      termvar->write(std::cout);
      std::cout <<  "  has value: " << x[termvar->getIndex()] << std::endl;
#endif

      double score = (termvar->getUb() - x[termvar->getIndex()])*
        (x[termvar->getIndex()] - termvar->getLb());

      if (score > largest_score) {
        largest_score = score;
        largest_score_var = termvar;
      }
    }
    if (fabs(zval - termval) > eTol_) {
      candidates.insert(largest_score_var);
#if defined(DEBUG_MULTILINEARTERMS_HANDLER)
      largest_score_var->write(std::cout);
      std::cout << " will be a candidate" << std::endl;      
#endif
    }
    
  }

#if defined(DEBUG_MULTILINEARTERMS_HANDLER)
  std::cout << "Branching candidates are: " << std::endl;
  for(SetOfVars::const_iterator it = candidates.begin(); it != candidates.end(); ++it) {
    (*it)->write(std::cout);
  }
#endif  

  for(SetOfVars::const_iterator it = candidates.begin(); it != candidates.end(); ++it) {
    ConstVariablePtr v = *it;
    BrVarCandPtr br_can = (BrVarCandPtr) new BrVarCand(v, v->getIndex(), 0.5, 0.5);
    cands.insert(br_can);
  }
  is_inf = false;
}