5#ifndef IDOL_OPTIMIZERWITHLAZYUPDATES_H
6#define IDOL_OPTIMIZERWITHLAZYUPDATES_H
8#include "idol/general/optimizers/Optimizer.h"
10#include "idol/mixed-integer/modeling/models/Model.h"
17 template<
class T,
class ImplT>
20 template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
21 class OptimizerWithLazyUpdates;
24template<
class T,
class ImplT>
27 std::optional<ImplT> m_impl;
28 std::optional<std::list<unsigned int>::iterator> m_to_be_updated_flag;
30 Lazy(
const T& t_object, std::list<unsigned int>::iterator t_to_be_updated_flag)
31 : m_object(t_object), m_to_be_updated_flag(t_to_be_updated_flag) {}
33 [[nodiscard]]
bool has_impl()
const {
return m_impl.has_value(); }
35 ImplT& impl() {
return m_impl.value(); }
37 const ImplT& impl()
const {
return m_impl.value(); }
39 [[nodiscard]]
bool is_to_be_updated()
const {
return m_to_be_updated_flag.has_value(); }
41 void set_as_to_be_updated(std::list<unsigned int>::iterator t_flag) { m_to_be_updated_flag = t_flag; }
43 void set_as_updated() {
return m_to_be_updated_flag.reset(); }
45 [[nodiscard]] std::list<unsigned int>::iterator to_be_updated_flag()
const {
return m_to_be_updated_flag.value(); }
47 void set_impl(ImplT&& t_impl) { m_impl = std::move(t_impl); }
49 const T& object()
const {
return m_object; }
52template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
54 std::vector<Lazy<Var, VarImplT>> m_variables;
55 std::list<unsigned int> m_variables_to_update;
57 std::vector<Lazy<Ctr, CtrImplT>> m_constraints;
58 std::list<unsigned int> m_constraints_to_update;
60 std::vector<Lazy<QCtr, QCtrImplT>> m_qconstraints;
61 std::list<unsigned int> m_qconstraints_to_update;
63 std::vector<Lazy<SOSCtr, SOSCtrImplT>> m_sosconstraints;
64 std::list<unsigned int> m_sosconstraints_to_update;
66 bool m_is_initialized =
false;
67 bool m_is_objective_to_be_updated =
true;
68 bool m_is_rhs_to_be_updated =
true;
73 void update_sosctrs();
75 void lazy_update_objective_sense();
76 void lazy_update_matrix(
const Ctr& t_ctr,
const Var &t_var,
double t_constant);
77 void lazy_update(
const Var& t_var);
78 void lazy_update(
const Ctr& t_ctr);
79 void lazy_update_objective();
80 void lazy_update_rhs();
85 virtual void hook_build() = 0;
87 void write(
const std::string &t_name)
final;
88 virtual void hook_write(
const std::string& t_name) = 0;
90 void add(
const Var &t_var)
final;
91 virtual VarImplT hook_add(
const Var& t_var,
bool t_add_column) = 0;
93 void add(
const Ctr &t_ctr)
final;
94 virtual CtrImplT hook_add(
const Ctr& t_ctr) = 0;
96 void add(
const QCtr& t_ctr)
final;
97 virtual QCtrImplT hook_add(
const QCtr& t_ctr) = 0;
99 void add(
const SOSCtr& t_ctr)
final;
100 virtual SOSCtrImplT hook_add(
const SOSCtr& t_ctr) = 0;
102 virtual void hook_update_objective_sense() = 0;
103 virtual void hook_update_matrix(
const Ctr &t_ctr,
const Var &t_var,
double t_constant) = 0;
106 virtual void hook_update() = 0;
107 virtual void hook_update(
const Var& t_var) = 0;
108 virtual void hook_update(
const Ctr& t_ctr) = 0;
110 virtual void hook_update_objective() = 0;
112 virtual void hook_update_rhs() = 0;
114 void remove(
const Var& t_var)
final;
115 virtual void hook_remove(
const Var& t_var) = 0;
117 void remove(
const Ctr& t_ctr)
final;
118 virtual void hook_remove(
const Ctr& t_ctr) = 0;
120 void remove(
const QCtr& t_ctr)
final;
121 virtual void hook_remove(
const QCtr& t_ctr) = 0;
123 void remove(
const SOSCtr& t_ctr)
final;
124 virtual void hook_remove(
const SOSCtr& t_ctr) = 0;
126 [[nodiscard]]
bool has_lazy(
const Var& t_var)
const {
127 const unsigned int index = parent().get_var_index(t_var);
128 return index < m_variables.size() && m_variables[index].object().id() == t_var.
id();
131 [[nodiscard]]
bool has_lazy(
const Ctr& t_ctr)
const {
132 const unsigned int index = parent().get_ctr_index(t_ctr);
133 return index < m_constraints.size() && m_constraints[index].object().id() == t_ctr.
id();
136 [[nodiscard]]
bool has_lazy(
const QCtr& t_qctr)
const {
137 const unsigned int index = parent().get_qctr_index(t_qctr);
138 return index < m_qconstraints.size() && m_qconstraints[index].object().id() == t_qctr.
id();
141 auto& lazy(
const Var& t_var) {
return m_variables[parent().get_var_index(t_var)]; }
142 const auto& lazy(
const Var& t_var)
const {
return m_variables[parent().get_var_index(t_var)]; }
144 auto& lazy(
const Ctr& t_ctr) {
return m_constraints[parent().get_ctr_index(t_ctr)]; }
145 const auto& lazy(
const Ctr& t_ctr)
const {
return m_constraints[parent().get_ctr_index(t_ctr)]; }
147 auto& lazy(
const QCtr& t_ctr) {
return m_qconstraints[parent().get_qctr_index(t_ctr)]; }
148 const auto& lazy(
const QCtr& t_ctr)
const {
return m_qconstraints[parent().get_qctr_index(t_ctr)]; }
150 auto& lazy(
const SOSCtr& t_ctr) {
return m_sosconstraints[parent().get_sosctr_index(t_ctr)]; }
151 const auto& lazy(
const SOSCtr& t_ctr)
const {
return m_sosconstraints[parent().get_sosctr_index(t_ctr)]; }
153 auto& lazy_vars() {
return m_variables; }
154 const auto& lazy_vars()
const {
return m_variables; }
156 auto& lazy_ctrs() {
return m_constraints; }
157 const auto& lazy_ctrs()
const {
return m_constraints; }
159 auto& lazy_qctrs() {
return m_qconstraints; }
160 const auto& lazy_qctrs()
const {
return m_qconstraints; }
162 auto& lazy_sosctrs() {
return m_sosconstraints; }
163 const auto& lazy_sosctrs()
const {
return m_sosconstraints; }
165 void set_objective_to_be_updated() { m_is_objective_to_be_updated =
true; }
166 [[nodiscard]]
bool is_objective_to_be_updated()
const {
return m_is_objective_to_be_updated; }
167 void set_objective_as_updated() { m_is_objective_to_be_updated =
false; }
169 void set_rhs_to_be_updated() { m_is_rhs_to_be_updated =
true; }
170 [[nodiscard]]
bool is_rhs_to_be_updated()
const {
return m_is_rhs_to_be_updated; }
171 void set_rhs_as_updated() { m_is_rhs_to_be_updated =
false; }
173 void update_obj_sense()
override;
174 void update_obj()
override;
175 void update_rhs()
override;
176 void update_obj_constant()
override;
177 void update_mat_coeff(
const Ctr &t_ctr,
const Var &t_var)
override;
178 void update_ctr_type(
const Ctr &t_ctr)
override;
179 void update_ctr_rhs(
const Ctr &t_ctr)
override;
180 void update_var_type(
const Var &t_var)
override;
181 void update_var_lb(
const Var &t_var)
override;
182 void update_var_ub(
const Var &t_var)
override;
183 void update_var_obj(
const Var &t_var)
override;
185 VarImplT& operator[](
const Var& t_var) {
return lazy(t_var).impl(); }
186 const VarImplT& operator[](
const Var& t_var)
const {
return lazy(t_var).impl(); }
188 CtrImplT& operator[](
const Ctr& t_ctr) {
return lazy(t_ctr).impl(); }
189 const CtrImplT& operator[](
const Ctr& t_ctr)
const {
return lazy(t_ctr).impl(); }
192template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
197template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
202template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
207template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
212template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
217template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
222template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
224 lazy_update_matrix(t_ctr, t_var, parent().get_mat_coeff(t_ctr, t_var));
227template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
229 lazy_update_objective();
232template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
234 lazy_update_objective();
237template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
239 lazy_update_objective_sense();
243template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
248template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
253template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
256 const auto& parent = this->parent();
258 m_variables.reserve(parent.vars().size());
259 for (
const auto& var : parent.vars()) {
263 m_constraints.reserve(parent.ctrs().size());
264 for (
const auto& ctr : parent.ctrs()) {
268 m_qconstraints.reserve(parent.qctrs().size());
269 for (
const auto& qctr : parent.qctrs()) {
273 m_sosconstraints.reserve(parent.sosctrs().size());
274 for (
const auto& sosctr : parent.sosctrs()) {
278 set_objective_to_be_updated();
279 set_rhs_to_be_updated();
284template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
290template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
301 if (is_objective_to_be_updated()) {
302 hook_update_objective();
303 set_objective_as_updated();
306 if (is_rhs_to_be_updated()) {
308 set_rhs_as_updated();
313 m_is_initialized =
true;
316template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
319 for (
const unsigned int index : m_variables_to_update) {
321 if (m_variables[index].has_impl()) {
322 hook_update(m_variables[index].
object());
324 auto impl = hook_add(m_variables[index].
object(), m_is_initialized);
325 m_variables[index].set_impl(std::move(impl));
328 m_variables[index].set_as_updated();
331 m_variables_to_update.clear();
335template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
338 for (
const unsigned int index : m_constraints_to_update) {
340 if (m_constraints[index].has_impl()) {
341 hook_update(m_constraints[index].
object());
343 auto impl = hook_add(m_constraints[index].
object());
344 m_constraints[index].set_impl(std::move(impl));
347 m_constraints[index].set_as_updated();
351 m_constraints_to_update.clear();
355template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
358 for (
const unsigned int index : m_qconstraints_to_update) {
360 if (m_qconstraints[index].has_impl()) {
361 throw Exception(
"Updating quadratic constraints is not supported.");
364 auto impl = hook_add(m_qconstraints[index].
object());
365 m_qconstraints[index].set_impl(std::move(impl));
368 m_qconstraints[index].set_as_updated();
372 m_qconstraints_to_update.clear();
376template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
379 for (
const unsigned int index : m_sosconstraints_to_update) {
381 if (m_sosconstraints[index].has_impl()) {
382 throw Exception(
"Updating SOS constraints is not supported.");
384 auto impl = hook_add(m_sosconstraints[index].
object());
385 m_sosconstraints[index].set_impl(std::move(impl));
388 m_sosconstraints[index].set_as_updated();
392 m_sosconstraints_to_update.clear();
396template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
398 set_rhs_to_be_updated();
401template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
403 set_objective_to_be_updated();
406template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
408 hook_update_objective_sense();
411template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
413 const unsigned int index = parent().get_var_index(t_var);
414 m_variables_to_update.emplace_back(index);
415 m_variables[index].set_as_to_be_updated(m_variables_to_update.begin());
418template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
420 const unsigned int index = parent().get_ctr_index(t_ctr);
421 m_constraints_to_update.emplace_back(index);
422 m_constraints[index].set_as_to_be_updated(m_constraints_to_update.begin());
425template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
427 hook_update_matrix(t_ctr, t_var, t_constant);
430template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
433 if (m_is_initialized) {
437 const unsigned int index = parent().get_ctr_index(t_ctr);
438 m_constraints_to_update.emplace_back(index);
439 m_constraints.emplace_back(t_ctr, m_constraints_to_update.begin());
442template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
445 if (m_is_initialized) {
449 const unsigned int index = parent().get_qctr_index(t_ctr);
450 m_qconstraints_to_update.emplace_back(index);
451 m_qconstraints.emplace_back(t_ctr, m_qconstraints_to_update.begin());
455template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
458 if (m_is_initialized) {
462 const unsigned int index = parent().get_sosctr_index(t_ctr);
463 m_sosconstraints_to_update.emplace_back(index);
464 m_sosconstraints.emplace_back(t_ctr, m_sosconstraints_to_update.begin());
468template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
471 if (m_is_initialized) {
475 const unsigned int index = parent().get_var_index(t_var);
476 m_variables_to_update.emplace_back(index);
477 m_variables.emplace_back(t_var, m_variables_to_update.begin());
480template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
485 const unsigned index = parent().get_var_index(t_var);
487 if (m_variables[index].has_impl()) {
488 hook_remove(m_variables[index].
object());
491 m_variables[index] = std::move(m_variables.back());
492 m_variables.pop_back();
495template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
500 const unsigned index = parent().get_ctr_index(t_ctr);
502 if (m_constraints[index].has_impl()) {
503 hook_remove(m_constraints[index].
object());
506 m_constraints[index] = std::move(m_constraints.back());
507 m_constraints.pop_back();
510template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
515 const unsigned index = parent().get_qctr_index(t_ctr);
517 if (m_qconstraints[index].has_impl()) {
518 hook_remove(m_qconstraints[index].
object());
521 m_qconstraints[index] = std::move(m_qconstraints.back());
522 m_qconstraints.pop_back();
525template<
class VarImplT,
class CtrImplT,
class QCtrImplT,
class SOSCtrImplT>
530 const unsigned index = parent().get_sosctr_index(t_ctr);
532 if (m_sosconstraints[index].has_impl()) {
533 hook_remove(m_sosconstraints[index].
object());
536 m_sosconstraints[index] = std::move(m_sosconstraints.back());
537 m_sosconstraints.pop_back();