Loading...
Searching...
No Matches
Optimizers_JuMP.h
1//
2// Created by henri on 02.05.25.
3//
4
5#ifndef IDOL_OPTIMIZERS_JUMP_H
6#define IDOL_OPTIMIZERS_JUMP_H
7
8#include "idol/general/optimizers/OptimizerWithLazyUpdates.h"
9#include "idol/general/utils/Set.h"
10
11namespace idol::Optimizers {
12 class JuMP;
13}
14
15extern "C" {
16
17 // Opaque Julia value (everything in Julia is this)
18 typedef struct _jl_value_t jl_value_t;
19
20 // Function object
21 typedef struct _jl_function_t jl_function_t;
22
23 // Julia module
24 typedef struct _jl_module_t jl_module_t;
25
26 // Julia array (opaque container)
27 typedef struct _jl_array_t jl_array_t;
28
29 // Data type object (Float64, Int64, etc.)
30 typedef struct _jl_datatype_t jl_datatype_t;
31
32 typedef struct _jl_sym_t jl_sym_t;
33
34 extern jl_module_t* jl_main_module;
35 extern jl_module_t* jl_base_module;
36
37 extern jl_value_t* jl_float64_type;
38 extern jl_value_t* jl_int64_type;
39 extern jl_value_t* jl_uint64_type;
40 extern jl_value_t* jl_bool_type;
41 extern jl_value_t* jl_any_type;
42 extern jl_value_t* jl_array_type;
43
44 void jl_init(void);
45 void jl_atexit_hook(int exitcode);
46 jl_value_t *jl_eval_string(const char *str);
47 jl_value_t *jl_apply_array_type(jl_value_t *type, size_t dim);
48 jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, size_t nel, int own_buffer);
49 jl_sym_t *jl_symbol(const char *str);
50 jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var);
51
52 jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, uint32_t nargs);
53 jl_value_t* jl_call0(jl_function_t* f);
54 jl_value_t* jl_call1(jl_function_t* f, jl_value_t* arg0);
55 jl_value_t* jl_call2(jl_function_t* f, jl_value_t* arg0, jl_value_t* arg1);
56 jl_value_t* jl_call3(jl_function_t* f, jl_value_t* arg0, jl_value_t* arg1, jl_value_t* arg2);
57
58 jl_value_t* jl_box_float64(double x);
59 jl_value_t* jl_box_uint64(uint64_t x);
60 jl_value_t* jl_box_uint16(uint16_t x);
61 jl_value_t* jl_box_int64(int64_t x);
62 jl_value_t* jl_cstr_to_string(const char* str);
63
64 double jl_unbox_float64(jl_value_t* v);
65 uint64_t jl_unbox_uint64(jl_value_t* v);
66 uint16_t jl_unbox_uint16(jl_value_t* v);
67 int64_t jl_unbox_int64(jl_value_t* v);
68
69 jl_datatype_t* jl_typeof(jl_value_t* v);
70 const char* jl_symbol_name(jl_sym_t* s);
71
72 jl_value_t* jl_exception_occurred(void);
73 void jl_exception_clear(void);
74
75 void jl_gc_collect(int);
76 void jl_gc_enable(int);
77
78}
79
80class idol::Optimizers::JuMP : public OptimizerWithLazyUpdates<bool, bool, bool, bool> {
81protected:
82 std::optional<uint64_t> m_model_id = 0;
83 const std::string m_optimizer;
84 const std::list<std::string> m_modules;
85 bool m_is_continuous_relaxation;
86
87 class DynamicLib;
88 static std::unique_ptr<DynamicLib> m_dynamic_lib;
89public:
90 JuMP(const Model& t_parent,
91 std::string t_optimizer,
92 const std::list<std::string>& t_modules,
93 bool t_is_continuous_relaxation);
94
95 ~JuMP() override;
96
97 static bool is_available();
98 static std::string get_version();
99
100 [[nodiscard]] std::string name() const override;
101 [[nodiscard]] SolutionStatus get_status() const override;
102 [[nodiscard]] SolutionReason get_reason() const override;
103 [[nodiscard]] double get_best_obj() const override;
104 [[nodiscard]] double get_best_bound() const override;
105 [[nodiscard]] double get_var_primal(const Var &t_var) const override;
106 [[nodiscard]] double get_var_reduced_cost(const Var &t_var) const override;
107 [[nodiscard]] double get_var_ray(const Var &t_var) const override;
108 [[nodiscard]] double get_ctr_dual(const Ctr &t_ctr) const override;
109 [[nodiscard]] double get_ctr_farkas(const Ctr &t_ctr) const override;
110 [[nodiscard]] double get_relative_gap() const override;
111 [[nodiscard]] double get_absolute_gap() const override;
112 [[nodiscard]] unsigned int get_n_solutions() const override;
113 [[nodiscard]] unsigned int get_solution_index() const override;
114 void debug_print() const;
115
116 static DynamicLib& get_dynamic_lib(bool t_throw_on_fail = true);
117protected:
118 void hook_optimize() override;
119
120 virtual uint64_t hook_create_julia_model(jl_value_t* t_optimizer);
121
122 void set_solution_index(unsigned int t_index) override;
123 void hook_build() override;
124 void hook_write(const std::string &t_name) override;
125 bool hook_add(const Var &t_var, bool t_add_column) override;
126 bool hook_add(const Ctr &t_ctr) override;
127 bool hook_add(const QCtr &t_ctr) override;
128 bool hook_add(const SOSCtr &t_ctr) override;
129 void hook_update_objective_sense() override;
130 void hook_update_matrix(const Ctr &t_ctr, const Var &t_var, double t_constant) override;
131 void hook_update() override;
132 void hook_update(const Var &t_var) override;
133 void hook_update(const Ctr &t_ctr) override;
134 void hook_update_objective() override;
135 void hook_update_rhs() override;
136 void hook_remove(const Var &t_var) override;
137 void hook_remove(const Ctr &t_ctr) override;
138 void hook_remove(const QCtr &t_ctr) override;
139 void hook_remove(const SOSCtr &t_ctr) override;
140
141 template<class T>
142 jl_value_t* make_julia_vector(const std::vector<T>& t_vector);
143
144};
145
146#define JULIA_SYM_PTR(name) \
147typedef decltype(::name)* name##_t; \
148name##_t name = nullptr
149
151 void* m_handle = nullptr;
152
153 static std::string find_library();
154public:
155 JULIA_SYM_PTR(jl_init);
156 JULIA_SYM_PTR(jl_atexit_hook);
157 JULIA_SYM_PTR(jl_eval_string);
158 JULIA_SYM_PTR(jl_apply_array_type);
159 JULIA_SYM_PTR(jl_ptr_to_array_1d);
160 JULIA_SYM_PTR(jl_symbol);
161 JULIA_SYM_PTR(jl_get_global);
162
163 JULIA_SYM_PTR(jl_call);
164 JULIA_SYM_PTR(jl_call0);
165 JULIA_SYM_PTR(jl_call1);
166 JULIA_SYM_PTR(jl_call2);
167 JULIA_SYM_PTR(jl_call3);
168
169 JULIA_SYM_PTR(jl_box_float64);
170 JULIA_SYM_PTR(jl_box_uint64);
171 JULIA_SYM_PTR(jl_box_uint16);
172 JULIA_SYM_PTR(jl_box_int64);
173 JULIA_SYM_PTR(jl_cstr_to_string);
174
175 JULIA_SYM_PTR(jl_unbox_float64);
176 JULIA_SYM_PTR(jl_unbox_uint64);
177 JULIA_SYM_PTR(jl_unbox_uint16);
178 JULIA_SYM_PTR(jl_unbox_int64);
179
180 JULIA_SYM_PTR(jl_typeof);
181 //JULIA_SYM_PTR(jl_symbol_name);
182
183 JULIA_SYM_PTR(jl_exception_occurred);
184 JULIA_SYM_PTR(jl_exception_clear);
185
186 JULIA_SYM_PTR(jl_gc_collect);
187 JULIA_SYM_PTR(jl_gc_enable);
188
189 JULIA_SYM_PTR(jl_main_module);
190
191 DynamicLib();
192
193 ~DynamicLib();
194
195 jl_value_t *jl_get_function(jl_module_t *m, const char *name) {
196 auto& lib = idol::Optimizers::JuMP::get_dynamic_lib();
197 assert(m != nullptr);
198 return (jl_value_t*) lib.jl_get_global(m, lib.jl_symbol(name));
199 }
200
201 [[nodiscard]] bool is_available() const { return m_handle; }
202};
203
204template <class T>
205jl_value_t* idol::Optimizers::JuMP::make_julia_vector(const std::vector<T>& t_vector) {
206
207 auto& lib = get_dynamic_lib();
208
209 jl_value_t* julia_type;
210 if constexpr (std::is_same_v<T, double>) {
211 julia_type = (jl_value_t*) jl_float64_type;
212 } else if constexpr (std::is_same_v<T, uint64_t>) {
213 julia_type = (jl_value_t*) jl_uint64_type;
214 } else {
215 throw idol::Exception("Unsupported julia_type");
216 }
217
218 jl_value_t* array_type = lib.jl_apply_array_type(julia_type, 1);
219 jl_array_t *result = lib.jl_ptr_to_array_1d(array_type, (T*) t_vector.data(), t_vector.size(), 0);
220
221 return (jl_value_t*) result;
222}
223
224namespace idol::impl {
225
226 class JuliaSessionManager {
227 bool m_idol_jump_module_is_loaded = false;
228 bool m_idol_coluna_is_loaded = false;
229 Set<std::string> m_loaded_modules;
230 static JuliaSessionManager* s_julia_session_manager;
231
232 static JuliaSessionManager& get();
233 public:
234 JuliaSessionManager();
235 JuliaSessionManager(const JuliaSessionManager&) = delete;
236 JuliaSessionManager(JuliaSessionManager&&) = delete;
237 JuliaSessionManager& operator=(const JuliaSessionManager&) = delete;
238 JuliaSessionManager& operator=(JuliaSessionManager&&) = delete;
239
240 static void load_idol_jump_module();
241 static void load_idol_coluna_module();
242 static void load_module(const std::string &t_module);
243
244 ~JuliaSessionManager();
245
246 static void throw_if_julia_error();
247 };
248
249}
250
251
252#endif