dReal4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
symbolic_formula.h
1 
2 #pragma once
3 
4 #include <functional>
5 #include <ostream>
6 #include <set>
7 #include <string>
8 #include <utility>
9 
10 #include "dreal/symbolic/hash.h"
11 #include "dreal/symbolic/symbolic_environment.h"
12 #include "dreal/symbolic/symbolic_expression.h"
13 #include "dreal/symbolic/symbolic_variable.h"
14 #include "dreal/symbolic/symbolic_variables.h"
15 
16 namespace dreal {
17 namespace drake {
18 namespace symbolic {
19 
20 /** Kinds of symbolic formulas. */
21 enum class FormulaKind {
22  False, ///< ⊥
23  True, ///< ⊤
24  Var, ///< Boolean Variable
25  Eq, ///< =
26  Neq, ///< !=
27  Gt, ///< >
28  Geq, ///< >=
29  Lt, ///< <
30  Leq, ///< <=
31  And, ///< Conjunction (∧)
32  Or, ///< Disjunction (∨)
33  Not, ///< Negation (¬)
34  Forall, ///< Universal quantification (∀)
35 };
36 
37 // Total ordering between FormulaKinds
38 bool operator<(FormulaKind k1, FormulaKind k2);
39 
40 class FormulaCell; // In symbolic/symbolic_formula_cell.h
41 class FormulaFalse; // In symbolic/symbolic_formula_cell.h
42 class FormulaTrue; // In symbolic/symbolic_formula_cell.h
43 class FormulaVar; // In symbolic/symbolic_formula_cell.h
44 class RelationalFormulaCell; // In symbolic/symbolic_formula_cell.h
45 class FormulaEq; // In symbolic/symbolic_formula_cell.h
46 class FormulaNeq; // In symbolic/symbolic_formula_cell.h
47 class FormulaGt; // In symbolic/symbolic_formula_cell.h
48 class FormulaGeq; // In symbolic/symbolic_formula_cell.h
49 class FormulaLt; // In symbolic/symbolic_formula_cell.h
50 class FormulaLeq; // In symbolic/symbolic_formula_cell.h
51 class NaryFormulaCell; // In symbolic/symbolic_formula_cell.h
52 class FormulaNot; // In symbolic/symbolic_formula_cell.h
53 class FormulaAnd; // In symbolic/symbolic_formula_cell.h
54 class FormulaOr; // In symbolic/symbolic_formula_cell.h
55 class FormulaForall; // In symbolic/symbolic_formula_cell.h
56 
57 /** Represents a symbolic form of a first-order logic formula.
58 
59 It has the following grammar:
60 
61 \verbatim
62  F := ⊥ | ⊤ | Var | E = E | E ≠ E | E > E | E ≥ E | E < E | E ≤ E
63  | E ∧ ... ∧ E | E ∨ ... ∨ E | ¬F | ∀ x₁, ..., xn. F
64 \endverbatim
65 
66 In the implementation, Formula is a simple wrapper including a raw
67 pointer to FormulaCell class which is a super-class of different kinds
68 of symbolic formulas (i.e. FormulaAnd, FormulaOr, FormulaEq).
69 
70 \note The sharing of sub-expressions is not yet implemented.
71 
72 The following simple simplifications are implemented:
73 \verbatim
74  E1 = E2 -> True (if E1 and E2 are structurally equal)
75  E1 ≠ E2 -> False (if E1 and E2 are structurally equal)
76  E1 > E2 -> False (if E1 and E2 are structurally equal)
77  E1 ≥ E2 -> True (if E1 and E2 are structurally equal)
78  E1 < E2 -> False (if E1 and E2 are structurally equal)
79  E1 ≤ E2 -> True (if E1 and E2 are structurally equal)
80  F1 ∧ F2 -> False (if either F1 or F2 is False)
81  F1 ∨ F2 -> True (if either F1 or F2 is True)
82  ¬(¬(F)) -> F
83 \endverbatim
84 
85 We flatten nested conjunctions (or disjunctions) at the construction. A
86 conjunction (resp. disjunction) takes a set of conjuncts (resp. disjuncts). Note
87 that any duplicated conjunct/disjunct is removed. For example, both of `f1 &&
88 (f2 && f1)` and `(f1 && f2) && f1` are flattened to `f1 && f2 && f1` and
89 simplified into `f1 && f2`. As a result, the two are identified as the same
90 formula.
91 
92 \note Formula class has an explicit conversion operator to bool. It evaluates a
93 symbolic formula under an empty environment. If a symbolic formula includes
94 variables, the conversion operator throws an exception. This operator is only
95 intended for third-party code doing things like `(imag(SymbolicExpression(0))
96 == SymbolicExpression(0)) { ... };` that we found in Eigen3 codebase. In
97 general, a user of this class should explicitly call `Evaluate` from within
98 Drake for readability.
99 
100 */
101 class Formula {
102  public:
103  /** Default constructor. */
104  Formula();
105  Formula(const Formula&);
106  Formula& operator=(const Formula&);
107  Formula(Formula&&) noexcept;
108  Formula& operator=(Formula&&) noexcept;
109  ~Formula();
110 
111  /** Constructs a formula from @p var.
112  * @pre @p var is of BOOLEAN type and not a dummy variable.
113  */
114  explicit Formula(const Variable& var);
115 
116  FormulaKind get_kind() const;
117  size_t get_hash() const;
118 
119  /** Gets free variables (unquantified variables).
120  */
121  const Variables& GetFreeVariables() const;
122 
123  /** Checks structural equality*/
124  bool EqualTo(const Formula& f) const;
125 
126  /** Checks lexicographical ordering between this and @p e.
127  *
128  * If the two formulas f1 and f2 have different kinds k1 and k2 respectively,
129  * f1.Less(f2) is equal to k1 < k2. If f1 and f2 are expressions of the same
130  * kind, we check the ordering between f1 and f2 by comparing their elements
131  * lexicographically.
132  *
133  * For example, in case of And, let f1 and f2 be
134  *
135  * f1 = f_1,1 ∧ ... ∧ f_1,n
136  * f2 = f_2,1 ∧ ... ∧ f_2,m
137  *
138  * f1.Less(f2) is true if there exists an index i (<= n, m) such that
139  * for all j < i, we have
140  *
141  * ¬(f_1_j.Less(f_2_j)) ∧ ¬(f_2_j.Less(f_1_j))
142  *
143  * and f_1_i.Less(f_2_i) holds.
144  *
145  * This function is used as a compare function in
146  * std::map<symbolic::Formula> and std::set<symbolic::Formula> via
147  * std::less<symbolic::Formula>. */
148  bool Less(const Formula& f) const;
149 
150  /** Evaluates under a given environment (by default, an empty environment).
151  *
152  * @throws runtime_error if a variable `v` is needed for an evaluation but not
153  * provided by @p env.
154  *
155  * Note that for an equality e₁ = e₂ and an inequality e₁ ≠ e₂, this method
156  * partially evaluates e₁ and e₂ and checks the structural equality of the two
157  * results if @p env does not provide complete information to call Evaluate on
158  * e₁ and e₂.
159  */
160  bool Evaluate(const Environment& env = Environment{}) const;
161 
162  /** Returns a copy of this formula replacing all occurrences of @p var
163  * with @p e.
164  * @throws std::runtime_error if NaN is detected during substitution.
165  */
166  Formula Substitute(const Variable& var, const Expression& e) const;
167 
168  /** Returns a copy of this formula replacing all occurrences of @p var
169  * with @p f.
170  * @throws std::runtime_error if NaN is detected during substitution.
171  */
172  Formula Substitute(const Variable& var, const Formula& f) const;
173 
174  /** Returns a copy of this formula replacing all occurrences of the variables
175  * in @p expr_subst with corresponding expressions in @p expr_subst and all
176  * occurrences of the variables in @p formula_subst with corresponding
177  * formulas in @p formula_subst.
178  *
179  * Note that the substitutions occur simultaneously. For example, (x / y >
180  * 0).Substitute({{x, y}, {y, x}}, {}) gets (y / x > 0).
181  *
182  * @throws std::runtime_error if NaN is detected during substitution.
183  */
184  Formula Substitute(const ExpressionSubstitution& expr_subst,
185  const FormulaSubstitution& formula_subst) const;
186 
187  /** Returns a copy of this formula replacing all occurrences of the variables
188  * in @p expr_subst with corresponding expressions in @p expr_subst.
189  *
190  * @note This is equivalent to `Substitute(expr_subst, {})`.
191  * @throws std::runtime_error if NaN is detected during substitution.
192  */
193  Formula Substitute(const ExpressionSubstitution& expr_subst) const;
194 
195  /** Returns a copy of this formula replacing all
196  * occurrences of the variables in @p formula_subst with corresponding
197  * formulas in @p formula_subst.
198  *
199  * @note This is equivalent to `Substitute({}, formula_subst)`.
200  * @throws std::runtime_error if NaN is detected during substitution.
201  */
202  Formula Substitute(const FormulaSubstitution& formula_subst) const;
203 
204  /** Returns string representation of Formula. */
205  std::string to_string() const;
206 
207  static Formula True();
208  static Formula False();
209 
210  /** Conversion to bool. */
211  explicit operator bool() const { return Evaluate(); }
212 
213  friend std::ostream& operator<<(std::ostream& os, const Formula& f);
214  friend void swap(Formula& a, Formula& b) { std::swap(a.ptr_, b.ptr_); }
215 
216  friend bool is_false(const Formula& f);
217  friend bool is_true(const Formula& f);
218  friend bool is_variable(const Formula& f);
219  friend bool is_equal_to(const Formula& f);
220  friend bool is_not_equal_to(const Formula& f);
221  friend bool is_greater_than(const Formula& f);
222  friend bool is_greater_than_or_equal_to(const Formula& f);
223  friend bool is_less_than(const Formula& f);
224  friend bool is_less_than_or_equal_to(const Formula& f);
225  friend bool is_relational(const Formula& f);
226  friend bool is_conjunction(const Formula& f);
227  friend bool is_disjunction(const Formula& f);
228  friend bool is_negation(const Formula& f);
229  friend bool is_forall(const Formula& f);
230 
231  // Note that the following cast functions are only for low-level operations
232  // and not exposed to the user of symbolic_formula.h. These functions are
233  // declared in symbolic_formula_cell.h header.
234  friend const FormulaFalse* to_false(const Formula& f);
235  friend const FormulaTrue* to_true(const Formula& f);
236  friend const FormulaVar* to_variable(const Formula& f);
237  friend const RelationalFormulaCell* to_relational(const Formula& f);
238  friend const FormulaEq* to_equal_to(const Formula& f);
239  friend const FormulaNeq* to_not_equal_to(const Formula& f);
240  friend const FormulaGt* to_greater_than(const Formula& f);
241  friend const FormulaGeq* to_greater_than_or_equal_to(const Formula& f);
242  friend const FormulaLt* to_less_than(const Formula& f);
243  friend const FormulaLeq* to_less_than_or_equal_to(const Formula& f);
244  friend const NaryFormulaCell* to_nary(const Formula& f);
245  friend NaryFormulaCell* to_nary(Formula& f);
246  friend const FormulaAnd* to_conjunction(const Formula& f);
247  friend const FormulaOr* to_disjunction(const Formula& f);
248  friend const FormulaNot* to_negation(const Formula& f);
249  friend const FormulaForall* to_forall(const Formula& f);
250 
251  // Returns f1 = f1 && f2.
252  static Formula make_conjunction(Formula& f1, const Formula& f2);
253  // Returns f1 = f1 || f2.
254  static Formula make_disjunction(Formula& f1, const Formula& f2);
255 
256  friend FormulaCell;
257  friend Formula forall(const Variables& vars, const Formula& f);
258  friend Formula make_conjunction(const std::set<Formula>& formulas);
259  friend Formula make_disjunction(const std::set<Formula>& formulas);
260  friend Formula operator!(const Formula& f);
261  friend Formula operator==(const Expression& e1, const Expression& e2);
262  friend Formula operator!=(const Expression& e1, const Expression& e2);
263  friend Formula operator<(const Expression& e1, const Expression& e2);
264  friend Formula operator<=(const Expression& e1, const Expression& e2);
265  friend Formula operator>(const Expression& e1, const Expression& e2);
266  friend Formula operator>=(const Expression& e1, const Expression& e2);
267 
268  /// Returns true if this symbolic formula includes an ITE (If-Then-Else)
269  /// expression.
270  bool include_ite() const;
271 
272  private:
273  explicit Formula(FormulaCell* ptr);
274 
275  FormulaCell* ptr_;
276 };
277 
278 /** Returns a formula @p f, universally quantified by variables @p vars. */
279 Formula forall(const Variables& vars, const Formula& f);
280 
281 /** Returns a conjunction of @p formulas. It performs the following
282  * simplification:
283  *
284  * - make_conjunction({}) returns True.
285  * - make_conjunction({f₁}) returns f₁.
286  * - If False ∈ @p formulas, it returns False.
287  * - If True ∈ @p formulas, it will not appear in the return value.
288  * - Nested conjunctions will be flattened. For example, make_conjunction({f₁,
289  * f₂ ∧ f₃}) returns f₁ ∧ f₂ ∧ f₃.
290  */
291 Formula make_conjunction(const std::set<Formula>& formulas);
292 Formula operator&&(const Formula& f1, const Formula& f2);
293 Formula operator&&(const Formula& f1, Formula&& f2);
294 Formula operator&&(Formula&& f1, const Formula& f2);
295 Formula operator&&(Formula&& f1, Formula&& f2);
296 
297 Formula operator&&(const Variable& v, const Formula& f);
298 Formula operator&&(const Variable& v, Formula&& f);
299 Formula operator&&(const Formula& f, const Variable& v);
300 Formula operator&&(Formula&& f, const Variable& v);
301 Formula operator&&(const Variable& v1, const Variable& v2);
302 
303 /** Returns a disjunction of @p formulas. It performs the following
304  * simplification:
305  *
306  * - make_disjunction({}) returns False.
307  * - make_disjunction({f₁}) returns f₁.
308  * - If True ∈ @p formulas, it returns True.
309  * - If False ∈ @p formulas, it will not appear in the return value.
310  * - Nested disjunctions will be flattened. For example, make_disjunction({f₁,
311  * f₂ ∨ f₃}) returns f₁ ∨ f₂ ∨ f₃.
312  */
313 Formula make_disjunction(const std::set<Formula>& formulas);
314 Formula operator||(const Formula& f1, const Formula& f2);
315 Formula operator||(const Formula& f1, Formula&& f2);
316 Formula operator||(Formula&& f1, const Formula& f2);
317 Formula operator||(Formula&& f1, Formula&& f2);
318 
319 Formula operator||(const Variable& v, const Formula& f);
320 Formula operator||(const Variable& v, Formula&& f);
321 Formula operator||(const Formula& f, const Variable& v);
322 Formula operator||(Formula&& f, const Variable& v);
323 Formula operator||(const Variable& v1, const Variable& v2);
324 
325 Formula operator!(const Formula& f);
326 Formula operator!(const Variable& v);
327 
328 /** Returns a formula representing v1 and v2 are equivalent.
329  * - When v1 and v2 are scalar variables (of type
330  * CONTINUOUS/BINARY/INTEGER), it forms `v1 == v2`.
331  * - When v1 and v2 are boolean variables, it returns `v1 ↔ v2`.
332  */
333 Formula operator==(const Variable& v1, const Variable& v2);
334 
335 /** Returns a formula representing (e1 = e2). */
336 Formula operator==(const Expression& e1, const Expression& e2);
337 
338 /** Returns a formula representing f1 ↔ f2. */
339 Formula operator==(const Formula& f1, const Formula& f2);
340 
341 /** Returns a formula representing v ↔ f. */
342 Formula operator==(const Variable& v, const Formula& f);
343 
344 /** Returns a formula representing f ↔ v. */
345 Formula operator==(const Formula& f, const Variable& v);
346 
347 /** Returns a formula representing v1 and v2 are *not* equivalent.
348  * - When v1 and v2 are scalar variables (of type
349  * CONTINUOUS/BINARY/INTEGER), it forms `v1 ≠ v2`.
350  * - When v1 and v2 are boolean variables, it returns `¬(v1 ↔ v2)`.
351  */
352 Formula operator!=(const Variable& v1, const Variable& v2);
353 
354 /** Returns a formula representing e1 ≠ e2. */
355 Formula operator!=(const Expression& e1, const Expression& e2);
356 
357 /** Returns a formula representing ¬(f1 ↔ f2). */
358 Formula operator!=(const Formula& f1, const Formula& f2);
359 
360 /** Returns a formula representing ¬(v ↔ f). */
361 Formula operator!=(const Variable& v, const Formula& f);
362 
363 /** Returns a formula representing ¬(f ↔ v). */
364 Formula operator!=(const Formula& f, const Variable& v);
365 
366 Formula operator<(const Expression& e1, const Expression& e2);
367 Formula operator<=(const Expression& e1, const Expression& e2);
368 Formula operator>(const Expression& e1, const Expression& e2);
369 Formula operator>=(const Expression& e1, const Expression& e2);
370 
371 std::ostream& operator<<(std::ostream& os, const Formula& f);
372 
373 /** Checks if @p f is structurally equal to False formula. */
374 bool is_false(const Formula& f);
375 /** Checks if @p f is structurally equal to True formula. */
376 bool is_true(const Formula& f);
377 /** Checks if @p f is a variable formula. */
378 bool is_variable(const Formula& f);
379 /** Checks if @p f is a formula representing equality (==). */
380 bool is_equal_to(const Formula& f);
381 /** Checks if @p f is a formula representing disequality (!=). */
382 bool is_not_equal_to(const Formula& f);
383 /** Checks if @p f is a formula representing greater-than (>). */
384 bool is_greater_than(const Formula& f);
385 /** Checks if @p f is a formula representing greater-than-or-equal-to (>=). */
386 bool is_greater_than_or_equal_to(const Formula& f);
387 /** Checks if @p f is a formula representing less-than (<). */
388 bool is_less_than(const Formula& f);
389 /** Checks if @p f is a formula representing less-than-or-equal-to (<=). */
390 bool is_less_than_or_equal_to(const Formula& f);
391 /** Checks if @p f is a relational formula ({==, !=, >, >=, <, <=}). */
392 bool is_relational(const Formula& f);
393 /** Checks if @p f is a conjunction (∧). */
394 bool is_conjunction(const Formula& f);
395 /** Checks if @p f is a disjunction (∨). */
396 bool is_disjunction(const Formula& f);
397 /** Checks if @p f is a n-ary formula ({∧, ∨}). */
398 bool is_nary(const Formula& f);
399 /** Checks if @p f is a negation (¬). */
400 bool is_negation(const Formula& f);
401 /** Checks if @p f is a Forall formula (∀). */
402 bool is_forall(const Formula& f);
403 
404 /** Returns the embedded variable in the variable formula @p f.
405  * @pre @p f is a variable formula.
406  */
407 const Variable& get_variable(const Formula& f);
408 
409 /** Returns the lhs-argument of a relational formula @p f.
410  * @pre @p f is a relational formula.
411  */
412 const Expression& get_lhs_expression(const Formula& f);
413 
414 /** Returns the rhs-argument of a relational formula @p f.
415  * @pre @p f is a relational formula.
416  */
417 const Expression& get_rhs_expression(const Formula& f);
418 
419 /** Returns the set of formulas in a n-ary formula @p f.
420  * @pre @p f is a n-ary formula.
421  */
422 const std::set<Formula>& get_operands(const Formula& f);
423 
424 /** Returns the formula in a negation formula @p f.
425  * @pre @p f is a negation formula.
426  */
427 const Formula& get_operand(const Formula& f);
428 
429 /** Returns the quantified variables in a forall formula @p f.
430  * @pre @p f is a forall formula.
431  */
432 const Variables& get_quantified_variables(const Formula& f);
433 
434 /** Returns the quantified formula in a forall formula @p f.
435  * @pre @p f is a forall formula.
436  */
437 const Formula& get_quantified_formula(const Formula& f);
438 
439 namespace detail {
440 /// Returns @p f1 ∧ @p f2. We have it because gcc-4.8 does not have
441 /// `std::logical_and`.
442 inline Formula logic_and(const Formula& f1, const Formula& f2) {
443  return f1 && f2;
444 }
445 } // namespace detail
446 } // namespace symbolic
447 
448 /** Computes the hash value of a symbolic formula. */
449 template <>
450 struct hash_value<symbolic::Formula> {
451  size_t operator()(const symbolic::Formula& f) const { return f.get_hash(); }
452 };
453 } // namespace drake
454 } // namespace dreal
455 
456 namespace std {
457 /* Provides std::less<dreal::drake::symbolic::Formula>. */
458 template <>
459 struct less<dreal::drake::symbolic::Formula> {
460  bool operator()(const dreal::drake::symbolic::Formula& lhs,
461  const dreal::drake::symbolic::Formula& rhs) const {
462  return lhs.Less(rhs);
463  }
464 };
465 
466 /* Provides std::equal_to<dreal::drake::symbolic::Formula>. */
467 template <>
468 struct equal_to<dreal::drake::symbolic::Formula> {
469  bool operator()(const dreal::drake::symbolic::Formula& lhs,
470  const dreal::drake::symbolic::Formula& rhs) const {
471  return lhs.EqualTo(rhs);
472  }
473 };
474 
475 template <>
476 struct hash<dreal::drake::symbolic::Formula> {
477  size_t operator()(const dreal::drake::symbolic::Formula& f) const {
478  return f.get_hash();
479  }
480 };
481 
482 } // namespace std
Formula make_conjunction(const vector< Formula > &formulas)
Make conjunction of formulas.
Definition: symbolic.cc:523
bool EqualTo(const Formula &f) const
Checks structural equality.
Definition: symbolic_formula.cc:82
Formula make_disjunction(const vector< Formula > &formulas)
Definition: symbolic.cc:531
Sum type of symbolic::Expression and symbolic::Formula.
Definition: api.cc:9
Symbolic formula representing &#39;less-than-or-equal-to&#39; (e1 ≤ e2).
Definition: symbolic_formula_cell.h:275
Symbolic formula representing disequality (e1 ≠ e2).
Definition: symbolic_formula_cell.h:231
STL namespace.
Symbolic formula representing &#39;greater-than-or-equal-to&#39; (e1 ≥ e2).
Definition: symbolic_formula_cell.h:253
std::shared_ptr< ContractorForall< ContextType > > to_forall(const Contractor &contractor)
Converts contractor to ContractorForall.
Definition: contractor_forall.h:331
Represents a symbolic variable.
Definition: symbolic_variable.h:16
Computes the hash value of v using std::hash.
Definition: hash.h:35
Symbolic formula representing equality (e1 = e2).
Definition: symbolic_formula_cell.h:220
RelationalOperator operator!(const RelationalOperator op)
Negates op.
Definition: symbolic.cc:551
Symbolic formula representing &#39;less-than&#39; (e1 < e2).
Definition: symbolic_formula_cell.h:264
Represents an abstract class which is the base of concrete symbolic-formula classes (i...
Definition: symbolic_formula_cell.h:27
Symbolic formula representing disjunctions (f1 ∨ ...
Definition: symbolic_formula_cell.h:299
Represents the base class for N-ary logic operators (∧ and ∨).
Definition: symbolic_formula_cell.h:141
Symbolic formula representing false.
Definition: symbolic_formula_cell.h:188
Represents a symbolic environment (mapping from a variable to a value).
Definition: symbolic_environment.h:52
Symbolic formula representing true.
Definition: symbolic_formula_cell.h:175
Symbolic formula representing negations (¬f).
Definition: symbolic_formula_cell.h:312
Represents the base class for relational operators (==, !=, <, <=, >, >=).
Definition: symbolic_formula_cell.h:106
Symbolic formula representing &#39;greater-than&#39; (e1 > e2).
Definition: symbolic_formula_cell.h:242
Symbolic formula representing a Boolean variable.
Definition: symbolic_formula_cell.h:201
Symbolic formula representing universal quantifications (∀ x₁, ..., * xn.
Definition: symbolic_formula_cell.h:332
Symbolic formula representing conjunctions (f1 ∧ ...
Definition: symbolic_formula_cell.h:286
bool is_forall(const Contractor &contractor)
Returns true if contractor is forall contractor.
Definition: contractor.cc:221
Represents a set of variables.
Definition: symbolic_variables.h:25
Represents a symbolic form of an expression.
Definition: symbolic_expression.h:164
Represents a symbolic form of a first-order logic formula.
Definition: symbolic_formula.h:101
bool Less(const Formula &f) const
Checks lexicographical ordering between this and e.
Definition: symbolic_formula.cc:100