summaryrefslogtreecommitdiff
path: root/build/Bonmin/include/coin/BonTMINLP.hpp
blob: b6d21e13e2902bd354be454c20de5ee9bbb09382 (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
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
// (C) Copyright International Business Machines Corporation and
// Carnegie Mellon University 2004, 2007
//
// All Rights Reserved.
// This code is published under the Eclipse Public License.
//
// Authors :
// Pierre Bonami, Carnegie Mellon University,
// Carl D. Laird, Carnegie Mellon University,
// Andreas Waechter, International Business Machines Corporation
//
// Date : 12/01/2004

#ifndef __TMINLP_HPP__
#define __TMINLP_HPP__

#include "IpUtils.hpp"
#include "IpReferenced.hpp"
#include "IpException.hpp"
#include "IpAlgTypes.hpp"
#include "CoinPackedMatrix.hpp"
#include "OsiCuts.hpp"
#include "IpTNLP.hpp"
#include "CoinError.hpp"
#include "CoinHelperFunctions.hpp"

namespace Bonmin
{
  DECLARE_STD_EXCEPTION(TMINLP_INVALID);
  DECLARE_STD_EXCEPTION(TMINLP_INVALID_VARIABLE_BOUNDS);

  /** Base class for all MINLPs that use a standard triplet matrix form
   *  and dense vectors.
   *  The class TMINLP2TNLP allows the caller to produce a viable TNLP
   *  from the MINLP (by relaxing binary and/or integers, or by
   *  fixing them), which can then be solved by Ipopt.
   *
   *  This interface presents the problem form:
   *  \f[
   *  \begin{array}{rl}
   *     &min f(x)\\
   *
   *     \mbox{s.t.}&\\
   *      &   g^L <= g(x) <= g^U\\
   *
   *       &   x^L <=  x   <= x^U\\
   *   \end{array}
   *  \f]
   *  Where each x_i is either a continuous, binary, or integer variable.
   *  If x_i is binary, the bounds [xL,xU] are assumed to be [0,1].
   *  In order to specify an equality constraint, set gL_i = gU_i =
   *  rhs.  The value that indicates "infinity" for the bounds
   *  (i.e. the variable or constraint has no lower bound (-infinity)
   *  or upper bound (+infinity)) is set through the option
   *  nlp_lower_bound_inf and nlp_upper_bound_inf.  To indicate that a
   *  variable has no upper or lower bound, set the bound to
   *  -ipopt_inf or +ipopt_inf respectively
   */
  class TMINLP : public Ipopt::ReferencedObject
  {
  public:
    friend class TMINLP2TNLP;
    /** Return statuses of algorithm.*/
    enum SolverReturn{
      SUCCESS,
      INFEASIBLE,
      CONTINUOUS_UNBOUNDED,
      LIMIT_EXCEEDED,
      USER_INTERRUPT,
      MINLP_ERROR};
    /** Class to store sos constraints for model */
    struct SosInfo
    {
      /** Number of SOS constraints.*/
      int num;
      /** Type of sos. At present Only type '1' SOS are supported by Cbc*/
      char * types;
      /** priorities of sos constraints.*/
      int * priorities;
      
      /** \name Sparse storage of the elements of the SOS constraints.*/
      /** @{ */
      /** Total number of non zeroes in SOS constraints.*/
      int numNz;
      /** For 0 <= i < nums, start[i] gives the indice of indices and weights arrays at which the description of constraints i begins..*/ 
      int * starts;
      /** indices of elements belonging to the SOS.*/
      int * indices;
      /** weights of the elements of the SOS.*/
      double * weights;
      /** @} */
      /** default constructor. */
      SosInfo();
      /** Copy constructor.*/
      SosInfo(const SosInfo & source);
      

      /** destructor*/
      ~SosInfo()
      {
        gutsOfDestructor();
      }


      /** Reset information */
      void gutsOfDestructor();

    };

    /** Stores branching priorities information. */
    struct BranchingInfo
    {
      /**number of variables*/
      int size;
      /** User set priorities on variables. */
      int * priorities;
      /** User set preferered branching direction. */
      int * branchingDirections;
      /** User set up pseudo costs.*/
      double * upPsCosts;
      /** User set down pseudo costs.*/
      double * downPsCosts;
      BranchingInfo():
      size(0),
      priorities(NULL),
      branchingDirections(NULL),
      upPsCosts(NULL),
      downPsCosts(NULL)
      {}
      BranchingInfo(const BranchingInfo &other)
      {
        gutsOfDestructor();
        size = other.size;
        priorities = CoinCopyOfArray(other.priorities, size);
        branchingDirections = CoinCopyOfArray(other.branchingDirections, size);
        upPsCosts = CoinCopyOfArray(other.upPsCosts, size);
        downPsCosts = CoinCopyOfArray(other.downPsCosts, size);
      }
      void gutsOfDestructor()
      {
      if (priorities != NULL) delete [] priorities;
      priorities = NULL;
      if (branchingDirections != NULL) delete [] branchingDirections;  
      branchingDirections = NULL;
      if (upPsCosts != NULL) delete [] upPsCosts;
      upPsCosts = NULL;
      if (downPsCosts != NULL) delete [] downPsCosts;
      downPsCosts = NULL;
      }
      ~BranchingInfo()
      {
	gutsOfDestructor();
      }
    };

    /** Class to store perturbation radii for variables in the model */
    class PerturbInfo
    {
    public:
      /** default constructor. */
      PerturbInfo() :
	perturb_radius_(NULL)
      {}

      /** destructor*/
      ~PerturbInfo()
      {
        delete [] perturb_radius_;
      }

      /** Method for setting the perturbation radii. */
      void SetPerturbationArray(Ipopt::Index numvars, const double* perturb_radius);

      /** Method for getting the array for the perturbation radii in
       *  order to use the values. */
      const double* GetPerturbationArray() const {
	return perturb_radius_;
      }

    private:
      /** Copy constructor.*/
      PerturbInfo(const PerturbInfo & source);

      /** Perturbation radii for all variables.  A negative value
       *  means that the radius has not been given. If the pointer is
       *  NULL, then no variables have been assigned a perturbation
       *  radius. */
      double* perturb_radius_;
    };

    /** Type of the variables.*/
    enum VariableType
    {
      CONTINUOUS,
      BINARY,
      INTEGER
    };

    /**@name Constructors/Destructors */
    //@{
    TMINLP();

    /** Default destructor */
    virtual ~TMINLP();
    //@}

    /**@name methods to gather information about the MINLP */
    //@{
    /** overload this method to return the number of variables
     *  and constraints, and the number of non-zeros in the jacobian and
     *  the hessian. */
    virtual bool get_nlp_info(Ipopt::Index& n, Ipopt::Index& m, Ipopt::Index& nnz_jac_g,
        Ipopt::Index& nnz_h_lag, Ipopt::TNLP::IndexStyleEnum& index_style)=0;

    /** overload this method to return scaling parameters. This is
     *  only called if the options are set to retrieve user scaling.
     *  There, use_x_scaling (or use_g_scaling) should get set to true
     *  only if the variables (or constraints) are to be scaled.  This
     *  method should return true only if the scaling parameters could
     *  be provided.
     */
    virtual bool get_scaling_parameters(Ipopt::Number& obj_scaling,
                                        bool& use_x_scaling, Ipopt::Index n,
                                        Ipopt::Number* x_scaling,
                                        bool& use_g_scaling, Ipopt::Index m,
                                        Ipopt::Number* g_scaling)
    {
      return false;
    }


    /** overload this method to provide the variables types. The var_types
     *  array will be allocated with length n. */
    virtual bool get_variables_types(Ipopt::Index n, VariableType* var_types)=0;

    /** overload this method to provide the variables linearity.
     * array should be allocated with length at least n.*/
    virtual bool get_variables_linearity(Ipopt::Index n, 
					   Ipopt::TNLP::LinearityType* var_types) = 0;

    /** overload this method to provide the constraint linearity.
     * array should be allocated with length at least m.*/
    virtual bool get_constraints_linearity(Ipopt::Index m, 
					   Ipopt::TNLP::LinearityType* const_types) = 0;

    /** overload this method to return the information about the bound
     *  on the variables and constraints. The value that indicates
     *  that a bound does not exist is specified in the parameters
     *  nlp_lower_bound_inf and nlp_upper_bound_inf.  By default,
     *  nlp_lower_bound_inf is -1e19 and nlp_upper_bound_inf is
     *  1e19.
     *  An exception will be thrown if x_l and x_u are not 0,1 for binary variables
     */
    virtual bool get_bounds_info(Ipopt::Index n, Ipopt::Number* x_l, Ipopt::Number* x_u,
        Ipopt::Index m, Ipopt::Number* g_l, Ipopt::Number* g_u)=0;

    /** overload this method to return the starting point. The bools
     *  init_x and init_lambda are both inputs and outputs. As inputs,
     *  they indicate whether or not the algorithm wants you to
     *  initialize x and lambda respectively. If, for some reason, the
     *  algorithm wants you to initialize these and you cannot, set
     *  the respective bool to false.
     */
    virtual bool get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number* x,
                                    bool init_z, Ipopt::Number* z_L, Ipopt::Number* z_U,
        Ipopt::Index m, bool init_lambda,
        Ipopt::Number* lambda)=0;

    /** overload this method to return the value of the objective function */
    virtual bool eval_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
        Ipopt::Number& obj_value)=0;

    /** overload this method to return the vector of the gradient of
     *  the objective w.r.t. x */
    virtual bool eval_grad_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
        Ipopt::Number* grad_f)=0;

    /** overload this method to return the vector of constraint values */
    virtual bool eval_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
        Ipopt::Index m, Ipopt::Number* g)=0;

    /** overload this method to return the jacobian of the
     *  constraints. The vectors iRow and jCol only need to be set
     *  once. The first call is used to set the structure only (iRow
     *  and jCol will be non-NULL, and values will be NULL) For
     *  subsequent calls, iRow and jCol will be NULL. */
    virtual bool eval_jac_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
        Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index* iRow,
        Ipopt::Index *jCol, Ipopt::Number* values)=0;

    /** overload this method to return the hessian of the
     *  lagrangian. The vectors iRow and jCol only need to be set once
     *  (during the first call). The first call is used to set the
     *  structure only (iRow and jCol will be non-NULL, and values
     *  will be NULL) For subsequent calls, iRow and jCol will be
     *  NULL. This matrix is symmetric - specify the lower diagonal
     *  only */
    virtual bool eval_h(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
        Ipopt::Number obj_factor, Ipopt::Index m, const Ipopt::Number* lambda,
        bool new_lambda, Ipopt::Index nele_hess,
        Ipopt::Index* iRow, Ipopt::Index* jCol, Ipopt::Number* values)=0;
    /** Compute the value of a single constraint. The constraint
     *  number is i (starting counting from 0. */
    virtual bool eval_gi(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
			 Ipopt::Index i, Ipopt::Number& gi)
    {
      std::cerr << "Method eval_gi not overloaded from TMINLP\n";
      throw -1;
    }
    /** Compute the structure or values of the gradient for one
     *  constraint. The constraint * number is i (starting counting
     *  from 0.  Other things are like with eval_jac_g. */
    virtual bool eval_grad_gi(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
			      Ipopt::Index i, Ipopt::Index& nele_grad_gi, Ipopt::Index* jCol,
			      Ipopt::Number* values)
    {
      std::cerr << "Method eval_grad_gi not overloaded from TMINLP\n";
      throw -1;
    }
    //@}

    /** @name Solution Methods */
    //@{
    /** This method is called when the algorithm is complete so the TNLP can store/write the solution */
    virtual void finalize_solution(TMINLP::SolverReturn status,
                                   Ipopt::Index n, const Ipopt::Number* x, Ipopt::Number obj_value) =0;
    //@}
    
    virtual const BranchingInfo * branchingInfo() const = 0;

    virtual const SosInfo * sosConstraints() const = 0;

    virtual const PerturbInfo* perturbInfo() const
    {
      return NULL;
    }

    /** Say if has a specific function to compute upper bounds*/
    virtual bool hasUpperBoundingObjective(){
      return false;}
    
    /** overload this method to return the value of an alternative objective function for
      upper bounding (to use it hasUpperBoundingObjective should return true).*/
    virtual bool eval_upper_bound_f(Ipopt::Index n, const Ipopt::Number* x,
                                    Ipopt::Number& obj_value){ return false; }

   /** Used to mark constraints of the problem.*/
   enum Convexity {
     Convex/** Constraint is convex.*/,
     NonConvex/** Constraint is non-convex.*/,
     SimpleConcave/** Constraint is concave of the simple form y >= F(x).*/};

   /** Structure for marked non-convex constraints. With possibility of
       storing index of a constraint relaxing the non-convex constraint*/
   struct MarkedNonConvex {
      /** Default constructor gives "safe" values.*/
	 MarkedNonConvex():
	 cIdx(-1), cRelaxIdx(-1){}
	 /** Index of the nonconvex constraint.*/
      int cIdx;
	 /** Index of constraint relaxing the nonconvex constraint.*/
	 int cRelaxIdx;};
   /** Structure which describes a constraints of the form
       $f[ y \gt F(x) \f]
	  with \f$ F(x) \f$ a concave function.*/
   struct SimpleConcaveConstraint{
      /** Default constructor gives "safe" values.*/
	 SimpleConcaveConstraint():
	   xIdx(-1), yIdx(-1), cIdx(-1){}
      /** Index of the variable x.*/
      int xIdx;
      /** Index of the variable y.*/
	 int yIdx;
      /** Index of the constraint.*/
	 int cIdx;};
    /** Get accest to constraint convexities.*/
    virtual bool get_constraint_convexities(int m, TMINLP::Convexity * constraints_convexities)const {
      CoinFillN(constraints_convexities, m, TMINLP::Convex);
      return true;}
  /** Get dimension information on nonconvex constraints.*/
  virtual bool get_number_nonconvex(int & number_non_conv, int & number_concave) const{
    number_non_conv = 0;
    number_concave = 0;
    return true;} 
  /** Get array describing the constraints marked nonconvex in the model.*/
  virtual bool get_constraint_convexities(int number_non_conv, MarkedNonConvex * non_convs) const{
    assert(number_non_conv == 0);
    return true;}
  /** Fill array containing indices of simple concave constraints.*/ 
  virtual bool get_simple_concave_constraints(int number_concave, SimpleConcaveConstraint * simple_concave) const{
    assert(number_concave == 0);
    return true;}

  /** Say if problem has a linear objective (for OA) */
  virtual bool hasLinearObjective(){return false;}

  /** Say if problem has general integer variables.*/
  bool hasGeneralInteger();

  /** Access array describing constraint to which perspectives should be applied.*/
  virtual const int * get_const_xtra_id() const{
    return NULL;
  }
  protected:
    /** Copy constructor */
    //@{
    /** Copy Constructor */
    TMINLP(const TMINLP&);

    /** Overloaded Equals Operator */
    void operator=(const TMINLP&);
    //@}

  private:
  };

} // namespace Ipopt

#endif