[Scip] Howto setup SCIP to solve LP change Matrix and resolve

Tobias Achterberg achterberg at zib.de
Fri Jul 24 09:33:11 MEST 2009


Hi Fergal,

you cannot use the LPI in this way. SCIP creates the LP relaxation of the problem when it
starts solving the root node. Therefore, if you freed the transformed problem (and the
whole search tree), there is no LP relaxation available anymore.

As far as I remember, you want to have an interface with which you can solve MIPs and LPs.
You can just do this with SCIP alone, because LPs are just a special case of MIPs. The
main issue with SCIP in this regard is that you cannot query the dual solution after an LP
solve because this concept is not available in MIP.

What you can do is the following:

Only use SCIP in your interface. This should allow you to implement most of your API
methods. Note that your method "Rows()" should return SCIPgetNConss(scip), and your method
"Cols()" should return SCIPgetNVars(scip).

In the dual solution query methods you need to do a trick. First, you probably should
assert that the problem at hand is indeed an LP, i.e., does not have any integegrality
restrictions. After you have called SCIPsolve(), the LP relaxation has been setup (at
least if the problem was not already solved in presolve) and the root node has been
solved. Since the problem was an LP, solving the root node solves the problem and SCIP is
done. Now, you can get the LPI via SCIPgetLPI() and query the LPI methods for the dual
solution vectors. The remaining problem is that these vectors are in terms of the
presolved model and you have to translate them to the original model, which is a
non-trivial task for the duals. Therefore, I suggest that in your solve() method you
disable presolve whenever you have an LP. Since the presolving of the embedded LP solver
is still active, you are not loosing anything by disabling SCIP's presolve.

So, the whole code could look as follows:

void solve()
{
   if (m_islp)
   {
      int oldmaxrounds;
      SCIP_CALL_EXC( SCIPgetIntParam(m_pMySCIP, "presolving/maxrounds", &oldmaxrounds) );
      SCIP_CALL_EXC( SCIPsetIntParam(m_pMySCIP, "presolving/maxrounds", 0) );
      SCIP_CALL_EXC( SCIPsolve(m_pMySCIP) );
      SCIP_CALL_EXC( SCIPsetIntParam(m_pMySCIP, "presolving/maxrounds", oldmaxrounds) );
   }
   else
   {
      SCIP_CALL_EXC( SCIPsolve(m_pMySCIP) );
   }
}

void getDualsol(double *dualsol)
{
   SCIP_LPI* p_Lpi = NULL;

   assert(m_islp);
   SCIP_CALL_EXC( SCIPgetLPI(m_pMySCIP, &p_Lpi) );
   SCIP_CALL_EXC( SCIPlpiGetSol(p_Lpi, NULL, NULL, dualsol, NULL, NULL) );
}


It may happen that you encounter problems with the ordering of the rows and columns in the
LP, namely that the order is different from the constraints in your SCIP object. If this
is the case, then you have to add a mapping layer in between.


Tobias


