7#include <initializer_list>
9#include <source_location>
16#include "sleipnir/autodiff/expression.hpp"
17#include "sleipnir/autodiff/expression_graph.hpp"
18#include "sleipnir/util/assert.hpp"
19#include "sleipnir/util/concepts.hpp"
20#include "sleipnir/util/small_vector.hpp"
21#include "sleipnir/util/symbol_exports.hpp"
23#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
24#include "sleipnir/util/print.hpp"
31class AdjointExpressionGraph;
33template <
int UpLo = Eigen::Lower | Eigen::Upper>
34 requires(UpLo == Eigen::Lower) || (UpLo == (Eigen::Lower | Eigen::Upper))
35class SLEIPNIR_DLLEXPORT Hessian;
36class SLEIPNIR_DLLEXPORT Jacobian;
51 explicit constexpr Variable(std::nullptr_t) : expr{nullptr} {}
59 : expr{detail::make_expression_ptr<detail::ConstExpression>(value)} {}
67 : expr{detail::make_expression_ptr<detail::ConstExpression>(value)} {}
82 : expr{std::move(expr)} {}
91 expr = detail::make_expression_ptr<detail::ConstExpression>(value);
102 if (expr->is_constant(0.0)) {
103 expr = detail::make_expression_ptr<detail::ConstExpression>(value);
105#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
108 if (expr->args[0] !=
nullptr) {
109 auto location = std::source_location::current();
112 "WARNING: {}:{}: {}: Modified the value of a dependent variable",
113 location.file_name(), location.line(), location.function_name());
129 return Variable{lhs.expr * rhs.expr};
152 return Variable{lhs.expr / rhs.expr};
175 return Variable{lhs.expr + rhs.expr};
198 return Variable{lhs.expr - rhs.expr};
237 m_graph = detail::topological_sort(expr);
239 detail::update_values(m_graph.value());
250 ExpressionType
type()
const {
return expr->type(); }
255 detail::make_expression_ptr<detail::DecisionVariableExpression>();
259 std::optional<small_vector<detail::Expression*>> m_graph;
288 requires(UpLo == Eigen::Lower) || (UpLo == (Eigen::Lower | Eigen::Upper))
289 friend class SLEIPNIR_DLLEXPORT
Hessian;
290 friend class SLEIPNIR_DLLEXPORT
Jacobian;
299 return Variable{detail::abs(x.expr)};
308 return Variable{detail::acos(x.expr)};
317 return Variable{detail::asin(x.expr)};
326 return Variable{detail::atan(x.expr)};
336 return Variable{detail::atan2(y.expr, x.expr)};
345 return Variable{detail::cos(x.expr)};
354 return Variable{detail::cosh(x.expr)};
363 return Variable{detail::erf(x.expr)};
372 return Variable{detail::exp(x.expr)};
382 return Variable{detail::hypot(x.expr, y.expr)};
393 return Variable{detail::pow(base.expr, power.expr)};
402 return Variable{detail::log(x.expr)};
411 return Variable{detail::log10(x.expr)};
420 return Variable{detail::sign(x.expr)};
429 return Variable{detail::sin(x.expr)};
438 return Variable{detail::sinh(x.expr)};
447 return Variable{detail::sqrt(x.expr)};
456 return Variable{detail::tan(x.expr)};
465 return Variable{detail::tanh(x.expr)};
477 return Variable{slp::sqrt(slp::pow(x, 2) + slp::pow(y, 2) + slp::pow(z, 2))};
491template <
typename LHS,
typename RHS>
495small_vector<Variable> make_constraints(LHS&& lhs, RHS&& rhs) {
496 small_vector<Variable> constraints;
499 constraints.emplace_back(lhs - rhs);
500 }
else if constexpr (ScalarLike<LHS> && MatrixLike<RHS>) {
501 constraints.reserve(rhs.rows() * rhs.cols());
503 for (
int row = 0; row < rhs.rows(); ++row) {
504 for (
int col = 0; col < rhs.cols(); ++col) {
506 if constexpr (EigenMatrixLike<std::decay_t<RHS>>) {
507 constraints.emplace_back(lhs - rhs(row, col));
509 constraints.emplace_back(lhs - rhs[row, col]);
513 }
else if constexpr (MatrixLike<LHS> && ScalarLike<RHS>) {
514 constraints.reserve(lhs.rows() * lhs.cols());
516 for (
int row = 0; row < lhs.rows(); ++row) {
517 for (
int col = 0; col < lhs.cols(); ++col) {
519 if constexpr (EigenMatrixLike<std::decay_t<LHS>>) {
520 constraints.emplace_back(lhs(row, col) - rhs);
522 constraints.emplace_back(lhs[row, col] - rhs);
526 }
else if constexpr (MatrixLike<LHS> && MatrixLike<RHS>) {
527 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
528 constraints.reserve(lhs.rows() * lhs.cols());
530 for (
int row = 0; row < lhs.rows(); ++row) {
531 for (
int col = 0; col < lhs.cols(); ++col) {
533 if constexpr (EigenMatrixLike<std::decay_t<LHS>> &&
534 EigenMatrixLike<std::decay_t<RHS>>) {
535 constraints.emplace_back(lhs(row, col) - rhs(row, col));
536 }
else if constexpr (EigenMatrixLike<std::decay_t<LHS>> &&
537 SleipnirMatrixLike<std::decay_t<RHS>>) {
538 constraints.emplace_back(lhs(row, col) - rhs[row, col]);
539 }
else if constexpr (SleipnirMatrixLike<std::decay_t<LHS>> &&
540 EigenMatrixLike<std::decay_t<RHS>>) {
541 constraints.emplace_back(lhs[row, col] - rhs(row, col));
542 }
else if constexpr (SleipnirMatrixLike<std::decay_t<LHS>> &&
543 SleipnirMatrixLike<std::decay_t<RHS>>) {
544 constraints.emplace_back(lhs[row, col] - rhs[row, col]);
566 std::initializer_list<EqualityConstraints> equality_constraints) {
567 for (
const auto& elem : equality_constraints) {
568 constraints.insert(constraints.end(), elem.constraints.begin(),
569 elem.constraints.end());
581 const std::vector<EqualityConstraints>& equality_constraints) {
582 for (
const auto& elem : equality_constraints) {
583 constraints.insert(constraints.end(), elem.constraints.begin(),
584 elem.constraints.end());
597 template <
typename LHS,
typename RHS>
602 : constraints{make_constraints(lhs, rhs)} {}
608 return std::ranges::all_of(constraints, [](
auto& constraint) {
609 return constraint.value() == 0.0;
628 std::initializer_list<InequalityConstraints> inequality_constraints) {
629 for (
const auto& elem : inequality_constraints) {
630 constraints.insert(constraints.end(), elem.constraints.begin(),
631 elem.constraints.end());
644 const std::vector<InequalityConstraints>& inequality_constraints) {
645 for (
const auto& elem : inequality_constraints) {
646 constraints.insert(constraints.end(), elem.constraints.begin(),
647 elem.constraints.end());
660 template <
typename LHS,
typename RHS>
665 : constraints{make_constraints(lhs, rhs)} {}
671 return std::ranges::all_of(constraints, [](
auto& constraint) {
672 return constraint.value() >= 0.0;
683template <
typename LHS,
typename RHS>
684 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
685 (ScalarLike<RHS> || MatrixLike<RHS>) &&
686 (SleipnirType<LHS> || SleipnirType<RHS>)
687EqualityConstraints
operator==(LHS&& lhs, RHS&& rhs) {
688 return EqualityConstraints{lhs, rhs};
698template <
typename LHS,
typename RHS>
699 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
700 (ScalarLike<RHS> || MatrixLike<RHS>) &&
701 (SleipnirType<LHS> || SleipnirType<RHS>)
702InequalityConstraints
operator<(LHS&& lhs, RHS&& rhs) {
713template <
typename LHS,
typename RHS>
714 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
715 (ScalarLike<RHS> || MatrixLike<RHS>) &&
716 (SleipnirType<LHS> || SleipnirType<RHS>)
717InequalityConstraints
operator<=(LHS&& lhs, RHS&& rhs) {
728template <
typename LHS,
typename RHS>
729 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
730 (ScalarLike<RHS> || MatrixLike<RHS>) &&
731 (SleipnirType<LHS> || SleipnirType<RHS>)
732InequalityConstraints
operator>(LHS&& lhs, RHS&& rhs) {
743template <
typename LHS,
typename RHS>
744 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
745 (ScalarLike<RHS> || MatrixLike<RHS>) &&
746 (SleipnirType<LHS> || SleipnirType<RHS>)
747InequalityConstraints
operator>=(LHS&& lhs, RHS&& rhs) {
748 return InequalityConstraints{lhs, rhs};
759struct NumTraits<slp::Variable> : NumTraits<double> {
768 static constexpr int IsComplex = 0;
770 static constexpr int IsInteger = 0;
772 static constexpr int IsSigned = 1;
774 static constexpr int RequireInitialization = 1;
776 static constexpr int ReadCost = 1;
778 static constexpr int AddCost = 3;
780 static constexpr int MulCost = 3;
Definition hessian.hpp:31
Definition jacobian.hpp:27
Definition variable.hpp:41
friend SLEIPNIR_DLLEXPORT Variable operator+(const Variable &lhs)
Definition variable.hpp:226
constexpr Variable(detail::ExpressionPtr &&expr)
Definition variable.hpp:81
friend SLEIPNIR_DLLEXPORT Variable operator*(const Variable &lhs, const Variable &rhs)
Definition variable.hpp:127
Variable & operator=(double value)
Definition variable.hpp:90
Variable & operator-=(const Variable &rhs)
Definition variable.hpp:207
friend SLEIPNIR_DLLEXPORT Variable operator-(const Variable &lhs)
Definition variable.hpp:217
friend SLEIPNIR_DLLEXPORT Variable operator+(const Variable &lhs, const Variable &rhs)
Definition variable.hpp:173
Variable & operator+=(const Variable &rhs)
Definition variable.hpp:184
friend SLEIPNIR_DLLEXPORT Variable operator-(const Variable &lhs, const Variable &rhs)
Definition variable.hpp:196
Variable & operator*=(const Variable &rhs)
Definition variable.hpp:138
Variable(std::floating_point auto value)
Definition variable.hpp:58
constexpr Variable(std::nullptr_t)
Definition variable.hpp:51
friend SLEIPNIR_DLLEXPORT Variable operator/(const Variable &lhs, const Variable &rhs)
Definition variable.hpp:150
Variable(std::integral auto value)
Definition variable.hpp:66
void set_value(double value)
Definition variable.hpp:101
Variable & operator/=(const Variable &rhs)
Definition variable.hpp:161
ExpressionType type() const
Definition variable.hpp:250
double value()
Definition variable.hpp:235
Variable(const detail::ExpressionPtr &expr)
Definition variable.hpp:74
Definition adjoint_expression_graph.hpp:21
Definition concepts.hpp:40
Definition concepts.hpp:13
Definition concepts.hpp:37
Definition variable.hpp:556
EqualityConstraints(std::initializer_list< EqualityConstraints > equality_constraints)
Definition variable.hpp:565
EqualityConstraints(const std::vector< EqualityConstraints > &equality_constraints)
Definition variable.hpp:580
EqualityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:601
small_vector< Variable > constraints
A vector of scalar equality constraints.
Definition variable.hpp:558
Definition variable.hpp:617
InequalityConstraints(const std::vector< InequalityConstraints > &inequality_constraints)
Definition variable.hpp:643
InequalityConstraints(std::initializer_list< InequalityConstraints > inequality_constraints)
Definition variable.hpp:627
small_vector< Variable > constraints
A vector of scalar inequality constraints.
Definition variable.hpp:619
InequalityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:664