[Coin-discuss] Questions about OSI - 4

Laszlo Ladanyi ladanyi at us.ibm.com
Mon Jul 9 08:53:12 EDT 2001


On Thu, 5 Jul 2001, Antonio Frangioni wrote:

> >  > This would allow derived solvers to re-use the methods for setting/getting
> >  > their specific parameters together with the "standard" ones.
> >
> >  Could you explain this a bit more? If I understand your point correctly
> >  then you suggest this change so that the solvers could just simply pass
> >  the arguments to their internal routines without having to switch. However,
> >  the value of key can be different for different solvers
> 
> No, that was not the idea.
> 
> The point is: if you define enums OsiIntParam and OsiDblParam, you restrict
> from the beginning the set of parameters that can be set/read to only those
> for which you provided values in the enum.

That's true, and actually that's intentional. This way if a user wants to
access a parameter that's specific to one solver then it's much better if the
user has to get a pointer to the model and call directly the solver's
parameter setting routine. That way it'll be absolutely clear that the
application depends on that solver. 

On the other hand I have no objection to include in the global enum everything
that is relevant to at least two solvers :-).

> you have another - and, in our opinion, better - alternative.
> Quite simply, you can use the same [set/get]***Param routines that
> handle the parameters for the base class. You can do that because you
> can always use an enum where an int is required. So, if you pass as
> `key' an Osi***Param, the method will set/get one of the standard
> parameters. But you can pass other values, different from those, and
> use the same methods to set implementation-specific paramters.
> 
> There is also a nice way for doing this "extending" the enum.
> Assume your last OsiIntParam is `LastIntParam', and you want to define
> an OsiCplex class which has some other parameters to set.
> 
> What you can do is
> 
> 	enum OsiCplexIntParam { FirstCPXPar = LastIntParam + 1,
> 	                        SecondCPXPar ,
> 				ThirdCPXPar ...
> 				}
> 
> In this way you can do things like
> 
> 	setIntParam( LastIntParam , 10 );
> 	setIntParam( ThirdCPXParam , 3 );
> 
> i.e., use the same set/get methods for setting both the parameters
> common to all solvers (those in the abstract class) and those specific
> to one implementation, avoiding to littering the interface with at least
> four new methods.

This wouldn't work very well with the multiple inheritance.

> 
> >As for deletion I always assumed that solvers compact the matrix
> 
> We do have one solver which moves the last row in place of the deleted
> one and leaves everything else untouched. However, as long as the
> semantic is clearly stated in the interface we can accept everything.

I would say that the solvers could do anything they want, but they must report
to user as if they had preserved the original ordering of rows/columns. That
is how most of the solvers behave.

As for the hierarchy:

I completely agree with you on every issue. We have had similar ideas but
definitely didn't think them through yet and you gave a very lucid description
of the possibilities :-) Thanks! 

The solution we'd prefer is Model B, that is to have the dreaded diamond
multiple inheritance :-). I believe on the long run it ensures a much cleaner
implementation than hoarding every method into one single class.

For now I'd suggest the following hierarchy:
OsiSolverInterface;
OsiLpSolverInterface : public virtual OsiSolverInterface;
OsiSimplexLpSolverInterface : public virtual OsiLpSolverInterface;
OsiVolumeLpSolverInterface : public virtual OsiLpSolverInterface;
OsiBarrierLpSolverInterface : public virtual OsiLpSolverInterface;
OsiQpSolverInterface : public virtual OsiSolverInterface;

I'm not sure where to put MIP, derive it from LP or derive it directly from
the SolverInterface. Also, we got to decide what is in the solverinterface. Do
we assume anything? Like linear constraints? W