fergal mohan wrote:
> Hi guys, in the .NET wrapper that I'm working on I'm trying to keep the interface methods primarily row and column based (for simplicity). I'm hoping that I can get some insight into any potential limitations of calling SCIPgetLPI. I realize that there are stages when it's not valid to be treating SCIP as an LPSolver but am a little hazy about the limits. I ran into one such limit when I tried to the following call sequence, Optimize, SCIPfreeTransform(), add a Constraint, and then I called a method that tries to get the number of Rows() see below. 
> I get the "cannot call method SCIPgetLPI in problem creation stage" message. I can work around this particular limitation by consulting my own reference number of Constraints (and number of Variables for the Columns) but would like to program in some safegaurds wherever I can. Are there any rules to safe calling SCIPgetLPI ? Any advice or tips would be appreciated, cheers, Fergal
> int Rows()
> {
> 	int rowCount = -1;
> 	if(m_pMySCIP)
> 	{
> 		SCIP_LPI* p_Lpi = NULL;
> 		SCIPgetLPI(m_pMySCIP, &p_Lpi);
> 		if(p_Lpi)
> 			SCIPlpiGetNRows(p_Lpi, &rowCount);
> 	}
> 	return rowCount;
> }
> 
> 
> --- On Tue, 7/14/09, Timo Berthold <berthold at zib.de> wrote:
> 
>> From: Timo Berthold <berthold at zib.de>
>> Subject: Re: [Scip] Howto setup SCIP to solve LP change Matrix and resolve
>> To: scip at zib.de
>> Date: Tuesday, July 14, 2009, 7:51 AM
>> Hi Fergal.
>>
>> The method you are looking for is SCIPfreeTransform() (see
>>
>> http://scip.zib.de/doc/html/scip_8h.html#9c2399c2334680cd8ad14a1a5ac31622)
>> Some explanation on the role of the original and the
>> transformed problem is 
>> given in Q/A 15 of the SCIP FAQ: http://scip.zib.de/faq.shtml#Q15
>>
>> Furthermore, you might consider to use the SCIP_CALL() /
>> SCIP_CALL_ABORT() 
>> macros for catching the SCIP_RETCODE's. See http://scip.zib.de/faq.shtml#Q17 
>> for an explanation and the end of 
>> http://scip.zib.de/doc/html/def_8h-source.html for
>> their definition.
>>
>> I hope that helps resolving your problem.
>>
>> Best, Timo
>>
>>
>> Am Tuesday 14 July 2009 16:35:25 schrieb fergal mohan:
>>> Hi all, I'm getting on well with the implementation of
>> the .NET wrapper to
>>> use SCIP instead of Soplex but am running into an
>> exception when I try to
>>> change the Matrix after I've already Solved. If there
>> anyting specific that
>>> needs to be called after solve before changeing a
>> Matrix values. It could
>>> be one of the many parameters that I'm passing to
>> Create the Constraint or
>>> Var but I'm hoping someone can confirm ? I wrote a
>> small C++ Test App that
>>> I can attach if that helps but the jist of it is the
>> below. BTW the
>>> getConstraint method calls
>>> SCIP_CALL_EXC(SCIPcreateConsLinear(m_pMySCIP, &
>> newCons, namebuf,
>>> 0, NULL, NULL,
>>> MINUSINFINITY, PLUSINFINITY,
>>> TRUE, TRUE, TRUE, TRUE, TRUE, FALSE,
>>> FALSE, FALSE, FALSE, FALSE));
>>> SCIP_CALL_EXC( SCIPaddCons(m_pMySCIP, newCons) );
>>> the getValue method calls
>>> SCIP_CALL_EXC( SCIPcreateVar(scip, &newvar, name,
>>>     0.0, SCIPinfinity(scip), 0.0,
>> SCIP_VARTYPE_CONTINUOUS,
>>>     TRUE/*initial*/,
>> FALSE/*removable*/,
>>>     NULL, NULL, NULL, NULL) );
>>> Any ideas would be appreciated.
>>> Fergal
>>> // Test App solves successfully with the following
>> call
>>> oSCIPPenv->Solve();   
>>         // calls SCIPsolve
>>> std::cout << "Result is " <<
>> oSCIPPenv->GetObjValue() << std::endl;
>>> // change a matrix value (2, 0) = 2 and resolve
>>> dColValue = 2;
>>> if(oSCIPPenv->getConstraint(m_pMySCIP, 2,
>> &cons, &wasCreated) == SCIP_OKAY)
>>>   if(oSCIPPenv->getVariable(m_pMySCIP, 0,
>> &var, &wasCreated) == SCIP_OKAY)
>>>    SCIP_CALL_EXC(SCIPaddCoefLinear(m_pMySCIP,
>> cons, var, dColValue));
>>> oSCIPPenv->Solve();   
>>         // calls SCIPsolve
>>> <<
>>> the call to SCIPaddCoefLinear fails down in the
>> SCIPlockVarCons Routine
>>> when it appears to be in the wrong (Transformed)
>> stage.
>>> _______________________________________________
>>> Scip mailing list
>>> Scip at zib.de
>>> http://listserv.zib.de/mailman/listinfo/scip
>>
>> _______________________________________________
>> Scip mailing list
>> Scip at zib.de
>> http://listserv.zib.de/mailman/listinfo/scip
>>
> 
> _______________________________________________
> Scip mailing list
> Scip at zib.de
> http://listserv.zib.de/mailman/listinfo/scip


More information about the Scip mailing list