dReal4
symbolic_expression_visitor.h
1 #pragma once
2 
3 #include <cassert>
4 #include <stdexcept>
5 #include <utility>
6 
7 #include "dreal/symbolic/symbolic_expression.h"
8 
9 namespace dreal {
10 namespace drake {
11 namespace symbolic {
12 
13 /// Calls visitor object @p v with a polynomial symbolic-expression @p e, and
14 /// arguments @p args. Visitor object is expected to implement the following
15 /// methods which take @p f and @p args: `VisitConstant`, `VisitRealConstant`,
16 /// `VisitVariable`, `VisitAddition`, `VisitMultiplication`, `VisitDivision`,
17 /// `VisitPow`.
18 ///
19 /// @throws std::runtime_error if NaN is detected during a visit.
20 ///
21 /// See the implementation of @c DegreeVisitor class and @c Degree function in
22 /// symbolic/monomial.cc as an example usage.
23 ///
24 /// @pre e.is_polynomial() is true.
25 template <typename Result, typename Visitor, typename... Args>
26 Result VisitPolynomial(Visitor* v, const Expression& e, Args&&... args) {
27  assert(e.is_polynomial());
28  switch (e.get_kind()) {
29  case ExpressionKind::Constant:
30  return v->VisitConstant(e, std::forward<Args>(args)...);
31 
32  case ExpressionKind::RealConstant:
33  return v->VisitRealConstant(e, std::forward<Args>(args)...);
34 
35  case ExpressionKind::Var:
36  return v->VisitVariable(e, std::forward<Args>(args)...);
37 
38  case ExpressionKind::Add:
39  return v->VisitAddition(e, std::forward<Args>(args)...);
40 
41  case ExpressionKind::Mul:
42  return v->VisitMultiplication(e, std::forward<Args>(args)...);
43 
44  case ExpressionKind::Div:
45  return v->VisitDivision(e, std::forward<Args>(args)...);
46 
47  case ExpressionKind::Pow:
48  return v->VisitPow(e, std::forward<Args>(args)...);
49 
50  case ExpressionKind::NaN:
51  throw std::runtime_error("NaN is detected while visiting an expression.");
52 
53  case ExpressionKind::Log:
54  case ExpressionKind::Abs:
55  case ExpressionKind::Exp:
56  case ExpressionKind::Sqrt:
57  case ExpressionKind::Sin:
58  case ExpressionKind::Cos:
59  case ExpressionKind::Tan:
60  case ExpressionKind::Asin:
61  case ExpressionKind::Acos:
62  case ExpressionKind::Atan:
63  case ExpressionKind::Atan2:
64  case ExpressionKind::Sinh:
65  case ExpressionKind::Cosh:
66  case ExpressionKind::Tanh:
67  case ExpressionKind::Min:
68  case ExpressionKind::Max:
69  case ExpressionKind::IfThenElse:
70  case ExpressionKind::UninterpretedFunction:
71  // Should not be reachable because of `DRAKE_ASSERT(e.is_polynomial())` at
72  // the top.
73  throw std::runtime_error("Should not be reachable.");
74  }
75  // Should not be reachable. But we need the following to avoid "control
76  // reaches end of non-void function" gcc-warning.
77  throw std::runtime_error("Should not be reachable.");
78 }
79 
80 /// Calls visitor object @p v with a symbolic-expression @p e, and
81 /// arguments @p args. Visitor object is expected to implement the
82 /// following methods which take @p f and @p args: `VisitConstant`,
83 /// `VisitRealConstant`, `VisitVariable`, `VisitAddition`,
84 /// `VisitMultiplication`, `VisitDivision`, `VisitLog`, `VisitAbs`,
85 /// `VisitExp`, `VisitSqrt`, `VisitPow`, `VisitSin`, `VisitCos`,
86 /// `VisitTan`, `VisitAsin`, `VisitAtan`, `VisitAtan2`, `VisitSinh`,
87 /// `VisitCosh`, `VisitTanh`, `VisitMin`, `VisitMax`,
88 /// `VisitIfThenElse`, `VisitUninterpretedFunction.
89 ///
90 /// @throws std::runtime_error if NaN is detected during a visit.
91 template <typename Result, typename Visitor, typename... Args>
92 Result VisitExpression(Visitor* v, const Expression& e, Args&&... args) {
93  switch (e.get_kind()) {
94  case ExpressionKind::Constant:
95  return v->VisitConstant(e, std::forward<Args>(args)...);
96 
97  case ExpressionKind::RealConstant:
98  return v->VisitRealConstant(e, std::forward<Args>(args)...);
99 
100  case ExpressionKind::Var:
101  return v->VisitVariable(e, std::forward<Args>(args)...);
102 
103  case ExpressionKind::Add:
104  return v->VisitAddition(e, std::forward<Args>(args)...);
105 
106  case ExpressionKind::Mul:
107  return v->VisitMultiplication(e, std::forward<Args>(args)...);
108 
109  case ExpressionKind::Div:
110  return v->VisitDivision(e, std::forward<Args>(args)...);
111 
112  case ExpressionKind::Log:
113  return v->VisitLog(e, std::forward<Args>(args)...);
114 
115  case ExpressionKind::Abs:
116  return v->VisitAbs(e, std::forward<Args>(args)...);
117 
118  case ExpressionKind::Exp:
119  return v->VisitExp(e, std::forward<Args>(args)...);
120 
121  case ExpressionKind::Sqrt:
122  return v->VisitSqrt(e, std::forward<Args>(args)...);
123 
124  case ExpressionKind::Pow:
125  return v->VisitPow(e, std::forward<Args>(args)...);
126 
127  case ExpressionKind::Sin:
128  return v->VisitSin(e, std::forward<Args>(args)...);
129 
130  case ExpressionKind::Cos:
131  return v->VisitCos(e, std::forward<Args>(args)...);
132 
133  case ExpressionKind::Tan:
134  return v->VisitTan(e, std::forward<Args>(args)...);
135 
136  case ExpressionKind::Asin:
137  return v->VisitAsin(e, std::forward<Args>(args)...);
138 
139  case ExpressionKind::Acos:
140  return v->VisitAcos(e, std::forward<Args>(args)...);
141 
142  case ExpressionKind::Atan:
143  return v->VisitAtan(e, std::forward<Args>(args)...);
144 
145  case ExpressionKind::Atan2:
146  return v->VisitAtan2(e, std::forward<Args>(args)...);
147 
148  case ExpressionKind::Sinh:
149  return v->VisitSinh(e, std::forward<Args>(args)...);
150 
151  case ExpressionKind::Cosh:
152  return v->VisitCosh(e, std::forward<Args>(args)...);
153 
154  case ExpressionKind::Tanh:
155  return v->VisitTanh(e, std::forward<Args>(args)...);
156 
157  case ExpressionKind::Min:
158  return v->VisitMin(e, std::forward<Args>(args)...);
159 
160  case ExpressionKind::Max:
161  return v->VisitMax(e, std::forward<Args>(args)...);
162 
163  case ExpressionKind::IfThenElse:
164  return v->VisitIfThenElse(e, std::forward<Args>(args)...);
165 
166  case ExpressionKind::NaN:
167  throw std::runtime_error("NaN is detected while visiting an expression.");
168 
169  case ExpressionKind::UninterpretedFunction:
170  return v->VisitUninterpretedFunction(e, std::forward<Args>(args)...);
171  }
172  // Should not be reachable. But we need the following to avoid "control
173  // reaches end of non-void function" gcc-warning.
174  throw std::runtime_error("Should not be reachable.");
175 }
176 
177 } // namespace symbolic
178 } // namespace drake
179 } // namespace dreal
Sum type of symbolic::Expression and symbolic::Formula.
Definition: api.cc:9