Ejemplo n.º 1
0
void Master::maxCpuTime(int hour, int min, int sec)
{

	if(sec >59||min >59){
		Logger::ifout() << "Master::setCpuTime() invalid argument \n - correct value: sec,min <=60\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcIllegalParameter);
	}
	maxCpuTime_ = int64_t(hour)*3600 + min*60 + sec;
}
Ejemplo n.º 2
0
void ConBranchRule::initialize(Sub* sub)
{
	if (poolSlotRef_.conVar() == nullptr) {
		Logger::ifout() << "ConBranchRule::initialize(): branching constraint not available\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcConBranchRule);
	}

	poolSlotRef_.conVar()->sub(sub);
}
Ejemplo n.º 3
0
void Master::requiredGuarantee(double g)
{
	if (g < 0.0) {
		Logger::ifout() << "Master::guarantee: " << g << "\nchoose nonnegative value.";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcIllegalParameter);
	}

	requiredGuarantee_ = g;
}
Ejemplo n.º 4
0
void LpSub::changeUBound(int i, double newUb)
{
	int lpVar = orig2lp_[i];

	if (lpVar == -1) {
		Logger::ifout() << "LpSub::changeUBound(" << i << " ," << newUb << ")\nvariable " << i << " is eliminated, cannot change bounds!\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcLpSub);
	}
	else LP::changeUBound(lpVar, newUb);
}
Ejemplo n.º 5
0
	void Stopwatch::stop()
	{
		if(!m_running) {
			Logger::ifout() << "Stopwatch::stop(): you cannot stop a non-running stopwatch.\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcTimer);
		}

		m_totalTime += theTime() - m_startTime;
		m_running   = false;
	}
