Example #1
0
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;
}
Example #2
0
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];
}
Example #3
0
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;
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
0
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();
	}
}
Example #7
0
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();

}
Example #8
0
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];
}
Example #9
0
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;
}