7#include <initializer_list>
8#include <source_location>
13#include <gch/small_vector.hpp>
15#include "sleipnir/autodiff/expression.hpp"
16#include "sleipnir/autodiff/expression_graph.hpp"
17#include "sleipnir/autodiff/sleipnir_base.hpp"
18#include "sleipnir/util/assert.hpp"
19#include "sleipnir/util/concepts.hpp"
21#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
22#include "sleipnir/util/print.hpp"
31template <
typename Scalar>
32class GradientExpressionGraph;
36template <
typename Scalar,
int UpLo = Eigen::Lower | Eigen::Upper>
37 requires(UpLo == Eigen::Lower) || (UpLo == (Eigen::Lower | Eigen::Upper))
40template <
typename Scalar>
46template <
typename Scalar_>
64 : expr{detail::make_expression_ptr<detail::ConstantExpression<
Scalar>>(
72 slp_assert(
value.rows() == 1 &&
value.cols() == 1);
80 : expr{detail::make_expression_ptr<detail::ConstantExpression<
Scalar>>(
88 : expr{detail::make_expression_ptr<detail::ConstantExpression<
Scalar>>(
100 : expr{std::
move(expr)} {}
108 detail::make_expression_ptr<detail::ConstantExpression<Scalar>>(
value);
109 m_graph_initialized =
false;
118#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
121 if (expr->args[0] !=
nullptr) {
122 auto location = std::source_location::current();
125 "WARNING: {}:{}: {}: Modified the value of a dependent variable",
136 if (!m_graph_initialized) {
137 m_graph = detail::topological_sort(expr);
138 m_graph_initialized =
true;
140 detail::update_values(m_graph);
149 ExpressionType
type()
const {
return expr->type(); }
156 template <ScalarLike LHS, SleipnirScalarLike<Scalar> RHS>
166 template <SleipnirScalarLike<Scalar> LHS, ScalarLike RHS>
264 detail::make_expression_ptr<detail::DecisionVariableExpression<Scalar>>();
268 gch::small_vector<detail::Expression<Scalar>*> m_graph;
271 bool m_graph_initialized =
false;
273 template <
typename Scalar>
275 template <
typename Scalar>
277 template <
typename Scalar>
279 template <
typename Scalar>
281 template <
typename Scalar>
284 template <
typename Scalar>
287 template <
typename Scalar>
290 template <
typename Scalar>
292 template <
typename Scalar>
294 template <
typename Scalar>
296 template <
typename Scalar>
298 template <
typename Scalar>
300 template <
typename Scalar>
303 template <
typename Scalar>
306 template <
typename Scalar>
309 template <
typename Scalar>
311 template <
typename Scalar>
313 template <
typename Scalar>
316 template <
typename Scalar>
319 template <
typename Scalar>
322 template <
typename Scalar>
324 template <
typename Scalar>
326 template <
typename Scalar>
328 template <
typename Scalar>
330 template <
typename Scalar>
332 template <
typename Scalar>
334 template <
typename Scalar>
340 template <
typename Scalar,
int UpLo>
341 requires(
UpLo == Eigen::Lower) || (
UpLo == (Eigen::Lower | Eigen::Upper))
343 template <
typename Scalar>
347template <
template <
typename>
typename T,
typename Scalar>
348 requires SleipnirMatrixLike<T<Scalar>, Scalar>
349Variable(T<Scalar>) -> Variable<Scalar>;
351template <std::
floating_po
int T>
352Variable(T) -> Variable<T>;
354template <std::
integral T>
355Variable(T) -> Variable<T>;
361template <
typename Scalar>
362Variable<Scalar> abs(
const Variable<Scalar>& x) {
363 return Variable{detail::abs(x.expr)};
370template <
typename Scalar>
371Variable<Scalar> acos(
const Variable<Scalar>& x) {
372 return Variable{detail::acos(x.expr)};
379template <
typename Scalar>
380Variable<Scalar> asin(
const Variable<Scalar>& x) {
381 return Variable{detail::asin(x.expr)};
388template <
typename Scalar>
389Variable<Scalar> atan(
const Variable<Scalar>& x) {
390 return Variable{detail::atan(x.expr)};
398template <
typename Scalar>
399Variable<Scalar> atan2(
const ScalarLike
auto& y,
const Variable<Scalar>& x) {
400 return Variable{detail::atan2(Variable<Scalar>(y).expr, x.expr)};
408template <
typename Scalar>
409Variable<Scalar> atan2(
const Variable<Scalar>& y,
const ScalarLike
auto& x) {
410 return Variable{detail::atan2(y.expr, Variable<Scalar>(x).expr)};
418template <
typename Scalar>
419Variable<Scalar> atan2(
const Variable<Scalar>& y,
const Variable<Scalar>& x) {
420 return Variable{detail::atan2(y.expr, x.expr)};
427template <
typename Scalar>
428Variable<Scalar> cbrt(
const Variable<Scalar>& x) {
429 return Variable{detail::cbrt(x.expr)};
436template <
typename Scalar>
437Variable<Scalar> cos(
const Variable<Scalar>& x) {
438 return Variable{detail::cos(x.expr)};
445template <
typename Scalar>
446Variable<Scalar> cosh(
const Variable<Scalar>& x) {
447 return Variable{detail::cosh(x.expr)};
454template <
typename Scalar>
455Variable<Scalar> erf(
const Variable<Scalar>& x) {
456 return Variable{detail::erf(x.expr)};
463template <
typename Scalar>
464Variable<Scalar> exp(
const Variable<Scalar>& x) {
465 return Variable{detail::exp(x.expr)};
473template <
typename Scalar>
474Variable<Scalar> hypot(
const ScalarLike
auto& x,
const Variable<Scalar>& y) {
475 return Variable{detail::hypot(Variable<Scalar>(x).expr, y.expr)};
483template <
typename Scalar>
484Variable<Scalar> hypot(
const Variable<Scalar>& x,
const ScalarLike
auto& y) {
485 return Variable{detail::hypot(x.expr, Variable<Scalar>(y).expr)};
493template <
typename Scalar>
494Variable<Scalar> hypot(
const Variable<Scalar>& x,
const Variable<Scalar>& y) {
495 return Variable{detail::hypot(x.expr, y.expr)};
502template <
typename Scalar>
503Variable<Scalar> log(
const Variable<Scalar>& x) {
504 return Variable{detail::log(x.expr)};
511template <
typename Scalar>
512Variable<Scalar> log10(
const Variable<Scalar>& x) {
513 return Variable{detail::log10(x.expr)};
521template <
typename Scalar>
522Variable<Scalar> pow(
const ScalarLike
auto& base,
523 const Variable<Scalar>& power) {
524 return Variable{detail::pow(Variable<Scalar>(base).expr, power.expr)};
532template <
typename Scalar>
533Variable<Scalar> pow(
const Variable<Scalar>& base,
534 const ScalarLike
auto& power) {
535 return Variable{detail::pow(base.expr, Variable<Scalar>(power).expr)};
543template <
typename Scalar>
544Variable<Scalar> pow(
const Variable<Scalar>& base,
545 const Variable<Scalar>& power) {
546 return Variable{detail::pow(base.expr, power.expr)};
553template <
typename Scalar>
554Variable<Scalar> sign(
const Variable<Scalar>& x) {
555 return Variable{detail::sign(x.expr)};
562template <
typename Scalar>
563Variable<Scalar> sin(
const Variable<Scalar>& x) {
564 return Variable{detail::sin(x.expr)};
571template <
typename Scalar>
572Variable<Scalar> sinh(
const Variable<Scalar>& x) {
573 return Variable{detail::sinh(x.expr)};
580template <
typename Scalar>
581Variable<Scalar> sqrt(
const Variable<Scalar>& x) {
582 return Variable{detail::sqrt(x.expr)};
589template <
typename Scalar>
590Variable<Scalar> tan(
const Variable<Scalar>& x) {
591 return Variable{detail::tan(x.expr)};
598template <
typename Scalar>
599Variable<Scalar> tanh(
const Variable<Scalar>& x) {
600 return Variable{detail::tanh(x.expr)};
609template <
typename Scalar>
610Variable<Scalar> hypot(
const Variable<Scalar>& x,
const Variable<Scalar>& y,
611 const Variable<Scalar>& z) {
612 return Variable{sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2))};
620template <
typename Scalar, ScalarLike LHS, ScalarLike RHS>
621 requires SleipnirScalarLike<LHS, Scalar> || SleipnirScalarLike<RHS, Scalar>
622auto make_constraints(LHS&& lhs, RHS&& rhs) {
623 gch::small_vector<Variable<Scalar>> constraints;
624 constraints.emplace_back(lhs - rhs);
629template <
typename Scalar, ScalarLike LHS, MatrixLike RHS>
630 requires SleipnirScalarLike<LHS, Scalar> || SleipnirMatrixLike<RHS, Scalar>
631auto make_constraints(LHS&& lhs, RHS&& rhs) {
632 gch::small_vector<Variable<Scalar>> constraints;
633 constraints.reserve(rhs.rows() * rhs.cols());
635 for (
int row = 0; row < rhs.rows(); ++row) {
636 for (
int col = 0; col < rhs.cols(); ++col) {
638 constraints.emplace_back(lhs - rhs[row, col]);
645template <
typename Scalar, MatrixLike LHS, ScalarLike RHS>
646 requires SleipnirMatrixLike<LHS, Scalar> || SleipnirScalarLike<RHS, Scalar>
647auto make_constraints(LHS&& lhs, RHS&& rhs) {
648 gch::small_vector<Variable<Scalar>> constraints;
649 constraints.reserve(lhs.rows() * lhs.cols());
651 for (
int row = 0; row < lhs.rows(); ++row) {
652 for (
int col = 0; col < lhs.cols(); ++col) {
654 constraints.emplace_back(lhs[row, col] - rhs);
661template <
typename Scalar, MatrixLike LHS, MatrixLike RHS>
662 requires SleipnirMatrixLike<LHS, Scalar> || SleipnirMatrixLike<RHS, Scalar>
663auto make_constraints(LHS&& lhs, RHS&& rhs) {
664 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
666 gch::small_vector<Variable<Scalar>> constraints;
667 constraints.reserve(lhs.rows() * lhs.cols());
669 for (
int row = 0; row < lhs.rows(); ++row) {
670 for (
int col = 0; col < lhs.cols(); ++col) {
672 constraints.emplace_back(lhs[row, col] - rhs[row, col]);
682template <
typename Scalar>
695 elem.constraints.end());
709 elem.constraints.end());
720 template <
typename LHS,
typename RHS>
739template <
typename Scalar>
752 elem.constraints.end());
766 elem.constraints.end());
778 template <
typename LHS,
typename RHS>
798template <
typename LHS,
typename RHS>
799 requires(ScalarLike<LHS> || MatrixLike<LHS>) && SleipnirType<LHS> &&
800 (ScalarLike<RHS> || MatrixLike<RHS>) && (!SleipnirType<RHS>)
801auto operator==(LHS&& lhs, RHS&& rhs) {
802 return EqualityConstraints<typename std::decay_t<LHS>::Scalar>{lhs, rhs};
809template <
typename LHS,
typename RHS>
810 requires(ScalarLike<LHS> || MatrixLike<LHS>) && (!SleipnirType<LHS>) &&
811 (ScalarLike<RHS> || MatrixLike<RHS>) && SleipnirType<RHS>
812auto operator==(LHS&& lhs, RHS&& rhs) {
813 return EqualityConstraints<typename std::decay_t<RHS>::Scalar>{lhs, rhs};
820template <
typename LHS,
typename RHS>
821 requires(ScalarLike<LHS> || MatrixLike<LHS>) && SleipnirType<LHS> &&
822 (ScalarLike<RHS> || MatrixLike<RHS>) && SleipnirType<RHS>
823auto operator==(LHS&& lhs, RHS&& rhs) {
824 return EqualityConstraints<typename std::decay_t<LHS>::Scalar>{lhs, rhs};
832template <
typename LHS,
typename RHS>
833 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
834 (ScalarLike<RHS> || MatrixLike<RHS>) &&
835 (SleipnirType<LHS> || SleipnirType<RHS>)
836auto operator<(LHS&& lhs, RHS&& rhs) {
845template <
typename LHS,
typename RHS>
846 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
847 (ScalarLike<RHS> || MatrixLike<RHS>) &&
848 (SleipnirType<LHS> || SleipnirType<RHS>)
849auto operator<=(LHS&& lhs, RHS&& rhs) {
858template <
typename LHS,
typename RHS>
859 requires(ScalarLike<LHS> || MatrixLike<LHS>) &&
860 (ScalarLike<RHS> || MatrixLike<RHS>) &&
861 (SleipnirType<LHS> || SleipnirType<RHS>)
862auto operator>(LHS&& lhs, RHS&& rhs) {
871template <
typename LHS,
typename RHS>
872 requires(ScalarLike<LHS> || MatrixLike<LHS>) && SleipnirType<LHS> &&
873 (ScalarLike<RHS> || MatrixLike<RHS>) && (!SleipnirType<RHS>)
874auto operator>=(LHS&& lhs, RHS&& rhs) {
875 return InequalityConstraints<typename std::decay_t<LHS>::Scalar>{lhs, rhs};
883template <
typename LHS,
typename RHS>
884 requires(ScalarLike<LHS> || MatrixLike<LHS>) && (!SleipnirType<LHS>) &&
885 (ScalarLike<RHS> || MatrixLike<RHS>) && SleipnirType<RHS>
886auto operator>=(LHS&& lhs, RHS&& rhs) {
887 return InequalityConstraints<typename std::decay_t<RHS>::Scalar>{lhs, rhs};
895template <
typename LHS,
typename RHS>
896 requires(ScalarLike<LHS> || MatrixLike<LHS>) && SleipnirType<LHS> &&
897 (ScalarLike<RHS> || MatrixLike<RHS>) && SleipnirType<RHS>
898auto operator>=(LHS&& lhs, RHS&& rhs) {
899 return InequalityConstraints<typename std::decay_t<LHS>::Scalar>{lhs, rhs};
907template <
typename L,
typename X,
typename U>
908 requires(ScalarLike<L> || MatrixLike<L>) && SleipnirType<X> &&
909 (ScalarLike<U> || MatrixLike<U>)
910auto bounds(L&& l, X&& x, U&& u) {
911 return InequalityConstraints{l <= x, x <= u};
922template <
typename Scalar>
923struct NumTraits<slp::Variable<Scalar>> : NumTraits<Scalar> {
932 static constexpr int IsComplex = 0;
934 static constexpr int IsInteger = 0;
936 static constexpr int IsSigned = 1;
938 static constexpr int RequireInitialization = 1;
940 static constexpr int ReadCost = 1;
942 static constexpr int AddCost = 3;
944 static constexpr int MulCost = 3;
Definition hessian.hpp:28
Definition intrusive_shared_ptr.hpp:27
Definition jacobian.hpp:28
Definition sleipnir_base.hpp:9
Definition variable.hpp:47
ExpressionType type() const
Definition variable.hpp:149
friend Variable< Scalar > operator*(const LHS &lhs, const RHS &rhs)
Definition variable.hpp:157
Variable(const detail::ExpressionPtr< Scalar > &expr)
Definition variable.hpp:94
Variable< Scalar > & operator/=(const Variable< Scalar > &rhs)
Definition variable.hpp:204
Variable< Scalar > & operator*=(const Variable< Scalar > &rhs)
Definition variable.hpp:185
friend Variable< Scalar > operator+(const Variable< Scalar > &lhs, const Variable< Scalar > &rhs)
Definition variable.hpp:214
void set_value(Scalar value)
Definition variable.hpp:117
friend Variable< Scalar > operator/(const Variable< Scalar > &lhs, const Variable< Scalar > &rhs)
Definition variable.hpp:195
Variable(std::floating_point auto value)
Definition variable.hpp:79
constexpr Variable(detail::ExpressionPtr< Scalar > &&expr)
Definition variable.hpp:99
friend Variable< Scalar > operator+(const Variable< Scalar > &lhs)
Definition variable.hpp:257
Variable(Scalar value)
Definition variable.hpp:62
constexpr Variable(std::nullptr_t)
Constructs an empty Variable.
Definition variable.hpp:56
Variable< Scalar > & operator=(ScalarLike auto value)
Definition variable.hpp:106
Variable()=default
Constructs a linear Variable with a value of zero.
friend Variable< Scalar > operator-(const Variable< Scalar > &lhs)
Definition variable.hpp:250
friend Variable< Scalar > operator*(const Variable< Scalar > &lhs, const Variable< Scalar > &rhs)
Definition variable.hpp:176
Variable(std::integral auto value)
Definition variable.hpp:87
Variable(SleipnirMatrixLike< Scalar > auto value)
Definition variable.hpp:71
Variable< Scalar > & operator+=(const Variable< Scalar > &rhs)
Definition variable.hpp:223
Scalar_ Scalar
Scalar type alias.
Definition variable.hpp:50
Scalar value()
Definition variable.hpp:135
Variable< Scalar > & operator-=(const Variable< Scalar > &rhs)
Definition variable.hpp:242
friend Variable< Scalar > operator-(const Variable< Scalar > &lhs, const Variable< Scalar > &rhs)
Definition variable.hpp:233
Definition gradient_expression_graph.hpp:25
Definition concepts.hpp:18
Definition concepts.hpp:24
Definition concepts.hpp:33
Definition concepts.hpp:15
Definition variable.hpp:683
EqualityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:724
EqualityConstraints(std::initializer_list< EqualityConstraints > equality_constraints)
Definition variable.hpp:691
gch::small_vector< Variable< Scalar > > constraints
A vector of scalar equality constraints.
Definition variable.hpp:685
EqualityConstraints(const std::vector< EqualityConstraints > &equality_constraints)
Definition variable.hpp:705
Definition variable.hpp:740
gch::small_vector< Variable< Scalar > > constraints
A vector of scalar inequality constraints.
Definition variable.hpp:742
InequalityConstraints(LHS &&lhs, RHS &&rhs)
Definition variable.hpp:782
InequalityConstraints(const std::vector< InequalityConstraints > &inequality_constraints)
Definition variable.hpp:762
InequalityConstraints(std::initializer_list< InequalityConstraints > inequality_constraints)
Definition variable.hpp:748