[Coin-discuss] Hints, throws, OsiForceDo

Lou Hafer lou at cs.sfu.ca
Wed May 7 15:05:11 EDT 2003


Folks,

	After working up an initial implementation of hints for
OsiDylpSolverInterface (ODSI), I did a rewrite of testHintParam in the
unitTest so that it would check for proper use of throws when the strength is
OsiForceDo. The results were, in hindsight, obvious: A throw for every hint,
true or false, when strength is OsiForceDo. The result is the same for dylp
and for clp (my default testing partner).

	Arguably the client should be expecting the possibility of a throw 
when using OsiForceDo, but it seems like a `throw on failure' policy would be
more appropriate.

	The OsiSolverInterface (OSI) hint arrays are private data, so there's
no way to reach them except through the default [set,get]HintParam routines.
Possible solutions:

  0) Do nothing. Client must always be prepared to catch, then ascertain
     success/failure.

  1) Declare the hint arrays protected, so they could be accessed directly
     by derived classes. [set,get]HintParam are simply overridden.

  2) Catch the throw in the getHintParam method of the derived class. Rethrow
     if appropriate.

  3) Abandon the hint arrays declared in OSI and declare new hint arrays in
     the derived class.

Currently I've implemented 2). I'd actually prefer 1), from an `ease of use'
viewpoint, but it allows exposure of OSI implementation details.

	Revised testHintParam code follows, with informational printing.

	Thoughts?

						Lou

=======================================================================

#include <sstream>

static bool testHintParam(OsiSolverInterface * si, int k, bool sense,
			  OsiHintStrength strength)
/*
  Tests for proper behaviour of [set,get]HintParam methods. The initial get
  tests if the hint is implemented.
  
  If yes, a pair of set/get calls is performed at the strength specified by
  the parameter. This can return true or (at strength OsiForceDo) throw an
  exception. The rationale would be that only OsiForceDo must be obeyed, so
  anything else should return true regardless of whether the solver followed
  the hint.

  If no, attempting to set the hint should return false or throw an exception
  at strength OsiForceDo.
*/
{ bool post_sense = true, pre_sense = true ;
  OsiHintStrength post_strength = OsiHintDo, pre_strength = OsiHintDo ;
  bool ret ;
  OsiHintParam key = static_cast<OsiHintParam>(k) ;

  if (si->getHintParam(key,pre_sense,pre_strength))
  { ret = false ;
    try
    { if (si->setHintParam(key,sense,strength))
      { ret = (si->getHintParam(key,post_sense,post_strength) == true) &&
	      (post_strength == strength) ; } }
    catch (CoinError)
    { std::ostringstream msg ;
      msg << "setHintParam throw for hint " << key << " sense " << sense <<
	      " strength " << strength ;
      failureMessage(*si,msg.str()) ;
      ret = (strength == OsiForceDo) ; } }
  else
  { ret = true ;
    try
    { ret = si->setHintParam(key,sense,strength) ; }
    catch (CoinError)
    { std::ostringstream msg ;
      msg << "setHintParam throw for hint " << key << " sense " << sense <<
	      " strength " << strength ;
      failureMessage(*si,msg.str()) ;
      ret = !(strength == OsiForceDo) ; } }
  
  return ret ; }

// And add these two lines with all the other calls to testHintParam

      assert(!exists ^ testHintParam(si, i, true, OsiForceDo));
      assert(!exists ^ testHintParam(si, i, false, OsiForceDo));




More information about the Coin-discuss mailing list