1 // Copyright (C) 2000, International Business Machines
2 // Corporation and others.  All Rights Reserved.
3 // This code is licensed under the terms of the Eclipse Public License (EPL).
4 
5 #ifndef OsiXprSolverInterface_H
6 #define OsiXprSolverInterface_H
7 
8 #include <string>
9 #include <cstdio>
10 
11 #include "OsiSolverInterface.hpp"
12 
13 typedef struct xo_prob_struct *XPRSprob;
14 
15 //#############################################################################
16 
17 /** XPRESS-MP Solver Interface
18 
19     Instantiation of OsiSolverInterface for XPRESS-MP
20  */
21 class OsiXprSolverInterface : virtual public OsiSolverInterface {
22   friend void OsiXprSolverInterfaceUnitTest(const std::string &mpsDir, const std::string &netlibDir);
23 
24 public:
25   /**@name Solve methods */
26   //@{
27   /// Solve initial LP relaxation
28   virtual void initialSolve();
29 
30   /// Resolve an LP relaxation after problem modification
31   virtual void resolve();
32 
33   /// Invoke solver's built-in enumeration algorithm
34   virtual void branchAndBound();
35   //@}
36 
37   /**@name Parameter set/get methods
38 
39      The set methods return true if the parameter was set to the given value,
40      false otherwise. There can be various reasons for failure: the given
41      parameter is not applicable for the solver (e.g., refactorization
42      frequency for the volume algorithm), the parameter is not yet implemented
43      for the solver or simply the value of the parameter is out of the range
44      the solver accepts. If a parameter setting call returns false check the
45      details of your solver.
46 
47      The get methods return true if the given parameter is applicable for the
48      solver and is implemented. In this case the value of the parameter is
49      returned in the second argument. Otherwise they return false.
50   */
51   //@{
52   // Set an integer parameter
53   bool setIntParam(OsiIntParam key, int value);
54   // Set an double parameter
55   bool setDblParam(OsiDblParam key, double value);
56   // Set a string parameter
57   bool setStrParam(OsiStrParam key, const std::string &value);
58   // Get an integer parameter
59   bool getIntParam(OsiIntParam key, int &value) const;
60   // Get an double parameter
61   bool getDblParam(OsiDblParam key, double &value) const;
62   // Get a string parameter
63   bool getStrParam(OsiStrParam key, std::string &value) const;
64   // Set mipstart option (pass column solution to XPRESS before MIP start)
setMipStart(bool value)65   void setMipStart(bool value) { domipstart = value; }
66   // Get mipstart option value
getMipStart() const67   bool getMipStart() const { return domipstart; }
68   //@}
69 
70   //---------------------------------------------------------------------------
71   ///@name Methods returning info on how the solution process terminated
72   //@{
73   /// Are there a numerical difficulties?
74   virtual bool isAbandoned() const;
75   /// Is optimality proven?
76   virtual bool isProvenOptimal() const;
77   /// Is primal infeasiblity proven?
78   virtual bool isProvenPrimalInfeasible() const;
79   /// Is dual infeasiblity proven?
80   virtual bool isProvenDualInfeasible() const;
81   /// Is the given primal objective limit reached?
82   virtual bool isPrimalObjectiveLimitReached() const;
83   /// Is the given dual objective limit reached?
84   virtual bool isDualObjectiveLimitReached() const;
85   /// Iteration limit reached?
86   virtual bool isIterationLimitReached() const;
87   //@}
88 
89   //---------------------------------------------------------------------------
90   /**@name WarmStart related methods */
91   //@{
92   /// Get empty warm start object
93   CoinWarmStart *getEmptyWarmStart() const;
94   /// Get warmstarting information
95   virtual CoinWarmStart *getWarmStart() const;
96   /** Set warmstarting information. Return true/false depending on whether
97 	the warmstart information was accepted or not. */
98   virtual bool setWarmStart(const CoinWarmStart *warmstart);
99   //@}
100 
101   //---------------------------------------------------------------------------
102   /**@name Hotstart related methods (primarily used in strong branching). <br>
103      The user can create a hotstart (a snapshot) of the optimization process
104      then reoptimize over and over again always starting from there.<br>
105      <strong>NOTE</strong>: between hotstarted optimizations only
106      bound changes are allowed. */
107   //@{
108   /// Create a hotstart point of the optimization process
109   virtual void markHotStart();
110   /// Optimize starting from the hotstart
111   virtual void solveFromHotStart();
112   /// Delete the snapshot
113   virtual void unmarkHotStart();
114   //@}
115 
116   //---------------------------------------------------------------------------
117   /**@name Problem information methods
118 
119      These methods call the solver's query routines to return
120      information about the problem referred to by the current object.
121      Querying a problem that has no data associated with it result in
122      zeros for the number of rows and columns, and NULL pointers from
123      the methods that return vectors.
124 
125      Const pointers returned from any data-query method are valid as
126      long as the data is unchanged and the solver is not called.
127   */
128   //@{
129   /**@name Methods related to querying the input data */
130   //@{
131   /// Get number of columns
132   virtual int getNumCols() const;
133 
134   /// Get number of rows
135   virtual int getNumRows() const;
136 
137   /// Get number of nonzero elements
138   virtual int getNumElements() const;
139 
140   /// Get pointer to array[getNumCols()] of column lower bounds
141   virtual const double *getColLower() const;
142 
143   /// Get pointer to array[getNumCols()] of column upper bounds
144   virtual const double *getColUpper() const;
145 
146   /** Get pointer to array[getNumRows()] of row constraint senses.
147   	<ul>
148   	<li>'L': <= constraint
149   	<li>'E': =  constraint
150   	<li>'G': >= constraint
151   	<li>'R': ranged constraint
152   	<li>'N': free constraint
153   	</ul>
154       */
155   virtual const char *getRowSense() const;
156 
157   /** Get pointer to array[getNumRows()] of rows right-hand sides
158   	<ul>
159   	  <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i]
160   	  <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i]
161   	  <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i]
162   	  <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0
163   	</ul>
164       */
165   virtual const double *getRightHandSide() const;
166 
167   /** Get pointer to array[getNumRows()] of row ranges.
168   	<ul>
169             <li> if rowsense()[i] == 'R' then
170                     rowrange()[i] == rowupper()[i] - rowlower()[i]
171             <li> if rowsense()[i] != 'R' then
172                     rowrange()[i] is 0.0
173           </ul>
174       */
175   virtual const double *getRowRange() const;
176 
177   /// Get pointer to array[getNumRows()] of row lower bounds
178   virtual const double *getRowLower() const;
179 
180   /// Get pointer to array[getNumRows()] of row upper bounds
181   virtual const double *getRowUpper() const;
182 
183   /// Get pointer to array[getNumCols()] of objective function coefficients
184   virtual const double *getObjCoefficients() const;
185 
186   /// Get objective function sense (1 for min (default), -1 for max)
187   virtual double getObjSense() const;
188 
189   /// Return true if variable is continuous
190   virtual bool isContinuous(int colIndex) const;
191 
192 #if 0
193       /// Return true if variable is binary
194       virtual bool isBinary(int colIndex) const;
195 
196       /** Return true if column is integer.
197           Note: This function returns true if the the column
198           is binary or a general integer.
199       */
200       virtual bool isInteger(int colIndex) const;
201 
202       /// Return true if variable is general integer
203       virtual bool isIntegerNonBinary(int colIndex) const;
204 
205       /// Return true if variable is binary and not fixed at either bound
206       virtual bool isFreeBinary(int colIndex) const;
207 #endif
208   /// Get pointer to row-wise copy of matrix
209   virtual const CoinPackedMatrix *getMatrixByRow() const;
210 
211   /// Get pointer to column-wise copy of matrix
212   virtual const CoinPackedMatrix *getMatrixByCol() const;
213 
214   /// Get solver's value for infinity
215   virtual double getInfinity() const;
216   //@}
217 
218   /**@name Methods related to querying the solution */
219   //@{
220   /// Get pointer to array[getNumCols()] of primal solution vector
221   virtual const double *getColSolution() const;
222 
223   /// Get pointer to array[getNumRows()] of dual prices
224   virtual const double *getRowPrice() const;
225 
226   /// Get a pointer to array[getNumCols()] of reduced costs
227   virtual const double *getReducedCost() const;
228 
229   /** Get pointer to array[getNumRows()] of row activity levels (constraint
230   	matrix times the solution vector */
231   virtual const double *getRowActivity() const;
232 
233   /// Get objective function value
234   virtual double getObjValue() const;
235 
236   /** Get how many iterations it took to solve the problem (whatever
237 	  "iteration" mean to the solver. */
238   virtual int getIterationCount() const;
239 
240   /** Get as many dual rays as the solver can provide. (In case of proven
241           primal infeasibility there should be at least one.)
242 
243 	  The first getNumRows() ray components will always be associated with
244 	  the row duals (as returned by getRowPrice()). If \c fullRay is true,
245 	  the final getNumCols() entries will correspond to the ray components
246 	  associated with the nonbasic variables. If the full ray is requested
247 	  and the method cannot provide it, it will throw an exception.
248 
249           <strong>NOTE for implementers of solver interfaces:</strong> <br>
250           The double pointers in the vector should point to arrays of length
251           getNumRows() and they should be allocated via new[]. <br>
252 
253           <strong>NOTE for users of solver interfaces:</strong> <br>
254           It is the user's responsibility to free the double pointers in the
255           vector using delete[].
256       */
257   virtual std::vector< double * > getDualRays(int maxNumRays,
258     bool fullRay = false) const;
259   /** Get as many primal rays as the solver can provide. (In case of proven
260           dual infeasibility there should be at least one.)
261 
262           <strong>NOTE for implementers of solver interfaces:</strong> <br>
263           The double pointers in the vector should point to arrays of length
264           getNumCols() and they should be allocated via new[]. <br>
265 
266           <strong>NOTE for users of solver interfaces:</strong> <br>
267           It is the user's responsibility to free the double pointers in the
268           vector using delete[].
269       */
270   virtual std::vector< double * > getPrimalRays(int maxNumRays) const;
271 
272 #if 0
273       /** Get vector of indices of solution which are integer variables
274   	presently at fractional values */
275       virtual OsiVectorInt getFractionalIndices(const double etol=1.e-05)
276 	const;
277 #endif
278   //@}
279   //@}
280 
281   //---------------------------------------------------------------------------
282 
283   /**@name Problem modifying methods */
284   //@{
285   //-------------------------------------------------------------------------
286   /**@name Changing bounds on variables and constraints */
287   //@{
288   /** Set an objective function coefficient */
289   virtual void setObjCoeff(int elementIndex, double elementValue);
290 
291   /** Set a single column lower bound<br>
292     	  Use -COIN_DBL_MAX for -infinity. */
293   virtual void setColLower(int elementIndex, double elementValue);
294 
295   /** Set a single column upper bound<br>
296     	  Use COIN_DBL_MAX for infinity. */
297   virtual void setColUpper(int elementIndex, double elementValue);
298 
299   /** Set a single column lower and upper bound<br>
300     	  The default implementation just invokes setColLower() and
301     	  setColUpper() */
302   virtual void setColBounds(int elementIndex,
303     double lower, double upper);
304 
305   /** Set the bounds on a number of columns simultaneously<br>
306     	  The default implementation just invokes setColLower() and
307     	  setColUpper() over and over again.
308     	  @param indexFirst,indexLast pointers to the beginning and after the
309 	         end of the array of the indices of the variables whose
310 		 <em>either</em> bound changes
311     	  @param boundList the new lower/upper bound pairs for the variables
312       */
313   virtual void setColSetBounds(const int *indexFirst,
314     const int *indexLast,
315     const double *boundList);
316 
317   /** Set a single row lower bound<br>
318     	  Use -COIN_DBL_MAX for -infinity. */
319   virtual void setRowLower(int elementIndex, double elementValue);
320 
321   /** Set a single row upper bound<br>
322     	  Use COIN_DBL_MAX for infinity. */
323   virtual void setRowUpper(int elementIndex, double elementValue);
324 
325   /** Set a single row lower and upper bound<br>
326     	  The default implementation just invokes setRowLower() and
327     	  setRowUpper() */
328   virtual void setRowBounds(int elementIndex,
329     double lower, double upper);
330 
331   /** Set the type of a single row<br> */
332   virtual void setRowType(int index, char sense, double rightHandSide,
333     double range);
334 
335   /** Set the bounds on a number of rows simultaneously<br>
336     	  The default implementation just invokes setRowLower() and
337     	  setRowUpper() over and over again.
338     	  @param indexFirst,indexLast pointers to the beginning and after the
339 	         end of the array of the indices of the constraints whose
340 		 <em>either</em> bound changes
341     	  @param boundList the new lower/upper bound pairs for the constraints
342       */
343   virtual void setRowSetBounds(const int *indexFirst,
344     const int *indexLast,
345     const double *boundList);
346 
347   /** Set the type of a number of rows simultaneously<br>
348     	  The default implementation just invokes setRowType()
349     	  over and over again.
350     	  @param indexFirst,indexLast pointers to the beginning and after the
351 	         end of the array of the indices of the constraints whose
352 		 <em>any</em> characteristics changes
353     	  @param senseList the new senses
354     	  @param rhsList   the new right hand sides
355     	  @param rangeList the new ranges
356       */
357   virtual void setRowSetTypes(const int *indexFirst,
358     const int *indexLast,
359     const char *senseList,
360     const double *rhsList,
361     const double *rangeList);
362   //@}
363 
364   //-------------------------------------------------------------------------
365   /**@name Integrality related changing methods */
366   //@{
367   /** Set the index-th variable to be a continuous variable */
368   virtual void setContinuous(int index);
369   /** Set the index-th variable to be an integer variable */
370   virtual void setInteger(int index);
371   /** Set the variables listed in indices (which is of length len) to be
372 	  continuous variables */
373   virtual void setContinuous(const int *indices, int len);
374   /** Set the variables listed in indices (which is of length len) to be
375 	  integer variables */
376   virtual void setInteger(const int *indices, int len);
377   //@}
378 
379   //-------------------------------------------------------------------------
380   /// Set objective function sense (1 for min (default), -1 for max,)
381   virtual void setObjSense(double s);
382 
383   /** Set the primal solution column values
384 
385     	colsol[numcols()] is an array of values of the problem column
386     	variables. These values are copied to memory owned by the
387     	solver object or the solver.  They will be returned as the
388     	result of colsol() until changed by another call to
389     	setColsol() or by a call to any solver routine.  Whether the
390     	solver makes use of the solution in any way is
391     	solver-dependent.
392     */
393   virtual void setColSolution(const double *colsol);
394 
395   /** Set dual solution vector
396 
397     	rowprice[numrows()] is an array of values of the problem row
398     	dual variables. These values are copied to memory owned by the
399     	solver object or the solver.  They will be returned as the
400     	result of rowprice() until changed by another call to
401     	setRowprice() or by a call to any solver routine.  Whether the
402     	solver makes use of the solution in any way is
403     	solver-dependent.
404     */
405   virtual void setRowPrice(const double *rowprice);
406 
407   //-------------------------------------------------------------------------
408   /**@name Methods to expand a problem.<br>
409        Note that if a column is added then by default it will correspond to a
410        continuous variable. */
411   //@{
412   /** */
413   virtual void addCol(const CoinPackedVectorBase &vec,
414     const double collb, const double colub,
415     const double obj);
416   /** */
417   virtual void addCols(const int numcols,
418     const CoinPackedVectorBase *const *cols,
419     const double *collb, const double *colub,
420     const double *obj);
421   /** */
422   virtual void deleteCols(const int num, const int *colIndices);
423 
424   /** */
425   virtual void addRow(const CoinPackedVectorBase &vec,
426     const double rowlb, const double rowub);
427   /** */
428   virtual void addRow(const CoinPackedVectorBase &vec,
429     const char rowsen, const double rowrhs,
430     const double rowrng);
431   /** */
432   virtual void addRows(const int numrows,
433     const CoinPackedVectorBase *const *rows,
434     const double *rowlb, const double *rowub);
435   /** */
436   virtual void addRows(const int numrows,
437     const CoinPackedVectorBase *const *rows,
438     const char *rowsen, const double *rowrhs,
439     const double *rowrng);
440   /** */
441   virtual void deleteRows(const int num, const int *rowIndices);
442 #if 0
443       //-----------------------------------------------------------------------
444       /** Apply a collection of cuts.<br>
445     	  Only cuts which have an <code>effectiveness >= effectivenessLb</code>
446     	  are applied.
447     	  <ul>
448     	    <li> ReturnCode.numberIneffective() -- number of cuts which were
449                  not applied because they had an
450     	         <code>effectiveness < effectivenessLb</code>
451     	    <li> ReturnCode.numberInconsistent() -- number of invalid cuts
452     	    <li> ReturnCode.numberInconsistentWrtIntegerModel() -- number of
453                  cuts that are invalid with respect to this integer model
454             <li> ReturnCode.numberInfeasible() -- number of cuts that would
455     	         make this integer model infeasible
456             <li> ReturnCode.numberApplied() -- number of integer cuts which
457     	         were applied to the integer model
458             <li> cs.size() == numberIneffective() +
459                               numberInconsistent() +
460     			      numberInconsistentWrtIntegerModel() +
461     			      numberInfeasible() +
462     			      nubmerApplied()
463           </ul>
464       */
465       virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs,
466     					    double effectivenessLb = 0.0);
467     //@}
468   //@}
469 #endif
470   //---------------------------------------------------------------------------
471 
472   /**@name Methods to input a problem */
473   //@{
474   /** Load in an problem by copying the arguments (the constraints on the
475         rows are given by lower and upper bounds). If a pointer is 0 then the
476         following values are the default:
477         <ul>
478           <li> <code>colub</code>: all columns have upper bound infinity
479           <li> <code>collb</code>: all columns have lower bound 0
480           <li> <code>rowub</code>: all rows have upper bound infinity
481           <li> <code>rowlb</code>: all rows have lower bound -infinity
482 	  <li> <code>obj</code>: all variables have 0 objective coefficient
483         </ul>
484     */
485   virtual void loadProblem(const CoinPackedMatrix &matrix,
486     const double *collb, const double *colub,
487     const double *obj,
488     const double *rowlb, const double *rowub);
489 
490   /** Load in an problem by assuming ownership of the arguments (the
491         constraints on the rows are given by lower and upper bounds). For
492         default values see the previous method. <br>
493 	<strong>WARNING</strong>: The arguments passed to this method will be
494 	freed using the C++ <code>delete</code> and <code>delete[]</code>
495 	functions.
496     */
497   virtual void assignProblem(CoinPackedMatrix *&matrix,
498     double *&collb, double *&colub, double *&obj,
499     double *&rowlb, double *&rowub);
500 
501   /** Load in an problem by copying the arguments (the constraints on the
502 	rows are given by sense/rhs/range triplets). If a pointer is 0 then the
503 	following values are the default:
504 	<ul>
505           <li> <code>colub</code>: all columns have upper bound infinity
506           <li> <code>collb</code>: all columns have lower bound 0
507 	  <li> <code>obj</code>: all variables have 0 objective coefficient
508           <li> <code>rowsen</code>: all rows are >=
509           <li> <code>rowrhs</code>: all right hand sides are 0
510           <li> <code>rowrng</code>: 0 for the ranged rows
511         </ul>
512     */
513   virtual void loadProblem(const CoinPackedMatrix &matrix,
514     const double *collb, const double *colub,
515     const double *obj,
516     const char *rowsen, const double *rowrhs,
517     const double *rowrng);
518 
519   /** Load in an problem by assuming ownership of the arguments (the
520         constraints on the rows are given by sense/rhs/range triplets). For
521         default values see the previous method. <br>
522 	<strong>WARNING</strong>: The arguments passed to this method will be
523 	freed using the C++ <code>delete</code> and <code>delete[]</code>
524 	functions.
525     */
526   virtual void assignProblem(CoinPackedMatrix *&matrix,
527     double *&collb, double *&colub, double *&obj,
528     char *&rowsen, double *&rowrhs,
529     double *&rowrng);
530 
531   /** Just like the other loadProblem() methods except that the matrix is
532 	given in a standard column major ordered format (without gaps). */
533   virtual void loadProblem(const int numcols, const int numrows,
534     const int *start, const int *index,
535     const double *value,
536     const double *collb, const double *colub,
537     const double *obj,
538     const double *rowlb, const double *rowub);
539 
540   /** Just like the other loadProblem() methods except that the matrix is
541 	given in a standard column major ordered format (without gaps). */
542   virtual void loadProblem(const int numcols, const int numrows,
543     const int *start, const int *index,
544     const double *value,
545     const double *collb, const double *colub,
546     const double *obj,
547     const char *rowsen, const double *rowrhs,
548     const double *rowrng);
549 
550   /** Read an mps file from the given filename */
551   virtual int readMps(const char *filename,
552     const char *extension = "mps");
553 
554   /** Write the problem into an mps file of the given filename.
555      If objSense is non zero then -1.0 forces the code to write a
556     maximization objective and +1.0 to write a minimization one.
557     If 0.0 then solver can do what it wants */
558   virtual void writeMps(const char *filename,
559     const char *extension = "mps",
560     double objSense = 0.0) const;
561   //@}
562 
563   /**@name Message handling */
564   //@{
565   /** Pass in a message handler
566         It is the client's responsibility to destroy a message handler installed
567         by this routine; it will not be destroyed when the solver interface is
568         destroyed.
569      */
570   void passInMessageHandler(CoinMessageHandler *handler);
571   //@}
572 
573   //---------------------------------------------------------------------------
574 
575   /**@name XPRESS specific public interfaces */
576   //@{
577   /**@name Static instance counter methods */
578   //@{
579   /** XPRESS has a context that must be created prior to all other XPRESS
580 	  calls.
581         This method:
582         <ul>
583         <li>Increments by 1 the number of uses of the XPRESS environment.
584         <li>Creates the XPRESS context when the number of uses is changed to 1
585 	    from 0.
586         </ul>
587       */
588   static void incrementInstanceCounter();
589 
590   /** XPRESS has a context that should be deleted after XPRESS calls.
591         This method:
592         <ul>
593         <li>Decrements by 1 the number of uses of the XPRESS environment.
594         <li>Deletes the XPRESS context when the number of uses is change to
595         0 from 1.
596         </ul>
597       */
598   static void decrementInstanceCounter();
599 
600   /** Return the number of instances of instantiated objects using XPRESS
601 	  services. */
602   static unsigned int getNumInstances();
603 
604   /** Return a pointer to the XPRESS problem */
getLpPtr()605   XPRSprob getLpPtr() { return prob_; }
606   //@}
607 
608   /// Return XPRESS-MP Version number
609   static int version();
610 
611   /**@name Log File  */
612   //@{
613   static int iXprCallCount_;
614 
615   /// Get logfile FILE *
616   static FILE *getLogFilePtr();
617   /**Set logfile name. The logfile is an attempt to
618 	 capture the calls to Xpress functions for debugging. */
619   static void setLogFileName(const char *filename);
620   //@}
621   //@}
622 
623   /**@name Constructors and destructors */
624   //@{
625   /// Default Constructor
626   OsiXprSolverInterface(int newrows = 50, int newnz = 100);
627 
628   /// Clone
629   virtual OsiSolverInterface *clone(bool copyData = true) const;
630 
631   /// Copy constructor
632   OsiXprSolverInterface(const OsiXprSolverInterface &);
633 
634   /// Assignment operator
635   OsiXprSolverInterface &operator=(const OsiXprSolverInterface &rhs);
636 
637   /// Destructor
638   virtual ~OsiXprSolverInterface();
639   //@}
640 
641 protected:
642   /**@name Protected methods */
643   //@{
644   /// Apply a row cut.  Return true if cut was applied.
645   virtual void applyRowCut(const OsiRowCut &rc);
646 
647   /** Apply a column cut (bound adjustment).
648       Return true if cut was applied.
649     */
650   virtual void applyColCut(const OsiColCut &cc);
651   //@}
652 
653 private:
654   /**@name Private static class data */
655   //@{
656   /// Name of the logfile
657   static const char *logFileName_;
658 
659   /// The FILE* to the logfile
660   static FILE *logFilePtr_;
661 
662   /// Number of live problem instances
663   static unsigned int numInstances_;
664 
665   /// Counts calls to incrementInstanceCounter()
666   static unsigned int osiSerial_;
667 
668   //@}
669 
670   /**@name Private methods */
671   //@{
672   /// The real work of a copy constructor (used by copy and assignment)
673   void gutsOfCopy(const OsiXprSolverInterface &source);
674 
675   /// The real work of a constructor (used by construct and assignment)
676   void gutsOfConstructor();
677 
678   /// The real work of a destructor (used by copy and assignment)
679   void gutsOfDestructor();
680 
681   /// Destroy cached copy of solution data (whenever it changes)
682   void freeSolution();
683 
684   /** Destroy cached copies of problem and solution data (whenever they
685 	change) */
686   void freeCachedResults();
687 
688   /// Number of integer variables in the problem
689   int getNumIntVars() const;
690 
691   /**@name Methods to support for XPRESS-MP multiple matrix facility */
692   //@{
693   /// Build cached copy of variable types
694   void getVarTypes() const;
695 
696   /** Save the current problem in XPRESS (if necessary) and
697           make this problem current (restore if necessary).
698       */
699   void activateMe() const;
700 
701   /** Save and restore are necessary if there is data associated with
702           this problem.  Also, queries to a problem with no data should
703           respond sensibly; XPRESS query results are undefined.
704       */
705   bool isDataLoaded() const;
706   //@}
707   //@}
708 
709   /**@name Private member data */
710   //@{
711 
712   /**@name Data to support for XPRESS-MP multiple matrix facility */
713   //@{
714 
715   mutable XPRSprob prob_;
716 
717   /// XPRESS problem name (should be unique for each saved problem)
718   mutable std::string xprProbname_;
719   //@}
720 
721   /**@name Cached copies of XPRESS-MP problem data */
722   //@{
723   /** Pointer to row-wise copy of problem matrix coefficients.<br>
724           Note that XPRESS keeps the objective row in the
725           problem matrix, so row indices and counts are adjusted
726           accordingly.
727       */
728   mutable CoinPackedMatrix *matrixByRow_;
729   mutable CoinPackedMatrix *matrixByCol_;
730 
731   /// Pointer to dense vector of structural variable upper bounds
732   mutable double *colupper_;
733 
734   /// Pointer to dense vector of structural variable lower bounds
735   mutable double *collower_;
736 
737   /// Pointer to dense vector of slack variable upper bounds
738   mutable double *rowupper_;
739 
740   /// Pointer to dense vector of slack variable lower bounds
741   mutable double *rowlower_;
742 
743   /// Pointer to dense vector of row sense indicators
744   mutable char *rowsense_;
745 
746   /// Pointer to dense vector of row right-hand side values
747   mutable double *rhs_;
748 
749   /** Pointer to dense vector of slack upper bounds for range
750           constraints (undefined for non-range rows)
751       */
752   mutable double *rowrange_;
753 
754   /// Pointer to dense vector of objective coefficients
755   mutable double *objcoeffs_;
756 
757   /// Sense of objective (1 for min; -1 for max)
758   mutable double objsense_;
759 
760   /// Pointer to dense vector of primal structural variable values
761   mutable double *colsol_;
762 
763   /// Pointer to dense vector of primal slack variable values
764   mutable double *rowsol_;
765 
766   /// Pointer to dense vector of primal slack variable values
767   mutable double *rowact_;
768 
769   /// Pointer to dense vector of dual row variable values
770   mutable double *rowprice_;
771 
772   /// Pointer to dense vector of dual column variable values
773   mutable double *colprice_;
774 
775   /// Pointer to list of indices of XPRESS "global" variables
776   mutable int *ivarind_;
777 
778   /** Pointer to list of global variable types:
779       <ul>
780       <li>'B': binary variable
781       <li>'I': general integer variable (but might have 0-1  bounds)
782       <li>'P': partial integer variable (not currently supported)
783       <li>'S': sem-continuous variable (not currently supported)
784       </ul>
785       */
786   mutable char *ivartype_;
787 
788   /** Pointer to dense vector of variable types
789           (as above, or 'C' for continuous)
790       */
791   mutable char *vartype_;
792 
793   /** Indicates whether the last solve was for a MIP or an LP. */
794   mutable bool lastsolvewasmip;
795   //@}
796   //@}
797 
798   /// Whether to pass a column solution to XPRESS before starting MIP solve (loadmipsol)
799   bool domipstart;
800 };
801 
802 //#############################################################################
803 /** A function that tests the methods in the OsiXprSolverInterface class. */
804 void OsiXprSolverInterfaceUnitTest(const std::string &mpsDir, const std::string &netlibDir);
805 
806 #endif
807 
808 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
809 */
810