void OsiIF::_addCols(ArrayBuffer<Column*> &newCols) { CoinPackedVector *newcol = new CoinPackedVector; for (int i = 0; i < newCols.size(); i++) { int num = newCols[i]->nnz(); double ub = newCols[i]->uBound(); double lb = newCols[i]->lBound(); double obj = newCols[i]->obj(); int *supports = new int[num]; //!< supports of added rows double *coeffs = new double[num]; //!< coefficients of added rows for (int j = 0; j < num; j++) { supports[j] = newCols[i]->support(j); coeffs[j] = newCols[i]->coeff(j); } newcol->setVector(num, supports, coeffs); lpSolverTime_.start(); osiLP_->addCol(*newcol, lb, ub, obj); lpSolverTime_.stop(); freeInt(supports); freeDouble(coeffs); } lpSolverTime_.start(); numCols_ = osiLP_->getNumCols(); collower_ = osiLP_->getColLower(); colupper_ = osiLP_->getColUpper(); objcoeff_ = osiLP_->getObjCoefficients(); lpSolverTime_.stop(); delete newcol; }
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]; }
void SparVec::leftShift(ArrayBuffer<int> &del) { const int nDel = del.size(); if (nDel == 0) return; int i,j; int current = del[0]; // shift all elements left of the last deleted element to the left side /* All elements in the arrays between the removed elements \a del[i] and * del[i+1] are shifted left in the inner loop. */ for (i = 0; i < nDel - 1; i++) { #ifdef ABACUSSAFE if(del[i] < 0 || del[i] >= nnz_) { Logger::ilout() << "ArrayBuffer:leftShift(): shift index " << i << " not valid.\n"; OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcSparVec); } #endif const int last = del[i+1]; for(j = del[i]+1; j < last; j++) { support_[current] = support_[j]; coeff_[current] = coeff_[j]; ++current; } } // shift all elements right of the last deleted element to the left side #ifdef ABACUSSAFE if(del[nDel -1] < 0 || del[nDel - 1] >= nnz_) { Logger::ilout() << "ArrayBuffer:leftShift(): shift index " << i << " not valid.\n"; OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcSparVec); } #endif for (j = del[nDel - 1] + 1; j < nnz_; j++) { support_[current] = support_[j]; coeff_[current] = coeff_[j]; ++current; } nnz_ -= nDel; }
void OsiIF::_remCols(ArrayBuffer<int> &vars) { int num = vars.size(); int *indices = new int[num]; for (int i = 0; i < num; i++) indices[i] = vars[i]; lpSolverTime_.start(); osiLP_->deleteCols(num, indices); numCols_ = osiLP_->getNumCols(); collower_ = osiLP_->getColLower(); colupper_ = osiLP_->getColUpper(); objcoeff_ = osiLP_->getObjCoefficients(); lpSolverTime_.stop(); freeInt(indices); }
void OsiIF::_remRows(ArrayBuffer<int> &ind) { const int n = ind.size(); int *indices = new int[n]; for (int i = 0; i < n; i++) { indices[i] = ind[i]; } lpSolverTime_.start(); osiLP_->deleteRows(n, indices); numRows_ = osiLP_->getNumRows(); rowsense_ = osiLP_->getRowSense(); rhs_ = osiLP_->getRightHandSide(); lpSolverTime_.stop(); freeInt(indices); }
void LpSub::constraint2row( ArrayBuffer<Constraint*> &cons, ArrayBuffer<Row*> &rows) { int conNnz; //!< number of nonzero elements in constraint Row rowBuf(master_, sub_->nVar()); //!< dummy to generate row Row *row; //!< pointer to the new row const int nCons = cons.size(); for (int c = 0; c < nCons; c++) { conNnz = cons[c]->genRow(sub_->actVar(), rowBuf); row = new Row(master_, conNnz); row->copy(rowBuf); rows.push(row); rowBuf.clear(); } }
void OsiIF::_addRows(ArrayBuffer<Row*> &rows) { CoinPackedVector *coinrow = new CoinPackedVector(); for (int i = 0; i < rows.size(); i++) { coinrow->clear(); for (int j = 0; j < rows[i]->nnz(); j++){ coinrow->insert(rows[i]->support(j), rows[i]->coeff(j)); } lpSolverTime_.start(); osiLP_->addRow(*coinrow, csense2osi(rows[i]->sense()), rows[i]->rhs(), 0.0); lpSolverTime_.stop(); } delete coinrow; lpSolverTime_.start(); numRows_ = osiLP_->getNumRows(); rhs_ = osiLP_->getRightHandSide(); numCols_ = osiLP_->getNumCols(); collower_ = osiLP_->getColLower(); colupper_ = osiLP_->getColUpper(); lpSolverTime_.stop(); }
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]; }
void LpSub::removeVars(ArrayBuffer<int> &vars) { // LpSub::removeVars(): local variables ArrayBuffer<int> lpVars(vars.size(),false); //!< indices in \a LP of removed variables Array<double> rhsDelta(0,sub_->nCon()-1, 0.0); //!< changes of right hand side int lpName; //!< name of variable in the \a LP double coeff; Variable *v; bool modifyRhs = false; double eps = master_->eps(); // LpSub::removeVars(): update the number of original variables int oldNOrigVar = nOrigVar_; nOrigVar_ -= vars.size(); // divide removed variables in eliminated and non-eliminated ones /* If a removed variable has earlier been eliminated from the LP, then * we might have to adapt the right hand side again, if earlier * the elimination changed the right and side. Otherwise, * we add the variable to the buffer \a lpVars in order to remove * it explicitly later. */ const int nVars = vars.size(); for (int i = 0; i < nVars; i++) { lpName = orig2lp_[vars[i]]; if (lpName == -1) { //! remove eliminated variable valueAdd_ += sub_->variable(i)->obj() * elimVal(i); const int nCon = sub_->nCon(); v = sub_->variable(i); for (int c = 0; c < nCon; c++) { coeff = sub_->constraint(c)->coeff(v); if (fabs(coeff) > eps) { rhsDelta[c] += coeff * elimVal(i); modifyRhs = true; } } } else lpVars.push(lpName); } // adapt the right hand side if eliminated variables are removed if (modifyRhs) { Array<double> newRhs(sub_->nCon()); const int nCon = sub_->nCon(); for (int c = 0; c < nCon; c++) newRhs[c] = rhs(c) - rhsDelta[c]; LP::changeRhs(newRhs); } // remove the non-eliminated variables /* Here, we also should check for constraints getting a void left hand side * and becoming infeasible. However, on the one hand this is computationally * expensive (using the member function \a row()) * as most LP-solvers (as, e.g., Cplex) work in a column oriented * form, and second, if immediately afterwards variables are added then * the linear program could become again feasible. * * Moreover, if only inequalities with void left hand side become infeasible, * then these infeasaibilities are recognized by the LP-solver and resolved * in \a makeFeas(). Only equations can cause some trouble as there is no * slack variable. * * Therefore, unfortunately, taking care that no equation becomes infeasible has to be * left to the user. */ LP::remCols(lpVars); // update mappings of original variables and LP variables // sort the variables being removed // check if sorting is required bool unordered = false; for (int i = 0; i < nVars - 1; i++) if (vars[i] > vars[i+1]) { unordered = true; break; } // if yes, sort the variables ArrayBuffer<int> varsSorted(oldNOrigVar,false); if (unordered) { Array<bool> marked(0,oldNOrigVar-1, false); for (int i = 0; i < nVars; i++) marked[vars[i]] = true; for (int i = 0; i < oldNOrigVar; i++) if (marked[i]) varsSorted.push(i); } else for (int i = 0; i < nVars; i++) varsSorted.push(vars[i]); // update mapping of original variables to LP variables /* In order to update the mapping of the original variables to the LP-variables * we have to eliminate the removed variables from the array \a orig2lp_ by a * leftshift. Moreover, if the variable \a i is not removed then we have to * reduce \a orig2lp_ by the number of variables that have been removed with a * index than \a i that have not been eliminated. */ int current = varsSorted[0]; int nNotEliminatedRemoved = 0; for (int i = 0; i < nVars - 1; i++) { if (orig2lp_[varsSorted[i]] != -1) nNotEliminatedRemoved++; const int last = varsSorted[i+1]; for(int j = varsSorted[i]+1; j < last; j++) if (orig2lp_[j] == -1) orig2lp_[current++] = -1; else orig2lp_[current++] = orig2lp_[j] - nNotEliminatedRemoved; } if (orig2lp_[varsSorted[nVars-1]] != -1) nNotEliminatedRemoved++; for (int j = varsSorted[nVars - 1] + 1; j < oldNOrigVar; j++) if (orig2lp_[j] == -1) orig2lp_[current++] = -1; else orig2lp_[current++] = orig2lp_[j] - nNotEliminatedRemoved; // update mapping of LP variables to original variables /* Since \a orig2lp_ is updated already we can update the reverse * mapping \a lp2orig_ in a straight forward way by scanning \a orig2lp_. */ int nVarLp = 0; for (int i = 0; i < nOrigVar_; i++) if (orig2lp_[i] != -1) lp2orig_[nVarLp++] = i; }