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>
494 (!std::same_as<std::decay_t<LHS>,
double> ||
495 !std::same_as<std::decay_t<RHS>,
double>)
496small_vector<Variable> make_constraints(LHS&& lhs, RHS&& rhs) {
497 small_vector<Variable> constraints;
500 constraints.emplace_back(lhs - rhs);
501 }
else if constexpr (ScalarLike<LHS> && MatrixLike<RHS>) {
502 constraints.reserve(rhs.rows() * rhs.cols());
504 for (
int row = 0; row < rhs.rows(); ++row) {
505 for (
int col = 0; col < rhs.cols(); ++col) {
507 constraints.emplace_back(lhs - rhs(row, col));
510 }
else if constexpr (MatrixLike<LHS> && ScalarLike<RHS>) {
511 constraints.reserve(lhs.rows() * lhs.cols());
513 for (
int row = 0; row < lhs.rows(); ++row) {
514 for (
int col = 0; col < lhs.cols(); ++col) {
516 constraints.emplace_back(lhs(row, col) - rhs);
519 }
else if constexpr (MatrixLike<LHS> && MatrixLike<RHS>) {
520 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
521 constraints.reserve(lhs.rows() * lhs.cols());
523 for (
int row = 0; row < lhs.rows(); ++row) {
524 for (
int col = 0; col < lhs.cols(); ++col) {
526 constraints.emplace_back(lhs(row, col) - rhs(row, col));
547 std::initializer_list<EqualityConstraints> equality_constraints) {
548 for (
const auto& elem : equality_constraints) {
549 constraints.insert(constraints.end(), elem.constraints.begin(),
550 elem.constraints.end());
562 const std::vector<EqualityConstraints>& equality_constraints) {
563 for (
const auto& elem : equality_constraints) {
564 constraints.insert(constraints.end(), elem.constraints.begin(),
565 elem.constraints.end());
578 template <
typename LHS,
typename RHS>
581 (!std::same_as<std::decay_t<LHS>,
double> ||
582 !std::same_as<std::decay_t<RHS>,
double>)
584 : constraints{make_constraints(lhs, rhs)} {}
590 return std::ranges::all_of(constraints, [](
auto& constraint) {
591 return constraint.value() == 0.0;
610 std::initializer_list<InequalityConstraints> inequality_constraints) {
611 for (
const auto& elem : inequality_constraints) {
612 constraints.insert(constraints.end(), elem.constraints.begin(),
613 elem.constraints.end());
626 const std::vector<InequalityConstraints>& inequality_constraints) {
627 for (
const auto& elem : inequality_constraints) {
628 constraints.insert(constraints.end(), elem.constraints.begin(),
629 elem.constraints.end());
642 template <
typename LHS,
typename RHS>
645 (!std::same_as<std::decay_t<LHS>,
double> ||
646 !std::same_as<std::decay_t<RHS>,
double>)
648 : constraints{make_constraints(lhs, rhs)} {}
654 return std::ranges::all_of(constraints, [](
auto& constraint) {
655 return constraint.value() >= 0.0;
666template <
typename LHS,
typename RHS>
667 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
668 (ScalarLike<RHS> || MatrixLike<RHS>) &&
669 (!std::same_as<std::decay_t<LHS>,
double> ||
670 !std::same_as<std::decay_t<RHS>,
double>)
671EqualityConstraints
operator==(LHS&& lhs, RHS&& rhs) {
672 return EqualityConstraints{lhs, rhs};
682template <
typename LHS,
typename RHS>
683 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
684 (ScalarLike<RHS> || MatrixLike<RHS>) &&
685 (!std::same_as<std::decay_t<LHS>,
double> ||
686 !std::same_as<std::decay_t<RHS>,
double>)
687InequalityConstraints
operator<(LHS&& lhs, RHS&& rhs) {
698template <
typename LHS,
typename RHS>
699 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
700 (ScalarLike<RHS> || MatrixLike<RHS>) &&
701 (!std::same_as<std::decay_t<LHS>,
double> ||
702 !std::same_as<std::decay_t<RHS>,
double>)
703InequalityConstraints
operator<=(LHS&& lhs, RHS&& rhs) {
714template <
typename LHS,
typename RHS>
715 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
716 (ScalarLike<RHS> || MatrixLike<RHS>) &&
717 (!std::same_as<std::decay_t<LHS>,
double> ||
718 !std::same_as<std::decay_t<RHS>,
double>)
719InequalityConstraints
operator>(LHS&& lhs, RHS&& rhs) {
730template <
typename LHS,
typename RHS>
731 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
732 (ScalarLike<RHS> || MatrixLike<RHS>) &&
733 (!std::same_as<std::decay_t<LHS>,
double> ||
734 !std::same_as<std::decay_t<RHS>,
double>)
735InequalityConstraints
operator>=(LHS&& lhs, RHS&& rhs) {
736 return InequalityConstraints{lhs, rhs};
747struct NumTraits<slp::Variable> : NumTraits<double> {
756 static constexpr int IsComplex = 0;
758 static constexpr int IsInteger = 0;
760 static constexpr int IsSigned = 1;
762 static constexpr int RequireInitialization = 1;
764 static constexpr int ReadCost = 1;
766 static constexpr int AddCost = 3;
768 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:29
Definition concepts.hpp:13
Definition variable.hpp:537
EqualityConstraints(std::initializer_list< EqualityConstraints > equality_constraints)
Definition variable.hpp:546
EqualityConstraints(const std::vector< EqualityConstraints > &equality_constraints)
Definition variable.hpp:561
EqualityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:583
small_vector< Variable > constraints
A vector of scalar equality constraints.
Definition variable.hpp:539
Definition variable.hpp:599
InequalityConstraints(const std::vector< InequalityConstraints > &inequality_constraints)
Definition variable.hpp:625
InequalityConstraints(std::initializer_list< InequalityConstraints > inequality_constraints)
Definition variable.hpp:609
small_vector< Variable > constraints
A vector of scalar inequality constraints.
Definition variable.hpp:601
InequalityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:647