void LpSub::addCons(ArrayBuffer<Constraint*> &newCons) { // LpSub::addCons(): local variables ArrayBuffer<Row*> newRows(newCons.size(),false); //!< the new constraints in row format ArrayBuffer<int> delVar(sub_->nVar(),false); //!< buffer of deletable components of row format double rhsDelta; //!< correction of right hand side InfeasCon::INFEAS infeas; //!< infeasibility mode (TooLarge, TooSmall) Row *nr; constraint2row(newCons, newRows); // eliminate variables in added constraints /* Also the elimination of variables in an added constraint might * cause a void left hand side (interpreted as 0) violated the right hand * side of the constraint. These infeasible constraints are recognized, * but the resolution is currently not implemented. */ const int nNewRows = newRows.size(); for (int c = 0; c < nNewRows; c++) { //! eliminate variables in constraint \a c delVar.clear(); rhsDelta = 0.0; nr = newRows[c]; const int nrNnz = nr->nnz(); for(int i = 0; i < nrNnz; i++) if(eliminated(nr->support(i))) { delVar.push(i); rhsDelta += nr->coeff(i)*elimVal(nr->support(i)); } nr->delInd(delVar,rhsDelta); nr->rename(orig2lp_); // check if constraint \a c has become infeasible if(nr->nnz() == 0) { infeas = newCons[c]->voidLhsViolated(nr->rhs()); if (infeas != InfeasCon::Feasible) { infeasCons_.push(new InfeasCon(master_, newCons[c], infeas)); Logger::ifout() << "LpSub::addCons(): infeasible constraint added.\nAll variables with nonzero coefficients are eliminated and constraint is violated.\nSorry, resolution not implemented yet.\n"; OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcLpSub); } } } LP::addRows(newRows); for (int i = 0; i < newRows.size(); i++) delete newRows[i]; }
/*! * \brief Ajoute une littérale atome en tant que variable d'une littérale passée en argument */ void LitteraleAtome::addVar(LitteraleAtome* atome, Litterale* l) { // On vérifie que l'atome en question n'existe pas déjà dans la liste vars. // On vérifie également que le même nom n'existe pas déjà. // Si l'une des deux vérifications précédentes n'est pas vérifiée, alors on écrase (on supprime la variable préexistente et on ajoute la nouvelle). // Parcourt de la liste for(vector<LitteraleAtome*>::iterator it=vars.begin(); it!=vars.end(); ++it) { // Même pointeur atome OU même nom d'atome -> on delete de la liste if(*it==atome || (*it)->getId()==atome->getId()) delVar(*it); } // On ajoute l'atome dans vars en tant que variable pour la littérale vars.push_back(atome); // On lie l'atome à sa littérale atome->valeur=l; }
void LpSub::initialize() { // LpSub::initialize(): local variables Array<double> obj(sub_->nVar()); Array<double> lBound(sub_->nVar()); Array<double> uBound(sub_->nVar()); Array<Row*> rows(sub_->nCon()); Array<LPVARSTAT::STATUS> lpVarStat(sub_->nVar()); Array<SlackStat::STATUS> slackStat(sub_->nCon()); Row row(master_, sub_->nVar()); //!< buffer to store generated row int conNnz; //!< number of nonzeros of constraint \a c int c; //!< loop index // generate the row format of the active constraints /* After the generation of the row format we allocate a row of * the correct length and make a copy in order to safe memory. */ int nRow = 0; const int nCon = sub_->nCon(); for (c = 0; c < nCon; c++) { conNnz = sub_->constraint(c)->genRow(sub_->actVar(), row); rows[nRow] = new Row(master_, conNnz); rows[nRow]->copy(row); slackStat[nRow] = sub_->slackStat(c)->status(); ++nRow; row.clear(); } // eliminate set and fixed variables and initialize the columns Variable *v; //!< pointer to variable of subproblem Array<bool> marked(0,sub_->nVar()-1, false); //!< \a true if variable can be eliminated nOrigVar_ = sub_->nVar(); valueAdd_ = 0.0; // LpSub: mark variables to eliminate, build objective function and bounds /* We mark all variables which can be eliminated, add them to the * ArrayBuffer \a delVar, compute the mappings from the original variable * set to the actual variable set in the \a LP, and vice versa, and * determine the correction term for the LP-value. * If all variables can be eliminated then we do not eliminate the last * variable for simpification. Otherwise it would be necessary to load * an problem with 0 variables to the LP-solver which is, e.g., for * Cplex not possible. Although the emulation of the optimization would * still be simple, but extra work would have to be performed if later * constraints were added. */ const int nVar = sub_->nVar(); int nCol = 0; for (int i = 0; i < nVar; i++) { v = sub_->variable(i); if(sub_->fsVarStat(i)->fixedOrSet()) { if (eliminable(i) && (nCol || (i != sub_->nVar() - 1))) { //! eliminate variable \a i from the LP marked[i] = true; valueAdd_ += v->obj() * elimVal(i); orig2lp_[i] = -1; } else { // fix variable \a i in the LP /* As variable \a i could not be eliminated we set both its upper and lower * bound to the value it is fixed or set to. */ orig2lp_[i] = nCol; lp2orig_[nCol] = i; obj[nCol] = v->obj(); lBound[nCol] = elimVal(i); uBound[nCol] = elimVal(i); lpVarStat[nCol] = sub_->lpVarStat(i)->status(); ++nCol; } } else { // add variable \a i to the LP orig2lp_[i] = nCol; lp2orig_[nCol] = i; obj[nCol] = v->obj(); lBound[nCol] = sub_->lBound(i); uBound[nCol] = sub_->uBound(i); lpVarStat[nCol] = sub_->lpVarStat(i)->status(); ++nCol; } } // LpSub: update the constraints /* If all active variables of a constraint are eliminated then * its left hand side is void (implicitly 0), but its right hand side * can be nonzero. Depending on the sense of the constraint it can be * infeasible. * If the elimination of variables from constraints causes an infeasible * \a LP, the constraint is memorized in \a infeasCons_. */ ArrayBuffer<int> delVar(sub_->nVar(),false); //!< buffer of deletable components of row format double rhsDelta; //!< correction of right hand side due to eliminations InfeasCon::INFEAS infeas; //!< infeasibility mode (TooLarge, TooSmall) for (c = 0; c < nCon; c++) { // eliminate the variables from the constraint delVar.clear(); rhsDelta = 0.0; const int rNnz = rows[c]->nnz(); for(int i = 0; i < rNnz; i++) if(marked[rows[c]->support(i)]) { delVar.push(i); rhsDelta += rows[c]->coeff(i)*elimVal(rows[c]->support(i)); } rows[c]->delInd(delVar, rhsDelta); // check if the constraint is now infeasible if (rows[c]->nnz() == 0) { infeas = sub_->constraint(c)->voidLhsViolated(rows[c]->rhs()); if (infeas != InfeasCon::Feasible) infeasCons_.push(new InfeasCon(master_, sub_->constraint(c), infeas)); } rows[c]->rename(orig2lp_); } // initialize the LP-solver and clean up LP::initialize(*master_->optSense(), nRow, sub_->maxCon(), nCol, sub_->maxVar(), obj, lBound, uBound, rows, lpVarStat, slackStat); for (c = 0; c < nCon; c++) delete rows[c]; }
void LpSub::addVars( ArrayBuffer<Variable*> &vars, ArrayBuffer<FSVarStat*> &fsVarStat, ArrayBuffer<double> &lb, ArrayBuffer<double> &ub) { // LpSub::addVars(): local variables ArrayBuffer<int> delVar(vars.size(),false); //!< the eliminated variables Array<double> rhsDelta(0,sub_->nCon()-1, 0.0); //!< the correction of the rhs double vValue; double coeff; bool modifyRhs = false; //!< if \a true the modification of rhs required int oldNCol = trueNCol(); int n = trueNCol(); Variable *v; // divide the added variables in eliminable and non-eliminable ones int nVariables = vars.size(); for (int i = 0; i < nVariables; i++) { v = vars[i]; if(fsVarStat[i]->fixedOrSet()) { if (eliminable(i)) { //! the new variable is eliminated delVar.push(i); vValue = elimVal(fsVarStat[i], lb[i], ub[i]); valueAdd_ += v->obj() * vValue; orig2lp_[nOrigVar_++] = -1; const int nCon = sub_->nCon(); for (int c = 0; c < nCon; c++) { coeff = sub_->constraint(c)->coeff(v); if (fabs(coeff) > master_->eps()) { rhsDelta[c] += vValue * coeff; modifyRhs = true; } } } else { // the new variable is fixed in the LP orig2lp_[nOrigVar_++] = n; lp2orig_[n] = oldNCol + i; ++n; lb[i] = ub[i] = elimVal(fsVarStat[i], lb[i], ub[i]); } } else { // the new variable will be added to the LP explicitly orig2lp_[nOrigVar_++] = n; lp2orig_[n] = oldNCol + i; ++n; } } // remove the fixed and set added variables if (delVar.size()) { vars.leftShift(delVar); fsVarStat.leftShift(delVar); lb.leftShift(delVar); ub.leftShift(delVar); } // generate the column of the added variable and add them to the LP ArrayBuffer<Column*> newCols(vars.size(),false); //!< new columns added to the constraint matrix Column colBuf(master_, nRow()); //!< buffer for generated columns Column *col; nVariables = vars.size(); for(int i = 0; i < nVariables; i++) { vars[i]->genColumn(sub_->actCon(), colBuf); col = new Column(master_, colBuf.nnz()); col->copy(colBuf); col->obj(colBuf.obj()); col->uBound(colBuf.uBound()); col->lBound(colBuf.lBound()); newCols.push(col); colBuf.clear(); } LP::addCols(newCols); // modify the right hand side if fixed or set variables are added if (modifyRhs) { const int nCon = sub_->nCon(); Array<double> newRhs(nCon); for(int c = 0; c < nCon; c++) newRhs[c] = rhs(c) - rhsDelta[c]; changeRhs(newRhs); } // LpSub::addVars(): clean up for(int i = 0; i < nVariables; i++) delete newCols[i]; }