summaryrefslogtreecommitdiff
path: root/thirdparty/linux/include/coin/BonOaDecBase.hpp
blob: 61156f70ecb61271dbfd227291cd0b19c31c789a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
// (C) Copyright International Business Machines (IBM) 2006
// All Rights Reserved.
// This code is published under the Eclipse Public License.
//
// Authors :
// P. Bonami, International Business Machines
//
// Date :  12/07/2006
#ifndef BonOaDecBase_HPP
#define BonOaDecBase_HPP
#include "BonSubMipSolver.hpp"
#include "CglCutGenerator.hpp"
#include "BonBabSetupBase.hpp"
#include "BonOAMessages.hpp"
#include "CbcModel.hpp"

#include "CbcStrategy.hpp"

#include "CoinTime.hpp"
#include "OsiAuxInfo.hpp"
#include "OsiBranchingObject.hpp"
#include <iostream>
#include "BonBabInfos.hpp"
namespace Bonmin
{
  /** Base class for OA algorithms.*/
  class OaDecompositionBase : public CglCutGenerator
  {
  public:


    /** Small class to manipulatee various things in an OsiSolverInterface and restore them.
        The OsiSolverInterface manipulated may already exist or may be cloned from another one.*/
    class solverManip
    {
    public:
      /** Constructor. */
      solverManip(OsiSolverInterface *si , bool saveNumRows=true,
          bool saveBasis=true, bool saveBounds=false,
          bool saveCutoff = false, bool resolve=true);

      /** Constructor which clone an other interface. */
      solverManip(const OsiSolverInterface & si);
      /** Destructor. */
      ~solverManip();
      /** Restore solver. */
      void restore();
      
      /** Get pointer to solver interface. */
      OsiSolverInterface * si()
      {
        return si_;
      }

      /** Set objects.*/
      void setObjects(OsiObject ** objects, int nObjects)
      {
        objects_ = objects;
        nObjects_ = nObjects;
      }

    private:
      /** Interface saved. */
      OsiSolverInterface * si_;
      /** Initial number of rows (-1 if don't save). */
      int initialNumberRows_;

      /** Initial lower bounds. */
      double * colLower_;

      /** Initial Upper bounds.*/
      double * colUpper_;

      /** Inital basis. */
      CoinWarmStart * warm_;

      /** Initial cutoff. */
      double cutoff_;

      /** delete si_ ? */
      bool deleteSolver_;

      /// Some objects the feasiblitiy of which to verify.
      OsiObject * * objects_;
      /// Number of objects.*/
      int nObjects_;
      /** \name Cached info from solver interface.*/
      /** @{ */
      /** Number of columns. */
      int numcols_;
      /** Number of rows. */
      int numrows_;
      /** Lower bounds on variables.*/
      const double * siColLower_;
      /** Upper bounds on variables. */
      const double * siColUpper_;

      void getCached();
      /** @} */
    };

    /// New usefull constructor
    OaDecompositionBase(BabSetupBase &b, bool leaveSiUnchanged,
        bool reassignLpsolver);

    /// Copy constructor
    OaDecompositionBase(const OaDecompositionBase & copy);


    /// Destructor
    virtual ~OaDecompositionBase();

    /** Standard cut generation methods. */
    virtual void generateCuts(const OsiSolverInterface &si,  OsiCuts & cs,
        const CglTreeInfo info = CglTreeInfo());

    /// Assign an OsiTMINLPInterface
    void assignNlpInterface(OsiTMINLPInterface * nlp)
    {
      nlp_ = nlp;
    }

    /// Assign an OsiTMINLPInterface
    void assignLpInterface(OsiSolverInterface * si)
    {
      lp_ = si;
    }

    bool reassignLpsolver()
    {
      return reassignLpsolver_;
    }
    /** Set objects.*/
    void setObjects(OsiObject ** objects, int nObjects)
    {
      objects_ = objects;
      nObjects_ = nObjects;
    }
    /// Set whether to leave the solverinterface unchanged
    inline void setLeaveSiUnchanged(bool yesno)
    {
      leaveSiUnchanged_ = yesno;
    }

