Sleipnir C++ API
Loading...
Searching...
No Matches
problem.hpp
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <algorithm>
6#include <concepts>
7#include <functional>
8#include <iterator>
9#include <optional>
10#include <ranges>
11#include <utility>
12
13#include <Eigen/Core>
14
15#include "sleipnir/autodiff/expression_type.hpp"
16#include "sleipnir/autodiff/variable.hpp"
17#include "sleipnir/autodiff/variable_matrix.hpp"
18#include "sleipnir/optimization/solver/exit_status.hpp"
19#include "sleipnir/optimization/solver/iteration_info.hpp"
20#include "sleipnir/optimization/solver/options.hpp"
21#include "sleipnir/util/small_vector.hpp"
22#include "sleipnir/util/symbol_exports.hpp"
23
24namespace slp {
25
47class SLEIPNIR_DLLEXPORT Problem {
48 public:
52 Problem() noexcept = default;
53
59 [[nodiscard]]
60 Variable decision_variable() {
61 m_decision_variables.emplace_back();
62 return m_decision_variables.back();
63 }
64
72 [[nodiscard]]
73 VariableMatrix decision_variable(int rows, int cols = 1) {
74 m_decision_variables.reserve(m_decision_variables.size() + rows * cols);
75
76 VariableMatrix vars{rows, cols};
77
78 for (int row = 0; row < rows; ++row) {
79 for (int col = 0; col < cols; ++col) {
80 m_decision_variables.emplace_back();
81 vars[row, col] = m_decision_variables.back();
82 }
83 }
84
85 return vars;
86 }
87
99 [[nodiscard]]
101 // We only need to store the lower triangle of an n x n symmetric matrix;
102 // the other elements are duplicates. The lower triangle has (n² + n)/2
103 // elements.
104 //
105 // n
106 // Σ k = (n² + n)/2
107 // k=1
108 m_decision_variables.reserve(m_decision_variables.size() +
109 (rows * rows + rows) / 2);
110
111 VariableMatrix vars{rows, rows};
112
113 for (int row = 0; row < rows; ++row) {
114 for (int col = 0; col <= row; ++col) {
115 m_decision_variables.emplace_back();
116 vars[row, col] = m_decision_variables.back();
117 vars[col, row] = m_decision_variables.back();
118 }
119 }
120
121 return vars;
122 }
123
133 void minimize(const Variable& cost) { m_f = cost; }
134
144 void minimize(Variable&& cost) { m_f = std::move(cost); }
145
155 void maximize(const Variable& objective) {
156 // Maximizing a cost function is the same as minimizing its negative
157 m_f = -objective;
158 }
159
169 void maximize(Variable&& objective) {
170 // Maximizing a cost function is the same as minimizing its negative
171 m_f = -std::move(objective);
172 }
173
180 void subject_to(const EqualityConstraints& constraint) {
181 m_equality_constraints.reserve(m_equality_constraints.size() +
182 constraint.constraints.size());
183 std::ranges::copy(constraint.constraints,
184 std::back_inserter(m_equality_constraints));
185 }
186
193 void subject_to(EqualityConstraints&& constraint) {
194 m_equality_constraints.reserve(m_equality_constraints.size() +
195 constraint.constraints.size());
196 std::ranges::copy(constraint.constraints,
197 std::back_inserter(m_equality_constraints));
198 }
199
206 void subject_to(const InequalityConstraints& constraint) {
207 m_inequality_constraints.reserve(m_inequality_constraints.size() +
208 constraint.constraints.size());
209 std::ranges::copy(constraint.constraints,
210 std::back_inserter(m_inequality_constraints));
211 }
212
220 m_inequality_constraints.reserve(m_inequality_constraints.size() +
221 constraint.constraints.size());
222 std::ranges::copy(constraint.constraints,
223 std::back_inserter(m_inequality_constraints));
224 }
225
231 ExpressionType cost_function_type() const {
232 if (m_f) {
233 return m_f.value().type();
234 } else {
235 return ExpressionType::NONE;
236 }
237 }
238
244 ExpressionType equality_constraint_type() const {
245 if (!m_equality_constraints.empty()) {
246 return std::ranges::max(m_equality_constraints, {}, &Variable::type)
247 .type();
248 } else {
249 return ExpressionType::NONE;
250 }
251 }
252
258 ExpressionType inequality_constraint_type() const {
259 if (!m_inequality_constraints.empty()) {
260 return std::ranges::max(m_inequality_constraints, {}, &Variable::type)
261 .type();
262 } else {
263 return ExpressionType::NONE;
264 }
265 }
266
277 ExitStatus solve(const Options& options = Options{},
278 [[maybe_unused]] bool spy = false);
279
287 template <typename F>
288 requires requires(F callback, const IterationInfo& info) {
289 { callback(info) } -> std::same_as<void>;
290 }
291 void add_callback(F&& callback) {
292 m_iteration_callbacks.emplace_back(
293 [=, callback = std::forward<F>(callback)](const IterationInfo& info) {
294 callback(info);
295 return false;
296 });
297 }
298
307 template <typename F>
308 requires requires(F callback, const IterationInfo& info) {
309 { callback(info) } -> std::same_as<bool>;
310 }
311 void add_callback(F&& callback) {
312 m_iteration_callbacks.emplace_back(std::forward<F>(callback));
313 }
314
318 void clear_callbacks() { m_iteration_callbacks.clear(); }
319
320 private:
321 // The list of decision variables, which are the root of the problem's
322 // expression tree
323 small_vector<Variable> m_decision_variables;
324
325 // The cost function: f(x)
326 std::optional<Variable> m_f;
327
328 // The list of equality constraints: cₑ(x) = 0
329 small_vector<Variable> m_equality_constraints;
330
331 // The list of inequality constraints: cᵢ(x) ≥ 0
332 small_vector<Variable> m_inequality_constraints;
333
334 // The iteration callbacks
335 small_vector<std::function<bool(const IterationInfo& info)>>
336 m_iteration_callbacks;
337
338 void print_exit_conditions([[maybe_unused]] const Options& options);
339 void print_problem_analysis();
340};
341
342} // namespace slp
Definition problem.hpp:47
void clear_callbacks()
Definition problem.hpp:318
void subject_to(const EqualityConstraints &constraint)
Definition problem.hpp:180
VariableMatrix decision_variable(int rows, int cols=1)
Definition problem.hpp:73
Problem() noexcept=default
void maximize(Variable &&objective)
Definition problem.hpp:169
ExitStatus solve(const Options &options=Options{}, bool spy=false)
ExpressionType equality_constraint_type() const
Definition problem.hpp:244
void subject_to(InequalityConstraints &&constraint)
Definition problem.hpp:219
void minimize(const Variable &cost)
Definition problem.hpp:133
VariableMatrix symmetric_decision_variable(int rows)
Definition problem.hpp:100
void subject_to(EqualityConstraints &&constraint)
Definition problem.hpp:193
void maximize(const Variable &objective)
Definition problem.hpp:155
void add_callback(F &&callback)
Definition problem.hpp:291
ExpressionType cost_function_type() const
Definition problem.hpp:231
void add_callback(F &&callback)
Definition problem.hpp:311
void minimize(Variable &&cost)
Definition problem.hpp:144
void subject_to(const InequalityConstraints &constraint)
Definition problem.hpp:206
ExpressionType inequality_constraint_type() const
Definition problem.hpp:258
Definition variable_matrix.hpp:29
Definition variable.hpp:40
Definition variable.hpp:559
small_vector< Variable > constraints
A vector of scalar equality constraints.
Definition variable.hpp:561
Definition variable.hpp:620
small_vector< Variable > constraints
A vector of scalar inequality constraints.
Definition variable.hpp:622
Definition iteration_info.hpp:13
Definition options.hpp:15