Ejemplo n.º 6
0
void AbacusGlobal::insertParameter(const char *name, const char *value)
{
	if(!name||!value) {
		Logger::ifout() << "AbacusGlobal:insertParameter(): both arguments must\nbe non-zero pointers\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcGlobal);
	}
	string stName(name);
	string stValue(value);
	paramTable_.overWrite(stName, stValue);
}
Ejemplo n.º 7
0
CSense::SENSE OsiIF::osi2csense(char sense) const
{
	switch(sense) {
	case 'L': return CSense::Less;
	case 'E': return CSense::Equal;
	case 'G': return CSense::Greater;
	default:
		Logger::ifout() << "OsiIF::osi2csense( " << sense << " ) unknown sense";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf);
	}
}
Ejemplo n.º 8
0
void OsiIF::_sense(const OptSense &newSense)
{
	if (newSense.unknown()) {
		Logger::ifout() << "OsiIF::_sense: The objective sense can not be set to 'unknown' with OSI.\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf);
	}
	else if (newSense.max())
		osiLP_->setObjSense(-1.);
	else
		osiLP_->setObjSense(1.);
}
Ejemplo n.º 9
0
ConClass *Constraint::classification(Active<Variable, Constraint> *var) const
{
	if (conClass_ == nullptr || var) {
		if (var == nullptr) {
			Logger::ifout() << "Constraint::classification(): Fatal error.\nNeither classification nor variable set specified.\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcConstraint);
		}
		conClass_ = classify(var);
	}
	return conClass_;
}
Ejemplo n.º 10
0
char OsiIF::csense2osi(CSense *sense) const
{
	switch(sense->sense()) {
	case CSense::Less:  return 'L';
	case CSense::Equal:  return 'E';
	case CSense::Greater: return 'G';
	default:
		Logger::ifout() << "OsiIF::csense2osi unknown sense\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf);
	}
}
Ejemplo n.º 11
0
Archivo: master.cpp Proyecto: ogdf/ogdf
void Master::primalBound(double x)
{
	if (optSense()->max()) {
		if (x < primalBound_) {
			Logger::ifout() << "Error: Master::primalBound(): got worse\nold bound: " << primalBound_ << "\nnew bound: " << x << "\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::AlgorithmFailureCode::PrimalBound);
		}
	}
	else {
		if (x > primalBound_) {
			Logger::ifout() << "Error: Master::primalBound(): got worse\nold bound: " << primalBound_ << "\nnew bound: " << x << "\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::AlgorithmFailureCode::PrimalBound);
		}
	}

	// make sure that this is an integer value for \a objInteger_
	/* After the test for integrality, we round the value to the next
	*   integer. The reason is that a new primal bound coming obtained
	*   by the solution of the relaxation in a subproblem might have some
	*   garbage in it (e.g., \a 10.000000000034 or \a 9.999999999987).
	*   With this garbage the
	*   fathoming of node might fail in the subproblem optimization, although
	*   it is already correct.
	*/
	if (objInteger_) {
		if (!isInteger(x, eps())) {
			Logger::ifout() << "Master::primalBound(): value " << x << " is not integer, but feasible solutions with integer objective function values are expected.\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::AlgorithmFailureCode::NotInteger);
		}

		x = floor(x + eps());
	}

	primalBound_ = x;

	// update the primal bound in the Tree Interface
	if (optSense()->max()) treeInterfaceLowerBound(x);
	else                   treeInterfaceUpperBound(x);

	history_->update();
}
Ejemplo n.º 12
0
Archivo: master.cpp Proyecto: ogdf/ogdf
int Master::enumerationStrategy(const Sub *s1, const Sub *s2)
{
	switch (enumerationStrategy_) {
	case BestFirst:    return bestFirstSearch(s1, s2);
	case BreadthFirst: return breadthFirstSearch(s1, s2);
	case DepthFirst:   return depthFirstSearch(s1, s2);
	case DiveAndBest:  return diveAndBestFirstSearch(s1, s2);
	default:
		Logger::ifout() << "Master::enumerationStrategy(): Unknown enumeration strategy\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::AlgorithmFailureCode::IllegalParameter);
	}
}
Ejemplo n.º 13
0
int LpSub::getInfeas(int &infeasCon, int &infeasVar, double *bInvRow) const
{
	int status = LP::getInfeas(infeasCon, infeasVar, bInvRow);

	if (status) {
		Logger::ifout() << "LpSub::getInfeas(): LP::getInfeas() failed\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcLpSub);
	}

	if (infeasVar >= 0) infeasVar = lp2orig_[infeasVar];

	return 0;
}
Ejemplo n.º 14
0
void Master::dualBound(double x)
{
	if (optSense()->max()) {
		if (x > dualBound_) {
			Logger::ifout() << "Error: Master::dualBound(): got worse\nold bound: " << dualBound_ << "\nnew bound: " << x << "\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcDualBound);
		}
	}
	else
		if (x < dualBound_) {
			Logger::ifout() << "Error: Master::dualBound(): got worse\nold bound: " << dualBound_ << "\nnew bound: " << x << "\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcDualBound);
		}

		dualBound_ = x;

		//! update the dual bound in the Tree Interface
		if (optSense()->max()) treeInterfaceUpperBound(x);
		else                   treeInterfaceLowerBound(x);

		history_->update();
}
Ejemplo n.º 15
0
void PivotMDS::call(GraphAttributes& GA)
{
	if (!isConnected(GA.constGraph())) {
		OGDF_THROW_PARAM(PreconditionViolatedException,pvcConnected);
		return;
	}
	if (m_hasEdgeCostsAttribute
			&& !GA.has(GraphAttributes::edgeDoubleWeight)) {
				OGDF_THROW(PreconditionViolatedException);
		return;
	}
	pivotMDSLayout(GA);
}
Ejemplo n.º 16
0
	void Stopwatch::start(bool reset)
	{
		if (reset)
			m_totalTime = 0;

		else if (m_running) {
			Logger::ifout() << "Stopwatch::start(): you cannot start a running stopwatch.\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcTimer);
		}

		m_running   = true;
		m_startTime = theTime();
	}
Ejemplo n.º 17
0
	//
	// C o n s t r u c t o r
	//
	LineBuffer::LineBuffer(istream &is) :
		m_pIs(&is),
		m_pLinBuf(0),
		m_numberOfMostRecentlyReadLine(0),
		m_inputFileLineCounter(0)
	{
		if (!(*m_pIs)) {
			Logger::slout() << "LineBuffer::LineBuffer: Error opening file!\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, afcUnknown);
		}

		// Create and initialize lineUpdateCountArray
		m_lineUpdateCountArray = new int[LineBuffer::c_maxNoOfLines];
		int i;
		for (i = 0; i < LineBuffer::c_maxNoOfLines; i++){
			m_lineUpdateCountArray[i] = 0;
		}

		// Create and initialize line buffer
		m_pLinBuf = new char[(LineBuffer::c_maxNoOfLines * LineBuffer::c_maxLineLength)];
		if (m_pLinBuf == 0)
			OGDF_THROW(InsufficientMemoryException);
		for (i = 0; i < LineBuffer::c_maxNoOfLines * LineBuffer::c_maxLineLength; i++){
			m_pLinBuf[i] = '0';
		}

		// Read first line
		if (!m_pIs->eof()){

			// Read first line
			m_pIs->getline(m_pLinBuf, LineBuffer::c_maxLineLength);

			// Increase inputFileLineCounter
			++m_inputFileLineCounter;

			// Increase updateCount
			++(m_lineUpdateCountArray[0]);

		}
		// End of file is reached immeadiately
		else{

			// Set eof marker
			*m_pLinBuf = EOF;

		}

		// Set position
		m_currentPosition.set(0, m_lineUpdateCountArray[0], 0);

	} // LineBuffer::LineBuffer
