1// Copyright (C) 2006, 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 OsiBranchingObject_H
6#define OsiBranchingObject_H
7
8#include <cassert>
9#include <string>
10#include <vector>
11
12#include "CoinError.hpp"
13#include "CoinTypes.hpp"
14
15class OsiSolverInterface;
16class OsiSolverBranch;
17
18class OsiBranchingObject;
19class OsiBranchingInformation;
20
21//#############################################################################
22//This contains the abstract base class for an object and for branching.
23//It also contains a simple integer class
24//#############################################################################
25
26/** Abstract base class for `objects'.
27
28 The branching model used in Osi is based on the idea of an <i>object</i>.
29 In the abstract, an object is something that has a feasible region, can be
30 evaluated for infeasibility, can be branched on (<i>i.e.</i>, there's some
31 constructive action to be taken to move toward feasibility), and allows
32 comparison of the effect of branching.
33
34 This class (OsiObject) is the base class for an object. To round out the
35 branching model, the class OsiBranchingObject describes how to perform a
36 branch, and the class OsiBranchDecision describes how to compare two
37 OsiBranchingObjects.
38
39 To create a new type of object you need to provide three methods:
40 #infeasibility(), #feasibleRegion(), and #createBranch(), described below.
41
42 This base class is primarily virtual to allow for any form of structure.
43 Any form of discontinuity is allowed.
44
45 As there is an overhead in getting information from solvers and because
46 other useful information is available there is also an OsiBranchingInformation
47 class which can contain pointers to information.
48 If used it must at minimum contain pointers to current value of objective,
49 maximum allowed objective and pointers to arrays for bounds and solution
50 and direction of optimization. Also integer and primal tolerance.
51
52 Classes which inherit might have other information such as depth, number of
53 solutions, pseudo-shadow prices etc etc.
54 May be easier just to throw in here - as I keep doing
55*/
56class OsiObject {
57
58public:
59
60 /// Default Constructor
61 OsiObject ();
62
63 /// Copy constructor
64 OsiObject ( const OsiObject &);
65
66 /// Assignment operator
67 OsiObject & operator=( const OsiObject& rhs);
68
69 /// Clone
70 virtual OsiObject * clone() const=0;
71
72 /// Destructor
73 virtual ~OsiObject ();
74
75 /** Infeasibility of the object
76
77 This is some measure of the infeasibility of the object. 0.0
78 indicates that the object is satisfied.
79
80 The preferred branching direction is returned in whichWay, where for
81 normal two-way branching 0 is down, 1 is up
82
83 This is used to prepare for strong branching but should also think of
84 case when no strong branching
85
86 The object may also compute an estimate of cost of going "up" or "down".
87 This will probably be based on pseudo-cost ideas
88
89 This should also set mutable infeasibility_ and whichWay_
90 This is for instant re-use for speed
91
92 Default for this just calls infeasibility with OsiBranchingInformation
93 NOTE - Convention says that an infeasibility of COIN_DBL_MAX means
94 object has worked out it can't be satisfied!
95 */
96 double infeasibility(const OsiSolverInterface * solver,int &whichWay) const ;
97 // Faster version when more information available
98 virtual double infeasibility(const OsiBranchingInformation * info, int &whichWay) const =0;
99 // This does NOT set mutable stuff
100 virtual double checkInfeasibility(const OsiBranchingInformation * info) const;
101
102 /** For the variable(s) referenced by the object,
103 look at the current solution and set bounds to match the solution.
104 Returns measure of how much it had to move solution to make feasible
105 */
106 virtual double feasibleRegion(OsiSolverInterface * solver) const ;
107 /** For the variable(s) referenced by the object,
108 look at the current solution and set bounds to match the solution.
109 Returns measure of how much it had to move solution to make feasible
110 Faster version
111 */
112 virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const =0;
113
114 /** Create a branching object and indicate which way to branch first.
115
116 The branching object has to know how to create branches (fix
117 variables, etc.)
118 */
119 virtual OsiBranchingObject * createBranch(OsiSolverInterface * /*solver*/,
120 const OsiBranchingInformation * /*info*/,
121 int /*way*/) const {throw CoinError("Need code","createBranch","OsiBranchingObject"); return nullptr; }
122
123 /** \brief Return true if object can take part in normal heuristics
124 */
125 virtual bool canDoHeuristics() const
126 {return true;}
127 /** \brief Return true if object can take part in move to nearest heuristic
128 */
129 virtual bool canMoveToNearest() const
130 {return false;}
131 /** Column number if single column object -1 otherwise,
132 Used by heuristics
133 */
134 virtual int columnNumber() const;
135 /// Return Priority - note 1 is highest priority
136 inline int priority() const
137 { return priority_;}
138 /// Set priority
139 inline void setPriority(int priority)
140 { priority_ = priority;}
141 /** \brief Return true if branch should only bound variables
142 */
143 virtual bool boundBranch() const
144 {return true;}
145 /// Return true if knows how to deal with Pseudo Shadow Prices
146 virtual bool canHandleShadowPrices() const
147 { return false;}
148 /// Return maximum number of ways branch may have
149 inline int numberWays() const
150 { return numberWays_;}
151 /// Set maximum number of ways branch may have
152 inline void setNumberWays(int numberWays)
153 { numberWays_ = static_cast<short int>(numberWays) ; }
154 /** Return preferred way to branch. If two
155 then way=0 means down and 1 means up, otherwise
156 way points to preferred branch
157 */
158 inline void setWhichWay(int way)
159 { whichWay_ = static_cast<short int>(way) ; }
160 /** Return current preferred way to branch. If two
161 then way=0 means down and 1 means up, otherwise
162 way points to preferred branch
163 */
164 inline int whichWay() const
165 { return whichWay_;}
166 /// Get pre-emptive preferred way of branching - -1 off, 0 down, 1 up (for 2-way)
167 virtual int preferredWay() const
168 { return -1;}
169 /// Return infeasibility
170 inline double infeasibility() const
171 { return infeasibility_;}
172 /// Return "up" estimate (default 1.0e-5)
173 virtual double upEstimate() const;
174 /// Return "down" estimate (default 1.0e-5)
175 virtual double downEstimate() const;
176 /** Reset variable bounds to their original values.
177 Bounds may be tightened, so it may be good to be able to reset them to
178 their original values.
179 */
180 virtual void resetBounds(const OsiSolverInterface * ) {}
181 /** Change column numbers after preprocessing
182 */
183 virtual void resetSequenceEtc(int , const int * ) {}
184 /// Updates stuff like pseudocosts before threads
185 virtual void updateBefore(const OsiObject * ) {}
186 /// Updates stuff like pseudocosts after threads finished
187 virtual void updateAfter(const OsiObject * , const OsiObject * ) {}
188
189protected:
190 /// data
191
192 /// Computed infeasibility
193 mutable double infeasibility_;
194 /// Computed preferred way to branch
195 mutable short whichWay_;
196 /// Maximum number of ways on branch
197 short numberWays_;
198 /// Priority
199 int priority_;
200
201};
202/// Define a class to add a bit of complexity to OsiObject
203/// This assumes 2 way branching
204
205
206class OsiObject2 : public OsiObject {
207
208public:
209
210 /// Default Constructor
211 OsiObject2 ();
212
213 /// Copy constructor
214 OsiObject2 ( const OsiObject2 &);
215
216 /// Assignment operator
217 OsiObject2 & operator=( const OsiObject2& rhs);
218
219 /// Destructor
220 virtual ~OsiObject2 ();
221
222 /// Set preferred way of branching - -1 off, 0 down, 1 up (for 2-way)
223 inline void setPreferredWay(int value)
224 {preferredWay_=value;}
225
226 /// Get preferred way of branching - -1 off, 0 down, 1 up (for 2-way)
227 virtual int preferredWay() const override
228 { return preferredWay_;}
229protected:
230 /// Preferred way of branching - -1 off, 0 down, 1 up (for 2-way)
231 int preferredWay_;
232 /// "Infeasibility" on other way
233 mutable double otherInfeasibility_;
234
235};
236
237/** \brief Abstract branching object base class
238
239 In the abstract, an OsiBranchingObject contains instructions for how to
240 branch. We want an abstract class so that we can describe how to branch on
241 simple objects (<i>e.g.</i>, integers) and more exotic objects
242 (<i>e.g.</i>, cliques or hyperplanes).
243
244 The #branch() method is the crucial routine: it is expected to be able to
245 step through a set of branch arms, executing the actions required to create
246 each subproblem in turn. The base class is primarily virtual to allow for
247 a wide range of problem modifications.
248
249 See OsiObject for an overview of the two classes (OsiObject and
250 OsiBranchingObject) which make up Osi's branching
251 model.
252*/
253
254class OsiBranchingObject {
255
256public:
257
258 /// Default Constructor
259 OsiBranchingObject ();
260
261 /// Constructor
262 OsiBranchingObject (OsiSolverInterface * solver, double value);
263
264 /// Copy constructor
265 OsiBranchingObject ( const OsiBranchingObject &);
266
267 /// Assignment operator
268 OsiBranchingObject & operator=( const OsiBranchingObject& rhs);
269
270 /// Clone
271 virtual OsiBranchingObject * clone() const=0;
272
273 /// Destructor
274 virtual ~OsiBranchingObject ();
275
276 /// The number of branch arms created for this branching object
277 inline int numberBranches() const
278 {return numberBranches_;}
279
280 /// The number of branch arms left for this branching object
281 inline int numberBranchesLeft() const
282 {return numberBranches_-branchIndex_;}
283
284 /// Increment the number of branch arms left for this branching object
285 inline void incrementNumberBranchesLeft()
286 { numberBranches_ ++;}
287
288 /** Set the number of branch arms left for this branching object
289 Just for forcing
290 */
291 inline void setNumberBranchesLeft(int /*value*/)
292 {/*assert (value==1&&!branchIndex_);*/ numberBranches_=1;}
293
294 /// Decrement the number of branch arms left for this branching object
295 inline void decrementNumberBranchesLeft()
296 {branchIndex_++;}
297
298 /** \brief Execute the actions required to branch, as specified by the
299 current state of the branching object, and advance the object's
300 state.
301 Returns change in guessed objective on next branch
302 */
303 virtual double branch(OsiSolverInterface * solver)=0;
304 /** \brief Execute the actions required to branch, as specified by the
305 current state of the branching object, and advance the object's
306 state.
307 Returns change in guessed objective on next branch
308 */
309 virtual double branch() {return branch(nullptr);}
310 /** \brief Return true if branch should fix variables
311 */
312 virtual bool boundBranch() const
313 {return true;}
314 /** Get the state of the branching object
315 This is just the branch index
316 */
317 inline int branchIndex() const
318 {return branchIndex_;}
319
320 /** Set the state of the branching object.
321 */
322 inline void setBranchingIndex(int branchIndex)
323 { branchIndex_ = static_cast<short int>(branchIndex) ; }
324
325 /// Current value
326 inline double value() const
327 {return value_;}
328
329 /// Return pointer back to object which created
330 inline const OsiObject * originalObject() const
331 {return originalObject_;}
332 /// Set pointer back to object which created
333 inline void setOriginalObject(const OsiObject * object)
334 {originalObject_=object;}
335 /** Double checks in case node can change its mind!
336 Returns objective value
337 Can change objective etc */
338 virtual void checkIsCutoff(double ) {}
339 /// For debug
340 int columnNumber() const;
341 /** \brief Print something about branch - only if log level high
342 */
343 virtual void print(const OsiSolverInterface * =nullptr) const {}
344
345protected:
346
347 /// Current value - has some meaning about branch
348 double value_;
349
350 /// Pointer back to object which created
351 const OsiObject * originalObject_;
352
353 /** Number of branches
354 */
355 int numberBranches_;
356
357 /** The state of the branching object. i.e. branch index
358 This starts at 0 when created
359 */
360 short branchIndex_;
361
362};
363/* This contains information
364 This could also contain pseudo shadow prices
365 or information for dealing with computing and trusting pseudo-costs
366*/
367class OsiBranchingInformation {
368
369public:
370
371 /// Default Constructor
372 OsiBranchingInformation ();
373
374 /** Useful Constructor
375 (normalSolver true if has matrix etc etc)
376 copySolution true if constructot should make a copy
377 */
378 OsiBranchingInformation (const OsiSolverInterface * solver, bool normalSolver,bool copySolution=false);
379
380 /// Copy constructor
381 OsiBranchingInformation ( const OsiBranchingInformation &);
382
383 /// Assignment operator
384 OsiBranchingInformation & operator=( const OsiBranchingInformation& rhs);
385
386 /// Clone
387 virtual OsiBranchingInformation * clone() const;
388
389 /// Destructor
390 virtual ~OsiBranchingInformation ();
391
392 // Note public
393public:
394 /// data
395
396 /** State of search
397 0 - no solution
398 1 - only heuristic solutions
399 2 - branched to a solution
400 3 - no solution but many nodes
401 */
402 int stateOfSearch_;
403 /// Value of objective function (in minimization sense)
404 double objectiveValue_;
405 /// Value of objective cutoff (in minimization sense)
406 double cutoff_;
407 /// Direction 1.0 for minimization, -1.0 for maximization
408 double direction_;
409 /// Integer tolerance
410 double integerTolerance_;
411 /// Primal tolerance
412 double primalTolerance_;
413 /// Maximum time remaining before stopping on time
414 double timeRemaining_;
415 /// Dual to use if row bound violated (if negative then pseudoShadowPrices off)
416 double defaultDual_;
417 /// Pointer to solver
418 mutable const OsiSolverInterface * solver_;
419 /// The number of columns
420 int numberColumns_;
421 /// Pointer to current lower bounds on columns
422 mutable const double * lower_;
423 /// Pointer to current solution
424 mutable const double * solution_;
425 /// Pointer to current upper bounds on columns
426 mutable const double * upper_;
427 /// Highly optional target (hot start) solution
428 const double * hotstartSolution_;
429 /// Pointer to duals
430 const double * pi_;
431 /// Pointer to row activity
432 const double * rowActivity_;
433 /// Objective
434 const double * objective_;
435 /// Pointer to current lower bounds on rows
436 const double * rowLower_;
437 /// Pointer to current upper bounds on rows
438 const double * rowUpper_;
439 /// Elements in column copy of matrix
440 const double * elementByColumn_;
441 /// Column starts
442 const CoinBigIndex * columnStart_;
443 /// Column lengths
444 const int * columnLength_;
445 /// Row indices
446 const int * row_;
447 /** Useful region of length CoinMax(numberColumns,2*numberRows)
448 This is allocated and deleted before OsiObject::infeasibility
449 It is zeroed on entry and should be so on exit
450 It only exists if defaultDual_>=0.0
451 */
452 double * usefulRegion_;
453 /// Useful index region to go with usefulRegion_
454 int * indexRegion_;
455 /// Number of solutions found
456 int numberSolutions_;
457 /// Number of branching solutions found (i.e. exclude heuristics)
458 int numberBranchingSolutions_;
459 /// Depth in tree
460 int depth_;
461 /// TEMP
462 bool owningSolution_;
463};
464
465/// This just adds two-wayness to a branching object
466
467class OsiTwoWayBranchingObject : public OsiBranchingObject {
468
469public:
470
471 /// Default constructor
472 OsiTwoWayBranchingObject ();
473
474 /** Create a standard tw0-way branch object
475
476 Specifies a simple two-way branch.
477 Specify way = -1 to set the object state to perform the down arm first,
478 way = 1 for the up arm.
479 */
480 OsiTwoWayBranchingObject (OsiSolverInterface *solver,const OsiObject * originalObject,
481 int way , double value) ;
482
483 /// Copy constructor
484 OsiTwoWayBranchingObject ( const OsiTwoWayBranchingObject &);
485
486 /// Assignment operator
487 OsiTwoWayBranchingObject & operator= (const OsiTwoWayBranchingObject& rhs);
488
489 /// Destructor
490 virtual ~OsiTwoWayBranchingObject ();
491
492 using OsiBranchingObject::branch ;
493 /** \brief Sets the bounds for the variable according to the current arm
494 of the branch and advances the object state to the next arm.
495 state.
496 Returns change in guessed objective on next branch
497 */
498 virtual double branch(OsiSolverInterface * solver)=0;
499
500 inline int firstBranch() const { return firstBranch_; }
501 /// Way returns -1 on down +1 on up
502 inline int way() const
503 { return !branchIndex_ ? firstBranch_ : -firstBranch_;}
504protected:
505 /// Which way was first branch -1 = down, +1 = up
506 int firstBranch_;
507};
508/// Define a single integer class
509
510
511class OsiSimpleInteger : public OsiObject2 {
512
513public:
514
515 /// Default Constructor
516 OsiSimpleInteger ();
517
518 /// Useful constructor - passed solver index
519 OsiSimpleInteger (const OsiSolverInterface * solver, int iColumn);
520
521 /// Useful constructor - passed solver index and original bounds
522 OsiSimpleInteger (int iColumn, double lower, double upper);
523
524 /// Copy constructor
525 OsiSimpleInteger ( const OsiSimpleInteger &);
526
527 /// Clone
528 virtual OsiObject * clone() const override;
529
530 /// Assignment operator
531 OsiSimpleInteger & operator=( const OsiSimpleInteger& rhs);
532
533 /// Destructor
534 virtual ~OsiSimpleInteger ();
535
536 using OsiObject::infeasibility ;
537 /// Infeasibility - large is 0.5
538 virtual double infeasibility(const OsiBranchingInformation * info, int & whichWay) const override;
539
540 using OsiObject::feasibleRegion ;
541 /** Set bounds to fix the variable at the current (integer) value.
542
543 Given an integer value, set the lower and upper bounds to fix the
544 variable. Returns amount it had to move variable.
545 */
546 virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const override;
547
548 /** Creates a branching object
549
550 The preferred direction is set by \p way, 0 for down, 1 for up.
551 */
552 virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const override;
553
554
555 /// Set solver column number
556 inline void setColumnNumber(int value)
557 {columnNumber_=value;}
558
559 /** Column number if single column object -1 otherwise,
560 so returns >= 0
561 Used by heuristics
562 */
563 virtual int columnNumber() const override;
564
565 /// Original bounds
566 inline double originalLowerBound() const
567 { return originalLower_;}
568 inline void setOriginalLowerBound(double value)
569 { originalLower_=value;}
570 inline double originalUpperBound() const
571 { return originalUpper_;}
572 inline void setOriginalUpperBound(double value)
573 { originalUpper_=value;}
574 /** Reset variable bounds to their original values.
575 Bounds may be tightened, so it may be good to be able to reset them to
576 their original values.
577 */
578 virtual void resetBounds(const OsiSolverInterface * solver) override ;
579 /** Change column numbers after preprocessing
580 */
581 virtual void resetSequenceEtc(int numberColumns, const int * originalColumns) override;
582
583 /// Return "up" estimate (default 1.0e-5)
584 virtual double upEstimate() const override;
585 /// Return "down" estimate (default 1.0e-5)
586 virtual double downEstimate() const override;
587 /// Return true if knows how to deal with Pseudo Shadow Prices
588 virtual bool canHandleShadowPrices() const override
589 { return false;}
590protected:
591 /// data
592 /// Original lower bound
593 double originalLower_;
594 /// Original upper bound
595 double originalUpper_;
596 /// Column number in solver
597 int columnNumber_;
598
599};
600/** Simple branching object for an integer variable
601
602 This object can specify a two-way branch on an integer variable. For each
603 arm of the branch, the upper and lower bounds on the variable can be
604 independently specified. 0 -> down, 1-> up.
605*/
606
607class OsiIntegerBranchingObject : public OsiTwoWayBranchingObject {
608
609public:
610
611 /// Default constructor
612 OsiIntegerBranchingObject ();
613
614 /** Create a standard floor/ceiling branch object
615
616 Specifies a simple two-way branch. Let \p value = x*. One arm of the
617 branch will be lb <= x <= floor(x*), the other ceil(x*) <= x <= ub.
618 Specify way = -1 to set the object state to perform the down arm first,
619 way = 1 for the up arm.
620 */
621 OsiIntegerBranchingObject (OsiSolverInterface *solver,const OsiSimpleInteger * originalObject,
622 int way , double value) ;
623 /** Create a standard floor/ceiling branch object
624
625 Specifies a simple two-way branch in a more flexible way. One arm of the
626 branch will be lb <= x <= downUpperBound, the other upLowerBound <= x <= ub.
627 Specify way = -1 to set the object state to perform the down arm first,
628 way = 1 for the up arm.
629 */
630 OsiIntegerBranchingObject (OsiSolverInterface *solver,const OsiSimpleInteger * originalObject,
631 int way , double value, double downUpperBound, double upLowerBound) ;
632
633 /// Copy constructor
634 OsiIntegerBranchingObject ( const OsiIntegerBranchingObject &);
635
636 /// Assignment operator
637 OsiIntegerBranchingObject & operator= (const OsiIntegerBranchingObject& rhs);
638
639 /// Clone
640 virtual OsiBranchingObject * clone() const override;
641
642 /// Destructor
643 virtual ~OsiIntegerBranchingObject ();
644
645 using OsiBranchingObject::branch ;
646 /** \brief Sets the bounds for the variable according to the current arm
647 of the branch and advances the object state to the next arm.
648 state.
649 Returns change in guessed objective on next branch
650 */
651 virtual double branch(OsiSolverInterface * solver) override;
652
653 using OsiBranchingObject::print ;
654 /** \brief Print something about branch - only if log level high
655 */
656 virtual void print(const OsiSolverInterface * solver=nullptr);
657
658protected:
659 // Probably could get away with just value which is already stored
660 /// Lower [0] and upper [1] bounds for the down arm (way_ = -1)
661 double down_[2];
662 /// Lower [0] and upper [1] bounds for the up arm (way_ = 1)
663 double up_[2];
664};
665
666
667/** Define Special Ordered Sets of type 1 and 2. These do not have to be
668 integer - so do not appear in lists of integers.
669
670 which_ points columns of matrix
671*/
672
673
674class OsiSOS : public OsiObject2 {
675
676public:
677
678 // Default Constructor
679 OsiSOS ();
680
681 /** Useful constructor - which are indices
682 and weights are also given. If null then 0,1,2..
683 type is SOS type
684 */
685 OsiSOS (const OsiSolverInterface * solver, int numberMembers,
686 const int * which, const double * weights, int type=1);
687
688 // Copy constructor
689 OsiSOS ( const OsiSOS &);
690
691 /// Clone
692 virtual OsiObject * clone() const override;
693
694 // Assignment operator
695 OsiSOS & operator=( const OsiSOS& rhs);
696
697 // Destructor
698 virtual ~OsiSOS ();
699
700 using OsiObject::infeasibility ;
701 /// Infeasibility - large is 0.5
702 virtual double infeasibility(const OsiBranchingInformation * info,int & whichWay) const override;
703
704 using OsiObject::feasibleRegion ;
705 /** Set bounds to fix the variable at the current (integer) value.
706
707 Given an integer value, set the lower and upper bounds to fix the
708 variable. Returns amount it had to move variable.
709 */
710 virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const override;
711
712 /** Creates a branching object
713
714 The preferred direction is set by \p way, 0 for down, 1 for up.
715 */
716 virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const override;
717 /// Return "up" estimate (default 1.0e-5)
718 virtual double upEstimate() const override;
719 /// Return "down" estimate (default 1.0e-5)
720 virtual double downEstimate() const override;
721
722 /// Redoes data when sequence numbers change
723 virtual void resetSequenceEtc(int numberColumns, const int * originalColumns) override;
724
725 /// Number of members
726 inline int numberMembers() const
727 {return numberMembers_;}
728
729 /// Members (indices in range 0 ... numberColumns-1)
730 inline const int * members() const
731 {return members_;}
732
733 /// SOS type
734 inline int sosType() const
735 {return sosType_;}
736
737 /// SOS type
738 inline int setType() const
739 {return sosType_;}
740
741 /** Array of weights */
742 inline const double * weights() const
743 { return weights_;}
744
745 /** \brief Return true if object can take part in normal heuristics
746 */
747 virtual bool canDoHeuristics() const override
748 {return (sosType_==1&&integerValued_);}
749 /// Set whether set is integer valued or not
750 inline void setIntegerValued(bool yesNo)
751 { integerValued_=yesNo;}
752 /// Return true if knows how to deal with Pseudo Shadow Prices
753 virtual bool canHandleShadowPrices() const override
754 { return true;}
755 /// Set number of members
756 inline void setNumberMembers(int value)
757 {numberMembers_=value;}
758
759 /// Members (indices in range 0 ... numberColumns-1)
760 inline int * mutableMembers() const
761 {return members_;}
762
763 /// Set SOS type
764 inline void setSosType(int value)
765 {sosType_=value;}
766
767 /** Array of weights */
768 inline double * mutableWeights() const
769 { return weights_;}
770protected:
771 /// data
772
773 /// Members (indices in range 0 ... numberColumns-1)
774 int * members_;
775 /// Weights
776 double * weights_;
777
778 /// Number of members
779 int numberMembers_;
780 /// SOS type
781 int sosType_;
782 /// Whether integer valued
783 bool integerValued_;
784};
785
786/** Branching object for Special ordered sets
787
788 */
789class OsiSOSBranchingObject : public OsiTwoWayBranchingObject {
790
791public:
792
793 // Default Constructor
794 OsiSOSBranchingObject ();
795
796 // Useful constructor
797 OsiSOSBranchingObject (OsiSolverInterface * solver, const OsiSOS * originalObject,
798 int way,
799 double separator);
800
801 // Copy constructor
802 OsiSOSBranchingObject ( const OsiSOSBranchingObject &);
803
804 // Assignment operator
805 OsiSOSBranchingObject & operator=( const OsiSOSBranchingObject& rhs);
806
807 /// Clone
808 virtual OsiBranchingObject * clone() const override;
809
810 // Destructor
811 virtual ~OsiSOSBranchingObject ();
812
813 using OsiBranchingObject::branch ;
814 /// Does next branch and updates state
815 virtual double branch(OsiSolverInterface * solver) override;
816
817 using OsiBranchingObject::print ;
818 /** \brief Print something about branch - only if log level high
819 */
820 virtual void print(const OsiSolverInterface * solver=nullptr);
821private:
822 /// data
823};
824/** Lotsize class */
825
826
827class OsiLotsize : public OsiObject2 {
828
829public:
830
831 // Default Constructor
832 OsiLotsize ();
833
834 /* Useful constructor - passed model index.
835 Also passed valid values - if range then pairs
836 */
837 OsiLotsize (const OsiSolverInterface * solver, int iColumn,
838 int numberPoints, const double * points, bool range=false);
839
840 // Copy constructor
841 OsiLotsize ( const OsiLotsize &);
842
843 /// Clone
844 virtual OsiObject * clone() const override;
845
846 // Assignment operator
847 OsiLotsize & operator=( const OsiLotsize& rhs);
848
849 // Destructor
850 ~OsiLotsize ();
851
852 using OsiObject::infeasibility ;
853 /// Infeasibility - large is 0.5
854 virtual double infeasibility(const OsiBranchingInformation * info, int & whichWay) const override;
855
856 using OsiObject::feasibleRegion ;
857 /** Set bounds to contain the current solution.
858
859 More precisely, for the variable associated with this object, take the
860 value given in the current solution, force it within the current bounds
861 if required, then set the bounds to fix the variable at the integer
862 nearest the solution value. Returns amount it had to move variable.
863 */
864 virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const override;
865
866 /** Creates a branching object
867
868 The preferred direction is set by \p way, 0 for down, 1 for up.
869 */
870 virtual OsiBranchingObject * createBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const override;
871
872
873 /// Set solver column number
874 inline void setColumnNumber(int value)
875 {columnNumber_=value;}
876
877 /** Column number if single column object -1 otherwise,
878 so returns >= 0
879 Used by heuristics
880 */
881 virtual int columnNumber() const override;
882 /** Reset original upper and lower bound values from the solver.
883
884 Handy for updating bounds held in this object after bounds held in the
885 solver have been tightened.
886 */
887 virtual void resetBounds(const OsiSolverInterface * solver) override;
888
889 /** Finds range of interest so value is feasible in range range_ or infeasible
890 between hi[range_] and lo[range_+1]. Returns true if feasible.
891 */
892 bool findRange(double value, double integerTolerance) const;
893
894 /** Returns floor and ceiling
895 */
896 virtual void floorCeiling(double & floorLotsize, double & ceilingLotsize, double value,
897 double tolerance) const;
898
899 /// Original bounds
900 inline double originalLowerBound() const
901 { return bound_[0];}
902 inline double originalUpperBound() const
903 { return bound_[rangeType_*numberRanges_-1];}
904 /// Type - 1 points, 2 ranges
905 inline int rangeType() const
906 { return rangeType_;}
907 /// Number of points
908 inline int numberRanges() const
909 { return numberRanges_;}
910 /// Ranges
911 inline double * bound() const
912 { return bound_;}
913 /** Change column numbers after preprocessing
914 */
915 virtual void resetSequenceEtc(int numberColumns, const int * originalColumns) override;
916
917 /// Return "up" estimate (default 1.0e-5)
918 virtual double upEstimate() const override;
919 /// Return "down" estimate (default 1.0e-5)
920 virtual double downEstimate() const override;
921 /// Return true if knows how to deal with Pseudo Shadow Prices
922 virtual bool canHandleShadowPrices() const override
923 { return true;}
924 /** \brief Return true if object can take part in normal heuristics
925 */
926 virtual bool canDoHeuristics() const override
927 {return false;}
928
929private:
930 /// data
931
932 /// Column number in model
933 int columnNumber_;
934 /// Type - 1 points, 2 ranges
935 int rangeType_;
936 /// Number of points
937 int numberRanges_;
938 // largest gap
939 double largestGap_;
940 /// Ranges
941 double * bound_;
942 /// Current range
943 mutable int range_;
944};
945
946
947/** Lotsize branching object
948
949 This object can specify a two-way branch on an integer variable. For each
950 arm of the branch, the upper and lower bounds on the variable can be
951 independently specified.
952
953 Variable_ holds the index of the integer variable in the integerVariable_
954 array of the model.
955*/
956
957class OsiLotsizeBranchingObject : public OsiTwoWayBranchingObject {
958
959public:
960
961 /// Default constructor
962 OsiLotsizeBranchingObject ();
963
964 /** Create a lotsize floor/ceiling branch object
965
966 Specifies a simple two-way branch. Let \p value = x*. One arm of the
967 branch will be is lb <= x <= valid range below(x*), the other valid range above(x*) <= x <= ub.
968 Specify way = -1 to set the object state to perform the down arm first,
969 way = 1 for the up arm.
970 */
971 OsiLotsizeBranchingObject (OsiSolverInterface *solver,const OsiLotsize * originalObject,
972 int way , double value) ;
973
974 /// Copy constructor
975 OsiLotsizeBranchingObject ( const OsiLotsizeBranchingObject &);
976
977 /// Assignment operator
978 OsiLotsizeBranchingObject & operator= (const OsiLotsizeBranchingObject& rhs);
979
980 /// Clone
981 virtual OsiBranchingObject * clone() const override;
982
983 /// Destructor
984 virtual ~OsiLotsizeBranchingObject ();
985
986 using OsiBranchingObject::branch ;
987 /** \brief Sets the bounds for the variable according to the current arm
988 of the branch and advances the object state to the next arm.
989 state.
990 Returns change in guessed objective on next branch
991 */
992 virtual double branch(OsiSolverInterface * solver) override;
993
994 using OsiBranchingObject::print ;
995 /** \brief Print something about branch - only if log level high
996 */
997 virtual void print(const OsiSolverInterface * solver=nullptr);
998
999protected:
1000 /// Lower [0] and upper [1] bounds for the down arm (way_ = -1)
1001 double down_[2];
1002 /// Lower [0] and upper [1] bounds for the up arm (way_ = 1)
1003 double up_[2];
1004};
1005#endif
1006