    /** Parameters for algorithm. */
    struct Parameters
    {
      /// Add cuts as global
      bool global_;
      /// Add only violated OA inequalities
      bool addOnlyViolated_;
      /// cutoff min increase (has to be intialized trhough Cbc)
      double cbcCutoffIncrement_;
      /// integer tolerance (has to be the same as Cbc's)
      double cbcIntegerTolerance_; 
      /** setting for gap tolerance.*/
      double gap_tol_;
      ///Total max number of local searches
      int maxLocalSearch_;
      /// maximum time for local searches
      double maxLocalSearchTime_;
      /** sub milp log level.*/
      int subMilpLogLevel_;
      /** maximum number of solutions*/
      int maxSols_;
      /** Frequency of log. */
      double logFrequency_;
     
      
      /** Constructor with default values */
      Parameters();

      /** Copy constructor */
      Parameters(const Parameters & other);

      /** Destructor */
      ~Parameters()
      {
        if (strategy_) delete strategy_;
      }

      /** Strategy to apply when using Cbc as MILP sub-solver.*/
      void setStrategy(const CbcStrategy & strategy)
      {
        if (strategy_) delete strategy_;
        strategy_ = strategy.clone();
      }

      const CbcStrategy * strategy() const
      {
        return strategy_;
      }

private:
      /** Strategy to apply when using Cbc as MILP sub-solver.*/
      CbcStrategy * strategy_;

    };

    Parameters& parameter()
    {
      return parameters_;
    }

    const Parameters& parameter()const
    {
      return parameters_;
    }

    void setLogLevel(int level)
    {
      handler_->setLogLevel(level);
    }

    void setReassignLpSolver(bool v){
      reassignLpsolver_ = v;
    }
    void passInMessageHandler(CoinMessageHandler * handler);
  protected:
      void setupMipSolver(BabSetupBase &b, const std::string &prefix);
    /// \name Protected helper functions
    /**@{ */

    /** Solve the nlp and do output.
        \return true if feasible*/
    bool post_nlp_solve(BabInfo * babInfo, double cutoff) const;
    /** @} */

    /// virtual method which performs the OA algorithm by modifying lp and nlp.
    virtual double performOa(OsiCuts &cs, solverManip &lpManip,
                             BabInfo * babInfo, double &, const CglTreeInfo & info) const = 0;
    /// virutal method to decide if local search is performed
    virtual bool doLocalSearch(BabInfo * babInfo) const = 0;

    /// \name Protected members
    /** @{ */
    /// Pointer to nlp interface
    mutable OsiTMINLPInterface * nlp_;
    /// Pointer to setup
    BabSetupBase * s_;
    ///Number of nlp solved done
    mutable int nSolve_;
    /// A linear solver
    mutable OsiSolverInterface * lp_;
    /// Some objects the feasiblitiy of which to verify.
    OsiObject * * objects_;
    /// Number of objects.*/
    int nObjects_;
    ///number of local searches performed
    mutable int nLocalSearch_;
    /** messages handler. */
    CoinMessageHandler * handler_;
    /** Messages for OA */
    CoinMessages messages_;
    /** Wether or not we should remove cuts at the end of the procedure */
    bool leaveSiUnchanged_;
    /** Do we need to reassign the lp solver with Cbc.*/
    bool reassignLpsolver_;
    /** time of construction*/
    double timeBegin_;
    /** number of solutions found by OA_decomposition.*/
    mutable int numSols_;
    
    /** Parameters.*/
    Parameters parameters_;

      /** Saved cuts: in some cases when using OA to check feasible solution algorithm may loop because Cbc removes inactive cuts.
          To overcome this we can impose that no OA cut can be discarded by Cbc but this consumes too much memory in some cases.
          Here we do it another way: cuts generated at current node are saved if algorithm seems to enter a loop we impose the needed cuts to be kept.*/
    mutable OsiCuts savedCuts_;
      /** Store the current node number.*/
    mutable int currentNodeNumber_;
    /** @} */

#ifdef OA_DEBUG
    class OaDebug
    {
      public:
      bool checkInteger(const OsiSolverInterface&nlp, std::ostream & os) const;

      void printEndOfProcedureDebugMessage(const OsiCuts &cs,
          bool foundSolution,
          double solValue,
          double milpBound,
          bool isInteger,
          bool feasible,
          std::ostream & os) const;
    };

    /** debug object. */
    OaDebug debug_;

#endif
  };
}
#endif