forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsymbolic_environment.h
159 lines (137 loc) · 5.69 KB
/
symbolic_environment.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
159
#pragma once
#ifndef DRAKE_COMMON_SYMBOLIC_HEADER
#error Do not directly include this file. Include "drake/common/symbolic.h".
#endif
#include <initializer_list>
#include <ostream>
#include <string>
#include <unordered_map>
#include "drake/common/drake_copyable.h"
#include "drake/common/eigen_types.h"
#include "drake/common/random.h"
#include "drake/common/symbolic.h"
namespace drake {
namespace symbolic {
/** Represents a symbolic environment (mapping from a variable to a value).
*
* This class is used when we evaluate symbolic expressions or formulas which
* include unquantified (free) variables. Here are examples:
*
* \code{.cpp}
* const Variable var_x{"x"};
* const Variable var_y{"y"};
* const Expression x{var_x};
* const Expression y{var_x};
* const Expression e1{x + y};
* const Expression e2{x - y};
* const Formula f{e1 > e2};
*
* // env maps var_x to 2.0 and var_y to 3.0
* const Environment env{{var_x, 2.0}, {var_y, 3.0}};
*
* const double res1 = e1.Evaluate(env); // x + y => 2.0 + 3.0 => 5.0
* const double res2 = e2.Evaluate(env); // x - y => 2.0 - 3.0 => -1.0
* const bool res = f.Evaluate(env); // x + y > x - y => 5.0 >= -1.0 => True
* \endcode
*
* Note that it is not allowed to have a dummy variable in an environment. It
* throws std::runtime_error for the attempts to create an environment with a
* dummy variable, to insert a dummy variable to an existing environment, or to
* take a reference to a value mapped to a dummy variable. See the following
* examples.
*
* \code{.cpp}
* Variable var_dummy{}; // OK to have a dummy variable
* Environment e1{var_dummy}; // throws std::runtime_error exception
* Environment e2{{var_dummy, 1.0}}; // throws std::runtime_error exception
* Environment e{};
* e.insert(var_dummy, 1.0); // throws std::runtime_error exception
* e[var_dummy] = 3.0; // throws std::runtime_error exception
* \endcode
*
*/
class Environment {
public:
DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(Environment)
typedef Variable key_type;
typedef double mapped_type;
typedef typename std::unordered_map<key_type, mapped_type> map;
/** std::pair<key_type, mapped_type> */
typedef typename map::value_type value_type;
typedef typename map::iterator iterator;
typedef typename map::const_iterator const_iterator;
/** Default constructor. */
Environment() = default;
/** List constructor. Constructs an environment from a list of (Variable *
* double).
*
* @throws std::runtime_error if @p init include a dummy variable or a NaN
* value.
*/
Environment(std::initializer_list<value_type> init);
/** List constructor. Constructs an environment from a list of
* Variable. Initializes the variables with 0.0.
*
* @throws std::runtime_error if @p vars include a dummy variable.
*/
Environment(std::initializer_list<key_type> vars);
/** Constructs an environment from @p m (of `map` type, which is
* `std::unordered_map`).
*
* @throws std::runtime_error if @p m include a dummy variable or a NaN value.
*/
explicit Environment(map m);
/** Returns an iterator to the beginning. */
iterator begin() { return map_.begin(); }
/** Returns an iterator to the end. */
iterator end() { return map_.end(); }
/** Returns a const iterator to the beginning. */
[[nodiscard]] const_iterator begin() const { return map_.cbegin(); }
/** Returns a const iterator to the end. */
[[nodiscard]] const_iterator end() const { return map_.cend(); }
/** Returns a const iterator to the beginning. */
[[nodiscard]] const_iterator cbegin() const { return map_.cbegin(); }
/** Returns a const iterator to the end. */
[[nodiscard]] const_iterator cend() const { return map_.cend(); }
/** Inserts a pair (@p key, @p elem). */
void insert(const key_type& key, const mapped_type& elem);
/** Given a matrix of symbolic variables @p keys and a matrix of values @p
* elements, inserts each pair (keys(i, j), elements(i, j)) into the
* environment.
*
* @throw std::runtime_error if the size of @p keys is different from the size
* of @p elements.
*/
void insert(const Eigen::Ref<const MatrixX<key_type>>& keys,
const Eigen::Ref<const MatrixX<mapped_type>>& elements);
/** Checks whether the container is empty. */
[[nodiscard]] bool empty() const { return map_.empty(); }
/** Returns the number of elements. */
[[nodiscard]] size_t size() const { return map_.size(); }
/** Finds element with specific key. */
iterator find(const key_type& key) { return map_.find(key); }
/** Finds element with specific key. */
[[nodiscard]] const_iterator find(const key_type& key) const {
return map_.find(key);
}
/** Returns the domain of this environment. */
[[nodiscard]] Variables domain() const;
/** Returns string representation. */
[[nodiscard]] std::string to_string() const;
/** Returns a reference to the value that is mapped to a key equivalent to
* @p key, performing an insertion if such key does not already exist.
*/
mapped_type& operator[](const key_type& key);
/** As above, but returns a constref and does not perform an insertion
* (throwing a runtime error instead) if the key does not exist. */
const mapped_type& operator[](const key_type& key) const;
friend std::ostream& operator<<(std::ostream& os, const Environment& env);
private:
map map_;
};
/** Populates the environment @p env by sampling values for the unassigned
* random variables in @p variables using @p random_generator. */
Environment PopulateRandomVariables(Environment env, const Variables& variables,
RandomGenerator* random_generator);
} // namespace symbolic
} // namespace drake