Ejemplo n.º 18
0
void AbacusGlobal::readParameters(const string &fileName)
{
	string line;
	string name;
	string value;

	// open the parameter file \a fileName
	/* CHANGED  ifstream paramFile(fileName, ios::in \a  ios::nocreate);*/
	ifstream paramFile(OGDF_STRING_OPEN(fileName), ios::in);

	if (!paramFile) {
		Logger::ifout() << "AbacusGlobal::readParameters(): opening file " << fileName << " failed\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcGlobal);
	}
	// read the parameter file line by line
	/* Lines in a parameter file starting with \a '#' are comments and hence they
	*   are skipped. Every other non-void line must contain two strings. The
	*   first one is the name of the parameter, the second one its value.
	*/
	std::stringstream is;
	while( std::getline(paramFile, line) ) {
		if (line.empty() || line[0] == '#')
			continue;

		is.str(line);
		is.clear();

		if( !(is >> name) )
			continue; // empty line

		if( !(is >> value) ) {
			Logger::ifout() << "AbacusGlobal::readParameters " << fileName << " value missing for parameter " << name << "\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcGlobal);
		}
		else {
			paramTable_.overWrite(name, value);
		}
	}
Ejemplo n.º 19
0
Archivo: master.cpp Proyecto: ogdf/ogdf
double Master::guarantee() const
{
	double lb = lowerBound();

	if (fabs(lb) < machineEps()) {
		if (fabs(upperBound()) < machineEps())
			return 0.0;
		else {
			Logger::ifout() << "Master::guarantee(): cannot compute guarantee with lower bound 0\n";
			OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::AlgorithmFailureCode::IllegalParameter);
		}
	}
	return fabs((upperBound() - lb)/lb * 100.0);
}
Ejemplo n.º 20
0
LP::OPTSTAT LpSub::optimize(METHOD method)
{
	OPTSTAT status;

	if (infeasCons_.size()) {
		Logger::ifout() << "LpSub::optimize(): there are infeasible constraints\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcLpSub);
	}
	else {
		status = LP::optimize(method);
		if (status == Infeasible && method != Dual) return optimize(Dual);
		else                                        return status;
	}
}
Ejemplo n.º 21
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];
}
Ejemplo n.º 22
0
OsiSolverInterface* OsiIF::switchInterfaces(SOLVERTYPE newMethod)
{
	OsiSolverInterface *s2 = nullptr;
	if( newMethod == Exact )
	{
		s2 = getDefaultInterface();
	}
	else
	{
#ifdef OSI_VOL
		// TODO switchInterfaces
		// s2 = getApproxInterface()
		s2 = new OsiVolSolverInterface;
#else
		Logger::ifout() << "ABACUS has not been compiled with support for the Volume Algorithm, cannot switch to approximate solver.\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf);
#endif
	}

	s2->setHintParam(OsiDoReducePrint, true, OsiHintDo);
	s2->messageHandler()->setLogLevel(0);
	master_->setSolverParameters(s2, currentSolverType() == Approx);

	if (currentSolverType() == Exact && numRows_ == 0 && master_->defaultLpSolver() == Master::CPLEX) {
		loadDummyRow(s2, osiLP_->getColLower(), osiLP_->getColUpper(), osiLP_->getObjCoefficients());
	}
	else {
		s2->loadProblem(*osiLP_->getMatrixByCol(), osiLP_->getColLower(),
			osiLP_->getColUpper(), osiLP_->getObjCoefficients(),
			osiLP_->getRowLower(), osiLP_->getRowUpper());
	}

	s2->setObjSense(osiLP_->getObjSense());

	delete osiLP_;

	// get the pointers to the solution, reduced costs etc.
	rhs_ = s2->getRightHandSide();
	rowsense_ = s2->getRowSense();
	colupper_ = s2->getColUpper();
	collower_ = s2->getColLower();
	objcoeff_ = s2->getObjCoefficients();
	if( ws_ != nullptr )
		delete ws_;
	ws_ = dynamic_cast<CoinWarmStartBasis* >(s2->getWarmStart());

	xValStatus_ = recoStatus_= yValStatus_ = slackStatus_ = basisStatus_ = Missing;
	return s2;
}
Ejemplo n.º 23
0
	int CPXPUBLIC CPX_CutCallback(CPXCENVptr xenv, void *cbdata,
			int wherefrom, void *cbhandle, int *useraction_p) {
//		cout << "Entering CPX Callback\n" << flush;
		CPXLPptr nodelp;
		CPXgetcallbacknodelp(xenv, cbdata, wherefrom, &nodelp);

		CoinCallbacks* ccc = (CoinCallbacks*)cbhandle;
		
		int length = CPXgetnumcols(xenv,nodelp) - 1; //hey, don't ask me! some VERY WIERD PHENOMENON... crap
		double objVal;
		double* solution = new double[length];
		CPXgetcallbacknodeobjval(xenv, cbdata, wherefrom, &objVal);
		CPXgetcallbacknodex(xenv, cbdata, wherefrom, solution, 0, length-1);

		OsiCuts* cuts = new OsiCuts();		
		CoinCallbacks::CutReturn ret = ccc->cutCallback(objVal, solution, cuts);
		
		if(ret == CoinCallbacks::CR_AddCuts) {
			for(int i = cuts->sizeRowCuts(); i-->0;) {
				const OsiRowCut& c = cuts->rowCut(i);				
				const CoinPackedVector& vec = c.row();

				if(c.globallyValid())
					/* Old Cplex-Versions did NOT have the last parameter (now set to "false").
					 * If you compile agains an older CPLEX version, simple *REMOVE*
					 *   ", false"
					 * from the calls to CPXcutscallbackadd
					 */
					CPXcutcallbackadd(xenv, cbdata, wherefrom,
						vec.getNumElements(), c.rhs(), c.sense(), vec.getIndices(), vec.getElements(), false);  //default to non-purgable cuts
				else
					CPXcutcallbackaddlocal(xenv, cbdata, wherefrom,
						vec.getNumElements(), c.rhs(), c.sense(), vec.getIndices(), vec.getElements());
				cuts->eraseRowCut(i);
			}
			if(cuts->sizeColCuts() > 0) {
				cerr << "ColCuts currently not supported...\n";
				OGDF_THROW_PARAM(LibraryNotSupportedException, lnscFunctionNotImplemented);
			}
		}
		
		*useraction_p = ( ret == CoinCallbacks::CR_Error) ? CPX_CALLBACK_FAIL :
		                ( ret == CoinCallbacks::CR_AddCuts ) ? CPX_CALLBACK_SET : 
		                CPX_CALLBACK_DEFAULT;
		delete cuts;
		delete[] solution;
//		cout << "Leaving CPX Callback\n" << flush;
		return 0; // success
	}
