7#include <initializer_list>
8#include <source_location>
15#include "sleipnir/autodiff/expression.hpp"
16#include "sleipnir/autodiff/expression_graph.hpp"
17#include "sleipnir/util/assert.hpp"
18#include "sleipnir/util/concepts.hpp"
19#include "sleipnir/util/small_vector.hpp"
20#include "sleipnir/util/symbol_exports.hpp"
22#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
23#include "sleipnir/util/print.hpp"
30class AdjointExpressionGraph;
32template <
int UpLo = Eigen::Lower | Eigen::Upper>
33 requires(UpLo == Eigen::Lower) || (UpLo == (Eigen::Lower | Eigen::Upper))
34class SLEIPNIR_DLLEXPORT Hessian;
35class SLEIPNIR_DLLEXPORT Jacobian;
50 explicit constexpr Variable(std::nullptr_t) : expr{nullptr} {}
58 : expr{detail::make_expression_ptr<detail::ConstExpression>(value)} {}
66 : expr{detail::make_expression_ptr<detail::ConstExpression>(value)} {}
81 : expr{std::move(expr)} {}
90 expr = detail::make_expression_ptr<detail::ConstExpression>(value);
101 if (expr->is_constant(0.0)) {
102 expr = detail::make_expression_ptr<detail::ConstExpression>(value);
104#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
107 if (expr->args[0] !=
nullptr) {
108 auto location = std::source_location::current();
111 "WARNING: {}:{}: {}: Modified the value of a dependent variable",
112 location.file_name(), location.line(), location.function_name());
128 return Variable{lhs.expr * rhs.expr};
151 return Variable{lhs.expr / rhs.expr};
174 return Variable{lhs.expr + rhs.expr};
197 return Variable{lhs.expr - rhs.expr};
235 if (!m_graph_initialized) {
236 m_graph = detail::topological_sort(expr);
237 m_graph_initialized =
true;
239 detail::update_values(m_graph);
250 ExpressionType
type()
const {
return expr->type(); }
255 detail::make_expression_ptr<detail::DecisionVariableExpression>();
259 small_vector<detail::Expression*> m_graph;
262 bool m_graph_initialized =
false;
291 requires(UpLo == Eigen::Lower) || (UpLo == (Eigen::Lower | Eigen::Upper))
292 friend class SLEIPNIR_DLLEXPORT
Hessian;
293 friend class SLEIPNIR_DLLEXPORT
Jacobian;
302 return Variable{detail::abs(x.expr)};
311 return Variable{detail::acos(x.expr)};
320 return Variable{detail::asin(x.expr)};
329 return Variable{detail::atan(x.expr)};
339 return Variable{detail::atan2(y.expr, x.expr)};
348 return Variable{detail::cos(x.expr)};
357 return Variable{detail::cosh(x.expr)};
366 return Variable{detail::erf(x.expr)};
375 return Variable{detail::exp(x.expr)};
385 return Variable{detail::hypot(x.expr, y.expr)};
396 return Variable{detail::pow(base.expr, power.expr)};
405 return Variable{detail::log(x.expr)};
414 return Variable{detail::log10(x.expr)};
423 return Variable{detail::sign(x.expr)};
432 return Variable{detail::sin(x.expr)};
441 return Variable{detail::sinh(x.expr)};
450 return Variable{detail::sqrt(x.expr)};
459 return Variable{detail::tan(x.expr)};
468 return Variable{detail::tanh(x.expr)};
480 return Variable{slp::sqrt(slp::pow(x, 2) + slp::pow(y, 2) + slp::pow(z, 2))};
494template <
typename LHS,
typename RHS>
498small_vector<Variable> make_constraints(LHS&& lhs, RHS&& rhs) {
499 small_vector<Variable> constraints;
502 constraints.emplace_back(lhs - rhs);
503 }
else if constexpr (ScalarLike<LHS> && MatrixLike<RHS>) {
504 constraints.reserve(rhs.rows() * rhs.cols());
506 for (
int row = 0; row < rhs.rows(); ++row) {
507 for (
int col = 0; col < rhs.cols(); ++col) {
509 if constexpr (EigenMatrixLike<std::decay_t<RHS>>) {
510 constraints.emplace_back(lhs - rhs(row, col));
512 constraints.emplace_back(lhs - rhs[row, col]);
516 }
else if constexpr (MatrixLike<LHS> && ScalarLike<RHS>) {
517 constraints.reserve(lhs.rows() * lhs.cols());
519 for (
int row = 0; row < lhs.rows(); ++row) {
520 for (
int col = 0; col < lhs.cols(); ++col) {
522 if constexpr (EigenMatrixLike<std::decay_t<LHS>>) {
523 constraints.emplace_back(lhs(row, col) - rhs);
525 constraints.emplace_back(lhs[row, col] - rhs);
529 }
else if constexpr (MatrixLike<LHS> && MatrixLike<RHS>) {
530 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
531 constraints.reserve(lhs.rows() * lhs.cols());
533 for (
int row = 0; row < lhs.rows(); ++row) {
534 for (
int col = 0; col < lhs.cols(); ++col) {
536 if constexpr (EigenMatrixLike<std::decay_t<LHS>> &&
537 EigenMatrixLike<std::decay_t<RHS>>) {
538 constraints.emplace_back(lhs(row, col) - rhs(row, col));
539 }
else if constexpr (EigenMatrixLike<std::decay_t<LHS>> &&
540 SleipnirMatrixLike<std::decay_t<RHS>>) {
541 constraints.emplace_back(lhs(row, col) - rhs[row, col]);
542 }
else if constexpr (SleipnirMatrixLike<std::decay_t<LHS>> &&
543 EigenMatrixLike<std::decay_t<RHS>>) {
544 constraints.emplace_back(lhs[row, col] - rhs(row, col));
545 }
else if constexpr (SleipnirMatrixLike<std::decay_t<LHS>> &&
546 SleipnirMatrixLike<std::decay_t<RHS>>) {
547 constraints.emplace_back(lhs[row, col] - rhs[row, col]);
569 std::initializer_list<EqualityConstraints> equality_constraints) {
570 for (
const auto& elem : equality_constraints) {
571 constraints.insert(constraints.end(), elem.constraints.begin(),
572 elem.constraints.end());
584 const std::vector<EqualityConstraints>& equality_constraints) {
585 for (
const auto& elem : equality_constraints) {
586 constraints.insert(constraints.end(), elem.constraints.begin(),
587 elem.constraints.end());
600 template <
typename LHS,
typename RHS>
605 : constraints{make_constraints(lhs, rhs)} {}
611 return std::ranges::all_of(constraints, [](
auto& constraint) {
612 return constraint.value() == 0.0;
631 std::initializer_list<InequalityConstraints> inequality_constraints) {
632 for (
const auto& elem : inequality_constraints) {
633 constraints.insert(constraints.end(), elem.constraints.begin(),
634 elem.constraints.end());
647 const std::vector<InequalityConstraints>& inequality_constraints) {
648 for (
const auto& elem : inequality_constraints) {
649 constraints.insert(constraints.end(), elem.constraints.begin(),
650 elem.constraints.end());
663 template <
typename LHS,
typename RHS>
668 : constraints{make_constraints(lhs, rhs)} {}
674 return std::ranges::all_of(constraints, [](
auto& constraint) {
675 return constraint.value() >= 0.0;
686template <
typename LHS,
typename RHS>
687 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
688 (ScalarLike<RHS> || MatrixLike<RHS>) &&
689 (SleipnirType<LHS> || SleipnirType<RHS>)
690EqualityConstraints
operator==(LHS&& lhs, RHS&& rhs) {
691 return EqualityConstraints{lhs, rhs};
701template <
typename LHS,
typename RHS>
702 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
703 (ScalarLike<RHS> || MatrixLike<RHS>) &&
704 (SleipnirType<LHS> || SleipnirType<RHS>)
705InequalityConstraints
operator<(LHS&& lhs, RHS&& rhs) {
716template <
typename LHS,
typename RHS>
717 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
718 (ScalarLike<RHS> || MatrixLike<RHS>) &&
719 (SleipnirType<LHS> || SleipnirType<RHS>)
720InequalityConstraints
operator<=(LHS&& lhs, RHS&& rhs) {
731template <
typename LHS,
typename RHS>
732 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
733 (ScalarLike<RHS> || MatrixLike<RHS>) &&
734 (SleipnirType<LHS> || SleipnirType<RHS>)
735InequalityConstraints
operator>(LHS&& lhs, RHS&& rhs) {
746template <
typename LHS,
typename RHS>
747 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
748 (ScalarLike<RHS> || MatrixLike<RHS>) &&
749 (SleipnirType<LHS> || SleipnirType<RHS>)
750InequalityConstraints
operator>=(LHS&& lhs, RHS&& rhs) {
751 return InequalityConstraints{lhs, rhs};
762struct NumTraits<slp::Variable> : NumTraits<double> {
771 static constexpr int IsComplex = 0;
773 static constexpr int IsInteger = 0;
775 static constexpr int IsSigned = 1;
777 static constexpr int RequireInitialization = 1;
779 static constexpr int ReadCost = 1;
781 static constexpr int AddCost = 3;
783 static constexpr int MulCost = 3;
Definition hessian.hpp:29
Definition jacobian.hpp:25
Definition variable.hpp:40
friend SLEIPNIR_DLLEXPORT Variable operator+(const Variable &lhs)
Definition variable.hpp:225
constexpr Variable(detail::ExpressionPtr &&expr)
Definition variable.hpp:80
friend SLEIPNIR_DLLEXPORT Variable operator*(const Variable &lhs, const Variable &rhs)
Definition variable.hpp:126
Variable & operator=(double value)
Definition variable.hpp:89
Variable & operator-=(const Variable &rhs)
Definition variable.hpp:206
friend SLEIPNIR_DLLEXPORT Variable operator-(const Variable &lhs)
Definition variable.hpp:216
friend SLEIPNIR_DLLEXPORT Variable operator+(const Variable &lhs, const Variable &rhs)
Definition variable.hpp:172
Variable & operator+=(const Variable &rhs)
Definition variable.hpp:183
friend SLEIPNIR_DLLEXPORT Variable operator-(const Variable &lhs, const Variable &rhs)
Definition variable.hpp:195
Variable & operator*=(const Variable &rhs)
Definition variable.hpp:137
Variable(std::floating_point auto value)
Definition variable.hpp:57
constexpr Variable(std::nullptr_t)
Definition variable.hpp:50
friend SLEIPNIR_DLLEXPORT Variable operator/(const Variable &lhs, const Variable &rhs)
Definition variable.hpp:149
Variable(std::integral auto value)
Definition variable.hpp:65
void set_value(double value)
Definition variable.hpp:100
Variable & operator/=(const Variable &rhs)
Definition variable.hpp:160
ExpressionType type() const
Definition variable.hpp:250
double value()
Definition variable.hpp:234
Variable(const detail::ExpressionPtr &expr)
Definition variable.hpp:73
Definition adjoint_expression_graph.hpp:21
Definition concepts.hpp:40
Definition concepts.hpp:13
Definition concepts.hpp:37
Definition variable.hpp:559
EqualityConstraints(std::initializer_list< EqualityConstraints > equality_constraints)
Definition variable.hpp:568
EqualityConstraints(const std::vector< EqualityConstraints > &equality_constraints)
Definition variable.hpp:583
EqualityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:604
small_vector< Variable > constraints
A vector of scalar equality constraints.
Definition variable.hpp:561
Definition variable.hpp:620
InequalityConstraints(const std::vector< InequalityConstraints > &inequality_constraints)
Definition variable.hpp:646
InequalityConstraints(std::initializer_list< InequalityConstraints > inequality_constraints)
Definition variable.hpp:630
small_vector< Variable > constraints
A vector of scalar inequality constraints.
Definition variable.hpp:622
InequalityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:667