> 
> >  > Proposal 1 - Extend directly the class OsiSolverInterface. All the
> >  > "quadratic" methods have a default implementation, so any class derived
> >  > from OsiSolverInterface can be left unchanged.
> 
> ...
> 
> >  > Proposal 2 - Derive a new class OsiQPSolverInteface from OsiSolverInterface
> >  > with the "quadratic" methods.
> >
> >  Actually, the same question arose already and if I remember well, we
> >  decided to derive a new class. What's more we were thinking on deriving
> >  separate classes for simplex based on non-simplex based LP solvers and
> >  maybe a higher level class for IP solvers.
> 
> This point is really critical for us, so please allow me to insist on it.
> 
> I strongly favour the solution 1, or possibly the solution 3 that you
> sketch in your answer (if i understood it correctly). The solution 2
> has some huge disadvantages, from our viewpoint, that I need to point
> to your attention.
> 
> If we use solution 1, everybody who has a derived class from
> OsiSolverInterface will need to do nothing to adapt to the new setting.
> If I need a solver with the quadratic part, what I can do is
> 
> - take one implementation with a solver that is also a QP solver, say
>    Cplex, already available
> 
> - add the few parts for implementing the QP-related methods
> 
> - give back the class to its original mantainer, who will afterwards
>    take care of it.
> 
> In this way, the work I do is kept.
> 
> If we use solution 2 instead, what I need to do is
> 
> - take one implementation with a solver that is also a QP solver, say
>    Cplex, already available
> 
> - phisically copy all the code in a new class CplexQPSolver deriving from
>    OSIQPSolverInterface
> 
> - do the modifications
> 
> After that, this will be my own class and I'll be responsible for mantaining
> it. I won't be able to simply derive from the existing, say, OsiCplexSolver
> because this would require that OsiSolverInterface be a virtual base class of
> both OsiCplexSolver and OsiQPSolverInterface, which is not. So there will be
> two separate OsiCplexSolver and OsiQPSolver, mantained by two separate
> groups, although initially the differences will be minimal. If I stop
> having time and resources for mantaining CplexQPSolver, all the work I've
> done will go to waste. And anyway I won't be able to automatically benefit
> from the improvements in OsiCplexSolver that the original mantainer does.
> 
> We don't think that this solution is efficient in terms of software
> development. Quite frankly, we don't know if we are going to make this
> development effort if there are so little chances that our work will be
> beneficial to anybody else.
> 
> What we think is that deriving an OsiQPSolverInterface is a departure from
> the general idea of your current interface, and should probably be avoided.
> Or, better, you might have to take a fundamental decision between two
> different models of interface.
> 
> Model A: The OsiSolverInterface contains all the methods for all possible
>           kinds of solvers we can envision (LP, QP, MIP, Network ...). All
>           the methods are structured in such a way that if a solver does not
>           support some of the features, it simply has to avoid implementing
>           the corresponding methods (of which an implementation is provided
>           that just throws an exception).
> 
> Model B: There is a GenericOsiSolverInterface which contains only the
>           methods that are common to all solvers. Then there are, say,
>            OsiLPSolverInterface
> 	  OsiQPSolverInterface
> 	  OsiMIPSolverInterface
> 	 which all derive *virtual* from GenericOsiSolverInterface.
>           Maybe OsiLPSolverInterface could have other derived classes
>           like OsiLPSimplexSolverInterface and OsiLPIPSolverInterface.
>           Then, all the solvers derive from *one or more* of these classes.
>           For instance, Cplex would derive from them all. A pure LP would
>           derive from some of the LP*Solver. And so on.
> 
> At this point your interface is following Model A, but - if we understood
> correctly - you are thinking to switching to Model B. Maybe Model B should
> indeed be preferred, but that's not the point right now. Our (humble)
> opinion is that solution 2 is an hybrid between the two of which we see no
> advantages. So, we would like, if possible, to continue the discussion on
> this subject until we can understend your motivations for the choice.
> 
> Of course, we perfectly see that changing the interface of the base class
> is something that should be avoided as much as possible in a distributed
> open source effort. However, going with our proposal 1 would not harm the
> existing codebase, and would make us more confident that our development
> work won't be wasted.
> 
> We are more then ready to try to find a compromise between these conflicting
> needs. For instance, we could start with solution 2 as you suggest, and
> when our derived class is ready and tested we could migrate the methods to
> the OsiSolverInterface (assuming you keep on following Model A). This would
> require more work than starting with solution 1 directly, but if it makes
> the thing feasible, we could do that.
> 
> Sorry for the long and complicated e-mail, but we reall need to sort these
> things out before starting to commit to the real implementation. Anyway, we
> think that these design decisions are very crucial, and need to be carefully
> pondered. We do believe that you did, so we'd like to understend better what
> you points are.

As I noted above, we have not pondered too much about how to extend the solver
interface. I'm afraid we were just adding whatever came along and we just
recently started to think about how it can be extended. Your comments (however
lengthy :-) are very much appreciated.

> 
> 				Best Regards
> 
> 				Antonio Frangioni
> 

Regards,
--Laci





More information about the Coin-discuss mailing list