Ejemplo n.º 24
0
double LpSub::elimVal(int i) const
{
	switch (sub_->fsVarStat(i)->status()) {
	case FSVarStat::SetToLowerBound:   return sub_->lBound(i);
	case FSVarStat::FixedToLowerBound: return sub_->variable(i)->lBound();
	case FSVarStat::SetToUpperBound:   return sub_->uBound(i);
	case FSVarStat::FixedToUpperBound: return sub_->variable(i)->uBound();
	case FSVarStat::Set:               return sub_->fsVarStat(i)->value();
	case FSVarStat::Fixed:             return sub_->variable(i)->fsVarStat()->value();

	default:
		Logger::ifout() << "LpSub::elimVal(): variable neither fixed nor set\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcLpSub);
	}
}
Ejemplo n.º 25
0
double LpSub::elimVal(FSVarStat *stat, double lb, double ub) const
{
	switch (stat->status()) {
	case FSVarStat::SetToLowerBound:   return lb;
	case FSVarStat::FixedToLowerBound: return lb;
	case FSVarStat::SetToUpperBound:   return ub;
	case FSVarStat::FixedToUpperBound: return ub;
	case FSVarStat::Set:               return stat->value();
	case FSVarStat::Fixed:             return stat->value();

	default:
		Logger::ifout() << "LpSub::elimVal(): variable neither fixed nor set\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcLpSub);
	}
}
Ejemplo n.º 26
0
SlackStat::STATUS OsiIF::osi2slackStat(CoinWarmStartBasis::Status stat) const
{
	switch (stat) {
	case CoinWarmStartBasis::atLowerBound:
		return SlackStat::NonBasicZero;
	case CoinWarmStartBasis::atUpperBound:
		return SlackStat::NonBasicNonZero;
	case CoinWarmStartBasis::basic:
		return SlackStat::Basic;
	case CoinWarmStartBasis::isFree:
	default:
		Logger::ifout() << "OsiIF::osi2slackStat( " << stat << " ) unknown status\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf);
	}
}
Ejemplo n.º 27
0
void SchnyderLayout::doCall(
	const Graph &G,
	adjEntry adjExternal,
	GridLayout &gridLayout,
	IPoint &boundingBox,
	bool fixEmbedding)
{
	// check for double edges & self loops
	OGDF_ASSERT(isSimple(G));

	// handle special case of graphs with less than 3 nodes
	if (G.numberOfNodes() < 3) {
		node v1, v2;
		switch (G.numberOfNodes()) {
		case 0:
			boundingBox = IPoint(0, 0);
			return;

		case 1:
			v1 = G.firstNode();
			gridLayout.x(v1) = gridLayout.y(v1) = 0;
			boundingBox = IPoint(0, 0);
			return;

		case 2:
			v1 = G.firstNode();
			v2 = G.lastNode();
			gridLayout.x(v1) = gridLayout.y(v1) = gridLayout.y(v2) = 0;
			gridLayout.x(v2) = 1;
			boundingBox = IPoint(1, 0);
			return;
		}
	}

	// make a copy for triangulation
	GraphCopy GC(G);

	// embed
	if (!fixEmbedding) {
		if (planarEmbed(GC) == false) {
			OGDF_THROW_PARAM(PreconditionViolatedException, pvcPlanar);
		}
	}

	triangulate(GC);

	schnyderEmbedding(GC, gridLayout, adjExternal);
}
Ejemplo n.º 28
0
InfeasCon::INFEAS Constraint::voidLhsViolated(double newRhs) const
{
	switch (sense_.sense()) {
	case CSense::Equal:
		if(newRhs > master_->eps())  return InfeasCon::TooLarge;
		if(newRhs < -master_->eps()) return InfeasCon::TooSmall;
		else                      return InfeasCon::Feasible;
	case CSense::Less:
		return newRhs < -master_->eps() ? InfeasCon::TooLarge : InfeasCon::Feasible;
	case CSense::Greater:
		return   newRhs > master_->eps() ? InfeasCon::TooSmall : InfeasCon::Feasible;
	default:
		Logger::ifout() << "Constraint::voidLhsViolated(): unknown sense\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcConstraint);
	}
}
Ejemplo n.º 29
0
double OsiIF::_slack(int i) const
{
	double rhs = rhs_[i];
	double ract = rowactivity_[i];
	switch (rowsense_[i]){
	case 'L':
		return rhs - ract;
	case 'G':
		return ract - rhs;
	case 'E':
		return 0.0;
	default:
		Logger::ifout() << "OsiIF::_slack : slack not defined for sense " << rowsense_[i] << " for row " << i << " of " << osiLP_->getNumRows() << " osiLP_->getNumRows()\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf);
	}
}
Ejemplo n.º 30
0
CoinWarmStartBasis::Status OsiIF::slackStat2osi(SlackStat::STATUS stat) const
{
	switch(stat) {
	case SlackStat::NonBasicZero:
		return CoinWarmStartBasis::atLowerBound;
	case SlackStat::Basic:
		return CoinWarmStartBasis::basic;
	case SlackStat::NonBasicNonZero:
		return CoinWarmStartBasis::atUpperBound;
	case SlackStat::Unknown:
		return CoinWarmStartBasis::atLowerBound;
	default:
		Logger::ifout() << "OsiIF::slackStat2osi( " << stat << " ) corresponding OSI status unknown\n";
		OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcOsiIf);
	}
}