forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
symbolic_monomial.h
158 lines (127 loc) · 4.98 KB
/
symbolic_monomial.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#pragma once
#ifndef DRAKE_COMMON_SYMBOLIC_HEADER
// TODO(soonho-tri): Change to #error, when #6613 merged.
#warning Do not directly include this file. Include "drake/common/symbolic.h".
#endif
#include <cstddef>
#include <map>
#include <ostream>
#include <utility>
#include <Eigen/Core>
#include "drake/common/drake_copyable.h"
#include "drake/common/hash.h"
#include "drake/common/symbolic.h"
namespace drake {
namespace symbolic {
/** Represents a monomial, a product of powers of variables with non-negative
* integer exponents. Note that it does not include the coefficient part of a
* monomial.
*/
class Monomial {
public:
DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(Monomial)
/** Constructs a monomial equal to 1. Namely the total degree is zero. */
Monomial() = default;
/** Constructs a Monomial from @p powers. */
explicit Monomial(const std::map<Variable, int>& powers);
/**
* Converts an expression to a monomial if the expression is written as
* ∏ᵢpow(xᵢ, kᵢ), otherwise throws a runtime error.
* @pre is_polynomial(e) should be true.
*/
explicit Monomial(const Expression& e);
/** Constructs a Monomial from @p var. */
explicit Monomial(const Variable& var);
/** Constructs a Monomial from @p var and @exponent. */
Monomial(const Variable& var, int exponent);
/** Returns the degree of this Monomial in a variable @p v. */
int degree(const Variable& v) const;
/** Returns the total degree of this Monomial. */
int total_degree() const { return total_degree_; }
/** Returns the set of variables in this monomial. */
Variables GetVariables() const;
/** Returns the internal representation of Monomial, the map from a base
* (Variable) to its exponent (int).*/
const std::map<Variable, int>& get_powers() const { return powers_; }
/** Evaluates under a given environment @p env.
*
* @throws std::out_of_range exception if there is a variable in this monomial
* whose assignment is not provided by @p env.
*/
double Evaluate(const Environment& env) const;
/** Partially evaluates using a given environment @p env. The evaluation
* result is of type pair<double, Monomial>. The first component (: double)
* represents the coefficient part while the second component represents the
* remaining parts of the Monomial which was not evaluated.
*
* Example 1. Evaluate with a fully-specified environment
* (x³*y²).EvaluatePartial({{x, 2}, {y, 3}})
* = (2³ * 3² = 8 * 9 = 72, Monomial{} = 1).
*
* Example 2. Evaluate with a partial environment
* (x³*y²).EvaluatePartial({{x, 2}})
* = (2³ = 8, y²).
*/
std::pair<double, Monomial> EvaluatePartial(const Environment& env) const;
/** Returns a symbolic expression representing this monomial. */
Expression ToExpression() const;
/** Checks if this monomial and @p m represent the same monomial. Two
* monomials are equal iff they contain the same variable raised to the same
* exponent. */
bool operator==(const Monomial& m) const;
/** Checks if this monomial and @p m do not represent the same monomial. */
bool operator!=(const Monomial& m) const;
/** Returns this monomial multiplied by @p m. */
Monomial& operator*=(const Monomial& m);
/** Returns this monomial raised to @p p.
* @throws std::runtime_error if @p p is negative.
*/
Monomial& pow_in_place(int p);
/** Implements the @ref hash_append concept. */
template <class HashAlgorithm>
friend void hash_append(
HashAlgorithm& hasher, const Monomial& item) noexcept {
using drake::hash_append;
// We do not send total_degree_ to the hasher, because it is already fully
// represented by powers_ -- it is just a cached tally of the exponents.
hash_append(hasher, item.powers_);
}
private:
int total_degree_{0};
std::map<Variable, int> powers_;
friend std::ostream& operator<<(std::ostream& out, const Monomial& m);
};
std::ostream& operator<<(std::ostream& out, const Monomial& m);
/** Returns a multiplication of two monomials, @p m1 and @p m2. */
Monomial operator*(Monomial m1, const Monomial& m2);
/** Returns @p m1 raised to @p p.
* @throws std::runtime_error if @p p is negative.
*/
Monomial pow(Monomial m, int p);
} // namespace symbolic
} // namespace drake
namespace std {
/* Provides std::hash<drake::symbolic::Monomial>. */
template <>
struct hash<drake::symbolic::Monomial>
: public drake::DefaultHash {};
} // namespace std
#if !defined(DRAKE_DOXYGEN_CXX)
namespace Eigen {
// Eigen scalar type traits for Matrix<drake::symbolic::Monomial>.
template <>
struct NumTraits<drake::symbolic::Monomial>
: GenericNumTraits<drake::symbolic::Monomial> {
static inline int digits10() { return 0; }
};
namespace internal {
// Informs Eigen how to cast drake::symbolic::Monomial to
// drake::symbolic::Expression.
template <>
EIGEN_DEVICE_FUNC inline drake::symbolic::Expression cast(
const drake::symbolic::Monomial& m) {
return m.ToExpression();
}
} // namespace internal
} // namespace Eigen
#endif // !defined(DRAKE_DOXYGEN_CXX)