forked from metab0t/PyOptInterface
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgurobi_model.hpp
More file actions
384 lines (328 loc) · 14.3 KB
/
Copy pathgurobi_model.hpp
File metadata and controls
384 lines (328 loc) · 14.3 KB
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
#pragma once
#include <memory>
#include "solvers/gurobi/gurobi_c.h"
#include "pyoptinterface/core.hpp"
#include "pyoptinterface/container.hpp"
#include "pyoptinterface/nlexpr.hpp"
#define USE_NLMIXIN
#include "pyoptinterface/solver_common.hpp"
#include "pyoptinterface/dylib.hpp"
#include "pyoptinterface/oneshot_model.hpp"
// define Gurobi C APIs
#define APILIST \
B(GRBnewmodel); \
B(GRBfreemodel); \
B(GRBreset); \
B(GRBgetenv); \
B(GRBwrite); \
B(GRBaddvar); \
B(GRBaddvars); \
B(GRBdelvars); \
B(GRBaddconstr); \
B(GRBaddconstrs); \
B(GRBaddqconstr); \
B(GRBaddsos); \
B(GRBaddgenconstrNL); \
B(GRBdelconstrs); \
B(GRBdelqconstrs); \
B(GRBdelsos); \
B(GRBdelgenconstrs); \
B(GRBdelq); \
B(GRBsetdblattrarray); \
B(GRBaddqpterms); \
B(GRBoptimize); \
B(GRBupdatemodel); \
B(GRBgetparamtype); \
B(GRBsetintparam); \
B(GRBsetdblparam); \
B(GRBsetstrparam); \
B(GRBgetintparam); \
B(GRBgetdblparam); \
B(GRBgetstrparam); \
B(GRBgetattrinfo); \
B(GRBsetintattr); \
B(GRBsetdblattr); \
B(GRBsetstrattr); \
B(GRBgetintattr); \
B(GRBgetdblattr); \
B(GRBgetstrattr); \
B(GRBgetdblattrarray); \
B(GRBgetdblattrlist); \
B(GRBsetdblattrlist); \
B(GRBsetintattrelement); \
B(GRBsetcharattrelement); \
B(GRBsetdblattrelement); \
B(GRBsetstrattrelement); \
B(GRBgetintattrelement); \
B(GRBgetcharattrelement); \
B(GRBgetdblattrelement); \
B(GRBgetstrattrelement); \
B(GRBgetcoeff); \
B(GRBchgcoeffs); \
B(GRBgeterrormsg); \
B(GRBversion); \
B(GRBsetcallbackfunc); \
B(GRBcbget); \
B(GRBcbproceed); \
B(GRBterminate); \
B(GRBcbsolution); \
B(GRBcblazy); \
B(GRBcbcut); \
B(GRBemptyenv); \
B(GRBloadenv); \
B(GRBfreeenv); \
B(GRBstartenv); \
B(GRBsetlogcallbackfunc); \
B(GRBconverttofixed); \
B(GRBcomputeIIS);
namespace gurobi
{
#define B DYLIB_EXTERN_DECLARE
APILIST
#undef B
bool is_library_loaded();
bool load_library(const std::string &path);
} // namespace gurobi
class GurobiEnv
{
public:
GurobiEnv(bool empty = false);
~GurobiEnv();
// parameter
int raw_parameter_type(const char *param_name);
void set_raw_parameter_int(const char *param_name, int value);
void set_raw_parameter_double(const char *param_name, double value);
void set_raw_parameter_string(const char *param_name, const char *value);
void start();
void close();
void check_error(int error);
GRBenv *m_env = nullptr;
};
struct GRBfreemodelT
{
void operator()(GRBmodel *model) const
{
gurobi::GRBfreemodel(model);
};
};
class GurobiModel;
using GurobiCallback = std::function<void(GurobiModel *, int)>;
struct GurobiCallbackUserdata
{
void *model = nullptr;
GurobiCallback callback;
int n_variables = 0;
int where = 0;
// store result of cbget
bool cb_get_mipsol_called = false;
std::vector<double> mipsol;
bool cb_get_mipnoderel_called = false;
std::vector<double> mipnoderel;
// Cache for cbsolution
bool cb_set_solution_called = false;
std::vector<double> heuristic_solution;
bool cb_requires_submit_solution = false;
};
using GurobiLoggingCallback = std::function<void(const char *)>;
struct GurobiLoggingCallbackUserdata
{
GurobiLoggingCallback callback;
};
class GurobiModel : public OnesideLinearConstraintMixin<GurobiModel>,
public OnesideQuadraticConstraintMixin<GurobiModel>,
public TwosideNLConstraintMixin<GurobiModel>,
public LinearObjectiveMixin<GurobiModel>,
public PPrintMixin<GurobiModel>,
public GetValueMixin<GurobiModel>
{
public:
GurobiModel() = default;
GurobiModel(const GurobiEnv &env);
// build the model from OneShotModel directly
GurobiModel(const GurobiEnv &env, const OneShotModel &model);
void close();
void _reset(int clearall);
double get_infinity() const;
void write(const std::string &filename);
VariableIndex add_variable(VariableDomain domain = VariableDomain::Continuous,
double lb = -GRB_INFINITY, double ub = GRB_INFINITY,
const char *name = nullptr);
void delete_variable(const VariableIndex &variable);
void delete_variables(const Vector<VariableIndex> &variables);
bool is_variable_active(const VariableIndex &variable);
double get_variable_value(const VariableIndex &variable);
std::string pprint_variable(const VariableIndex &variable);
void set_variable_bounds(const VariableIndex &variable, double lb, double ub);
void set_variable_name(const VariableIndex &variable, const char *name);
void set_constraint_name(const ConstraintIndex &constraint, const char *name);
ConstraintIndex add_linear_constraint(const ScalarAffineFunction &function,
ConstraintSense sense, CoeffT rhs,
const char *name = nullptr);
ConstraintIndex add_quadratic_constraint(const ScalarQuadraticFunction &function,
ConstraintSense sense, CoeffT rhs,
const char *name = nullptr);
ConstraintIndex add_sos_constraint(const Vector<VariableIndex> &variables, SOSType sos_type);
ConstraintIndex add_sos_constraint(const Vector<VariableIndex> &variables, SOSType sos_type,
const Vector<CoeffT> &weights);
// Nonlinear constraint
void information_of_expr(const ExpressionGraph &graph, const ExpressionHandle &expr,
int &opcode, double &data);
void decode_graph(const ExpressionGraph &graph, const ExpressionHandle &result,
std::vector<int> &opcodes, std::vector<int> &parents,
std::vector<double> &datas);
ConstraintIndex add_single_nl_constraint(const ExpressionGraph &graph,
const ExpressionHandle &result,
const std::tuple<double, double> &interval,
const char *name = nullptr);
void delete_constraint(const ConstraintIndex &constraint);
bool is_constraint_active(const ConstraintIndex &constraint);
void _set_affine_objective(const ScalarAffineFunction &function, ObjectiveSense sense,
bool clear_quadratic);
void set_objective(const ScalarAffineFunction &function, ObjectiveSense sense);
void set_objective(const ScalarQuadraticFunction &function, ObjectiveSense sense);
void set_objective(const ExprBuilder &function, ObjectiveSense sense);
void add_single_nl_objective(ExpressionGraph &graph, const ExpressionHandle &result);
void set_nl_objective();
void optimize();
void update();
void *get_raw_model();
std::string version_string();
// parameter
int raw_parameter_type(const char *param_name);
void set_raw_parameter_int(const char *param_name, int value);
void set_raw_parameter_double(const char *param_name, double value);
void set_raw_parameter_string(const char *param_name, const char *value);
int get_raw_parameter_int(const char *param_name);
double get_raw_parameter_double(const char *param_name);
std::string get_raw_parameter_string(const char *param_name);
// attribute
int raw_attribute_type(const char *attr_name);
// model attribute
void set_model_raw_attribute_int(const char *attr_name, int value);
void set_model_raw_attribute_double(const char *attr_name, double value);
void set_model_raw_attribute_string(const char *attr_name, const char *value);
int get_model_raw_attribute_int(const char *attr_name);
double get_model_raw_attribute_double(const char *attr_name);
std::string get_model_raw_attribute_string(const char *attr_name);
std::vector<double> get_model_raw_attribute_vector_double(const char *attr_name, int start,
int len);
std::vector<double> get_model_raw_attribute_list_double(const char *attr_name,
const std::vector<int> &ind);
// variable attribute
void set_variable_raw_attribute_int(const VariableIndex &variable, const char *attr_name,
int value);
void set_variable_raw_attribute_char(const VariableIndex &variable, const char *attr_name,
char value);
void set_variable_raw_attribute_double(const VariableIndex &variable, const char *attr_name,
double value);
void set_variable_raw_attribute_string(const VariableIndex &variable, const char *attr_name,
const char *value);
int get_variable_raw_attribute_int(const VariableIndex &variable, const char *attr_name);
char get_variable_raw_attribute_char(const VariableIndex &variable, const char *attr_name);
double get_variable_raw_attribute_double(const VariableIndex &variable, const char *attr_name);
std::string get_variable_raw_attribute_string(const VariableIndex &variable,
const char *attr_name);
int _variable_index(const VariableIndex &variable);
int _checked_variable_index(const VariableIndex &variable);
// constraint attribute
void set_constraint_raw_attribute_int(const ConstraintIndex &constraint, const char *attr_name,
int value);
void set_constraint_raw_attribute_char(const ConstraintIndex &constraint, const char *attr_name,
char value);
void set_constraint_raw_attribute_double(const ConstraintIndex &constraint,
const char *attr_name, double value);
void set_constraint_raw_attribute_string(const ConstraintIndex &constraint,
const char *attr_name, const char *value);
int get_constraint_raw_attribute_int(const ConstraintIndex &constraint, const char *attr_name);
char get_constraint_raw_attribute_char(const ConstraintIndex &constraint,
const char *attr_name);
double get_constraint_raw_attribute_double(const ConstraintIndex &constraint,
const char *attr_name);
std::string get_constraint_raw_attribute_string(const ConstraintIndex &constraint,
const char *attr_name);
int _constraint_index(const ConstraintIndex &constraint);
int _checked_constraint_index(const ConstraintIndex &constraint);
// Modifications of model
// 1. set/get RHS of a constraint
double get_normalized_rhs(const ConstraintIndex &constraint);
void set_normalized_rhs(const ConstraintIndex &constraint, double value);
// 2. set/get coefficient of variable in constraint
double get_normalized_coefficient(const ConstraintIndex &constraint,
const VariableIndex &variable);
void set_normalized_coefficient(const ConstraintIndex &constraint,
const VariableIndex &variable, double value);
// 3. set/get linear coefficient of variable in objective
double get_objective_coefficient(const VariableIndex &variable);
void set_objective_coefficient(const VariableIndex &variable, double value);
// Gurobi-specific convertofixed
void _converttofixed();
// IIS related
void computeIIS();
// Non-exported functions
void check_error(int error);
// Control logging
void set_logging(const GurobiLoggingCallback &callback);
GurobiLoggingCallbackUserdata m_logging_callback_userdata;
// Callback
void set_callback(const GurobiCallback &callback);
// For callback
bool has_callback = false;
void *m_cbdata = nullptr;
GurobiCallbackUserdata m_callback_userdata;
int cb_get_info_int(int what);
double cb_get_info_double(int what);
void cb_get_info_doublearray(int what);
double cb_get_solution(const VariableIndex &variable);
double cb_get_relaxation(const VariableIndex &variable);
void cb_set_solution(const VariableIndex &variable, double value);
double cb_submit_solution();
void cb_exit();
void cb_add_lazy_constraint(const ScalarAffineFunction &function, ConstraintSense sense,
CoeffT rhs);
void cb_add_lazy_constraint(const ExprBuilder &function, ConstraintSense sense, CoeffT rhs);
void cb_add_user_cut(const ScalarAffineFunction &function, ConstraintSense sense, CoeffT rhs);
void cb_add_user_cut(const ExprBuilder &function, ConstraintSense sense, CoeffT rhs);
private:
MonotoneIndexer<int> m_variable_index;
MonotoneIndexer<int> m_linear_constraint_index;
MonotoneIndexer<int> m_quadratic_constraint_index;
MonotoneIndexer<int> m_sos_constraint_index;
MonotoneIndexer<int> m_general_constraint_index;
// Gurobi only accepts y = f(x) style nonlinear constraint
// so for each lb <= f(x) <= ub, we need to convert it to
// lb <= y <= ub, and add y = f(x) as a nonlinear constraint
// y is called the result variable (resvar)
Hashmap<IndexT, IndexT> m_nlcon_resvar_map;
// for each nonlinear term in objective function, we need to record the resvar to set their
// coefficient in objective as 1.0
// add f(x) to the objective is divided into two steps:
// 1. add a new nonlinear constraint y = f(x)
// 2. set the coefficient of y in objective to 1.0
int m_nlobj_num = 0;
std::vector<int> m_nlobj_con_indices;
std::vector<int> m_nlobj_resvar_indices;
/* flag to indicate whether the model needs update */
enum : std::uint64_t
{
m_variable_creation = 1,
m_variable_deletion = 1 << 1,
m_linear_constraint_creation = 1 << 2,
m_linear_constraint_deletion = 1 << 3,
m_quadratic_constraint_creation = 1 << 4,
m_quadratic_constraint_deletion = 1 << 5,
m_sos_constraint_creation = 1 << 6,
m_sos_constraint_deletion = 1 << 7,
m_general_constraint_creation = 1 << 8,
m_general_constraint_deletion = 1 << 9,
m_objective_update = 1 << 10,
m_attribute_update = 1 << 11,
m_constraint_coefficient_update = 1 << 12,
};
std::uint64_t m_update_flag = 0;
void _update_for_information();
void _update_for_variable_index();
void _update_for_constraint_index(ConstraintType type);
/* Gurobi part */
GRBenv *m_env = nullptr;
std::unique_ptr<GRBmodel, GRBfreemodelT> m_model;
};