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
|
// (C) Copyright International Business Machines Corporation 2007
// All Rights Reserved.
// This code is published under the Eclipse Public License.
//
// Authors :
// Pierre Bonami, International Business Machines Corporation
//
// Date : 10/16/2007
#ifndef BonminTMINLP2OsiLP_H
#define BonminTMINLP2OsiLP_H
#include <cmath>
#include <cstdio>
#include "IpSmartPtr.hpp"
#include "IpTNLP.hpp"
#include "BonTypes.hpp"
class OsiSolverInterface;
class OsiCuts;
namespace Bonmin {
class TMINLP2TNLP;
class BabSetupBase;
/** A transformer class to build outer approximations i.e. transfomrs nonlinear programs into linear programs.*/
class TMINLP2OsiLP: public Ipopt::ReferencedObject {
public:
/** Default constructor.*/
TMINLP2OsiLP():
tiny_(-0.),
very_tiny_(-0.)
{}
/** Copy constructor.*/
TMINLP2OsiLP(const TMINLP2OsiLP & other):
tiny_(other.tiny_),
very_tiny_(other.very_tiny_),
model_(other.model_){
}
/** virtual copy constructor*/
virtual TMINLP2OsiLP * clone() const = 0;
void set_tols(double tiny, double very_tiny, double rhs_relax, double infty){
tiny_ = tiny;
very_tiny_ = very_tiny;
rhs_relax_ = rhs_relax;
infty_ = infty;
}
void set_model(Bonmin::TMINLP2TNLP * model){
model_ = model;
initialize_jac_storage();
}
/** Assignment operator.*/
TMINLP2OsiLP & operator=(const TMINLP2OsiLP& rhs){
if(this != & rhs){
tiny_ = rhs.tiny_;
very_tiny_ = rhs.very_tiny_;
model_ = rhs.model_;
}
return (*this);
}
/** Destructor.*/
~TMINLP2OsiLP(){}
/** Build the Outer approximation of model_ in x and put it in si.*/
virtual void extract(OsiSolverInterface *si,
const double * x, bool getObj) = 0;
/** Get OAs of nonlinear constraints in x.*/
virtual void get_refined_oa(OsiCuts & cs
) const = 0;
/** Get OAs of nonlinear constraints in x.*/
virtual void get_oas(OsiCuts & cs,
const double * x, bool getObj, bool global) const = 0;
protected:
/** Facilitator to clean up coefficient.*/
inline bool cleanNnz(double &value, double colLower, double colUpper,
double rowLower, double rowUpper, double colsol,
double & lb, double &ub, double tiny, double veryTiny) const;
/** If constraint coefficient is below this, we try to remove it.*/
double tiny_;
/** If constraint coefficient is below this, we neglect it.*/
double very_tiny_;
/** Amount by which to relax OA constraints RHSes*/
double rhs_relax_;
/** infinity.*/
double infty_;
/** Count the number of linear outer approximations taken.*/
static int nTimesCalled;
/** Cache Jacobian matrix*/
/** Columns of jacobian.*/
mutable vector<int> jCol_;
/** Rows of jacobian.*/
mutable vector<int> iRow_;
/** Values of jacobian.*/
mutable vector<double> value_;
vector<Ipopt::TNLP::LinearityType> const_types_;
void initialize_jac_storage();
Ipopt::SmartPtr<Bonmin::TMINLP2TNLP> model_;
};
//A procedure to try to remove small coefficients in OA cuts (or make it non small
inline
bool
TMINLP2OsiLP::cleanNnz(double &value, double colLower, double colUpper,
double rowLower, double rowUpper, double colsol,
double & lb, double &ub, double tiny, double veryTiny) const
{
if(fabs(value)>= tiny) return 1;
//fprintf(stderr, "Warning: small coefficient %g\n", tiny);
if(fabs(value)<veryTiny) return 0;//Take the risk?
//try and remove
double infty = 1e20;
bool colUpBounded = colUpper < 10000;
bool colLoBounded = colLower > -10000;
bool rowNotLoBounded = rowLower <= - infty;
bool rowNotUpBounded = rowUpper >= infty;
bool pos = value > 0;
if(colLoBounded && !pos && rowNotUpBounded) {
lb += value * (colsol - colLower);
return 0;
}
else
if(colLoBounded && pos && rowNotLoBounded) {
ub += value * (colsol - colLower);
return 0;
}
else
if(colUpBounded && pos && rowNotUpBounded) {
lb += value * (colsol - colUpper);
return 0;
}
else
if(colUpBounded && !pos && rowNotLoBounded) {
ub += value * (colsol - colUpper);
return 0;
}
//can not remove coefficient
return 1;
}
}
#endif
|