visitor.h
Go to the documentation of this file.
1 
6 #ifndef SYMENGINE_VISITOR_H
7 #define SYMENGINE_VISITOR_H
8 
11 #include <symengine/polys/uexprpoly.h>
12 #include <symengine/polys/msymenginepoly.h>
14 #include <symengine/complex_mpc.h>
16 #include <symengine/series_piranha.h>
17 #include <symengine/series_flint.h>
19 #include <symengine/series_piranha.h>
20 #include <symengine/sets.h>
21 #include <symengine/fields.h>
22 #include <symengine/logic.h>
23 #include <symengine/infinity.h>
24 #include <symengine/nan.h>
25 #include <symengine/matrix.h>
26 #include <symengine/ntheory_funcs.h>
27 #include <symengine/symengine_casts.h>
28 #include <symengine/tuple.h>
29 #include <symengine/matrix_expressions.h>
30 
31 namespace SymEngine
32 {
33 
34 class Visitor
35 {
36 public:
37  virtual ~Visitor(){};
38 #define SYMENGINE_ENUM(TypeID, Class) virtual void visit(const Class &) = 0;
39 #include "symengine/type_codes.inc"
40 #undef SYMENGINE_ENUM
41 };
42 
43 void preorder_traversal(const Basic &b, Visitor &v);
44 void postorder_traversal(const Basic &b, Visitor &v);
45 
46 template <class Derived, class Base = Visitor>
47 class BaseVisitor : public Base
48 {
49 
50 public:
51 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 8 \
52  || defined(__SUNPRO_CC))
53  // Following two ctors can be replaced by `using Base::Base` if inheriting
54  // constructors are allowed by the compiler. GCC 4.8 is the earliest
55  // version supporting this.
56  template <typename... Args,
57  typename
58  = enable_if_t<std::is_constructible<Base, Args...>::value>>
59  BaseVisitor(Args &&...args) : Base(std::forward<Args>(args)...)
60  {
61  }
62 
63  BaseVisitor() : Base() {}
64 #else
65  using Base::Base;
66 #endif
67 
68 #define SYMENGINE_ENUM(TypeID, Class) \
69  virtual void visit(const Class &x) \
70  { \
71  down_cast<Derived *>(this)->bvisit(x); \
72  };
73 #include "symengine/type_codes.inc"
74 #undef SYMENGINE_ENUM
75 };
76 
77 class StopVisitor : public Visitor
78 {
79 public:
80  bool stop_;
81 };
82 
84 {
85 public:
86  bool local_stop_;
87 };
88 
89 void preorder_traversal_stop(const Basic &b, StopVisitor &v);
90 void postorder_traversal_stop(const Basic &b, StopVisitor &v);
91 void preorder_traversal_local_stop(const Basic &b, LocalStopVisitor &v);
92 
94 {
95 protected:
96  Ptr<const Basic> looking_for_;
97  bool has_;
98 
99 public:
100  HasBasicVisitor(Ptr<const Basic> looking_for);
101  bool apply(const Basic &b)
102  {
103  has_ = false;
104  stop_ = false;
105  preorder_traversal_stop(b, *this);
106  return has_;
107  }
108  void bvisit(const Basic &arg)
109  {
110  if (eq(*looking_for_, arg)) {
111  has_ = true;
112  stop_ = true;
113  }
114  }
115 };
116 
118 {
119 protected:
120  Ptr<const Basic> x_;
121  bool has_;
122 
123 public:
124  HasSymbolVisitor(Ptr<const Basic> x) : x_(x) {}
125 
126  void bvisit(const Symbol &x)
127  {
128  if (eq(*x_, x)) {
129  has_ = true;
130  stop_ = true;
131  }
132  }
133 
134  void bvisit(const FunctionSymbol &x)
135  {
136  if (eq(*x_, x)) {
137  has_ = true;
138  stop_ = true;
139  }
140  }
141 
142  void bvisit(const Basic &x) {}
143 
144  bool apply(const Basic &b)
145  {
146  has_ = false;
147  stop_ = false;
148  preorder_traversal_stop(b, *this);
149  return has_;
150  }
151 };
152 
153 bool has_basic(const Basic &b, const Basic &x);
154 bool has_symbol(const Basic &b, const Basic &x);
155 
157 {
158 protected:
159  Ptr<const Basic> x_;
160  Ptr<const Basic> n_;
161  RCP<const Basic> coeff_;
162 
163 public:
164  CoeffVisitor(Ptr<const Basic> x, Ptr<const Basic> n) : x_(x), n_(n) {}
165 
166  void bvisit(const Add &x)
167  {
168  umap_basic_num dict;
169  RCP<const Number> coef = zero;
170  for (auto &p : x.get_dict()) {
171  p.first->accept(*this);
172  if (neq(*coeff_, *zero)) {
173  Add::coef_dict_add_term(outArg(coef), dict, p.second, coeff_);
174  }
175  }
176  if (eq(*zero, *n_)) {
177  iaddnum(outArg(coef), x.get_coef());
178  }
179  coeff_ = Add::from_dict(coef, std::move(dict));
180  }
181 
182  void bvisit(const Mul &x)
183  {
184  for (auto &p : x.get_dict()) {
185  if (eq(*p.first, *x_) and eq(*p.second, *n_)) {
186  map_basic_basic dict = x.get_dict();
187  dict.erase(p.first);
188  coeff_ = Mul::from_dict(x.get_coef(), std::move(dict));
189  return;
190  }
191  }
192  if (eq(*zero, *n_) and not has_symbol(x, *x_)) {
193  coeff_ = x.rcp_from_this();
194  } else {
195  coeff_ = zero;
196  }
197  }
198 
199  void bvisit(const Pow &x)
200  {
201  if (eq(*x.get_base(), *x_) and eq(*x.get_exp(), *n_)) {
202  coeff_ = one;
203  } else if (neq(*x.get_base(), *x_) and eq(*zero, *n_)) {
204  coeff_ = x.rcp_from_this();
205  } else {
206  coeff_ = zero;
207  }
208  }
209 
210  void bvisit(const Symbol &x)
211  {
212  if (eq(x, *x_) and eq(*one, *n_)) {
213  coeff_ = one;
214  } else if (neq(x, *x_) and eq(*zero, *n_)) {
215  coeff_ = x.rcp_from_this();
216  } else {
217  coeff_ = zero;
218  }
219  }
220 
221  void bvisit(const FunctionSymbol &x)
222  {
223  if (eq(x, *x_) and eq(*one, *n_)) {
224  coeff_ = one;
225  } else if (neq(x, *x_) and eq(*zero, *n_)) {
226  coeff_ = x.rcp_from_this();
227  } else {
228  coeff_ = zero;
229  }
230  }
231 
232  void bvisit(const Basic &x)
233  {
234  if (neq(*zero, *n_)) {
235  coeff_ = zero;
236  return;
237  }
238  if (has_symbol(x, *x_)) {
239  coeff_ = zero;
240  } else {
241  coeff_ = x.rcp_from_this();
242  }
243  }
244 
245  RCP<const Basic> apply(const Basic &b)
246  {
247  coeff_ = zero;
248  b.accept(*this);
249  return coeff_;
250  }
251 };
252 
253 RCP<const Basic> coeff(const Basic &b, const Basic &x, const Basic &n);
254 
255 set_basic free_symbols(const Basic &b);
256 
257 set_basic free_symbols(const MatrixBase &m);
258 
259 set_basic function_symbols(const Basic &b);
260 
262 {
263 protected:
264  RCP<const Basic> result_;
265 
266 public:
267  TransformVisitor() {}
268 
269  virtual RCP<const Basic> apply(const RCP<const Basic> &x);
270 
271  void bvisit(const Basic &x);
272  void bvisit(const Add &x);
273  void bvisit(const Mul &x);
274  void bvisit(const Pow &x);
275  void bvisit(const OneArgFunction &x);
276 
277  template <class T>
278  void bvisit(const TwoArgBasic<T> &x)
279  {
280  auto farg1 = x.get_arg1(), farg2 = x.get_arg2();
281  auto newarg1 = apply(farg1), newarg2 = apply(farg2);
282  if (farg1 != newarg1 or farg2 != newarg2) {
283  result_ = x.create(newarg1, newarg2);
284  } else {
285  result_ = x.rcp_from_this();
286  }
287  }
288 
289  void bvisit(const MultiArgFunction &x);
290  void bvisit(const Piecewise &x);
291 };
292 
293 template <typename Derived, typename First, typename... Rest>
295  static const bool value = std::is_base_of<First, Derived>::value
296  or is_base_of_multiple<Derived, Rest...>::value;
297 };
298 
299 template <typename Derived, typename First>
300 struct is_base_of_multiple<Derived, First> {
301  static const bool value = std::is_base_of<First, Derived>::value;
302 };
303 
304 template <typename... Args>
305 class AtomsVisitor : public BaseVisitor<AtomsVisitor<Args...>>
306 {
307 public:
308  set_basic s;
309  uset_basic visited;
310 
311  template <typename T,
312  typename = enable_if_t<is_base_of_multiple<T, Args...>::value>>
313  void bvisit(const T &x)
314  {
315  s.insert(x.rcp_from_this());
316  visited.insert(x.rcp_from_this());
317  bvisit((const Basic &)x);
318  }
319 
320  void bvisit(const Basic &x)
321  {
322  for (const auto &p : x.get_args()) {
323  auto iter = visited.insert(p->rcp_from_this());
324  if (iter.second) {
325  p->accept(*this);
326  }
327  }
328  }
329 
330  set_basic apply(const Basic &b)
331  {
332  b.accept(*this);
333  return s;
334  }
335 };
336 
337 template <typename... Args>
338 inline set_basic atoms(const Basic &b)
339 {
340  AtomsVisitor<Args...> visitor;
341  return visitor.apply(b);
342 };
343 
344 class CountOpsVisitor : public BaseVisitor<CountOpsVisitor>
345 {
346 protected:
347  std::unordered_map<RCP<const Basic>, unsigned, RCPBasicHash, RCPBasicKeyEq>
348  v;
349 
350 public:
351  unsigned count = 0;
352  void apply(const Basic &b);
353  void bvisit(const Mul &x);
354  void bvisit(const Add &x);
355  void bvisit(const Pow &x);
356  void bvisit(const Number &x);
357  void bvisit(const ComplexBase &x);
358  void bvisit(const Symbol &x);
359  void bvisit(const Constant &x);
360  void bvisit(const Basic &x);
361 };
362 
363 unsigned count_ops(const vec_basic &a);
364 
365 } // namespace SymEngine
366 
367 #endif
The base class for representing addition in symbolic expressions.
Definition: add.h:27
static RCP< const Basic > from_dict(const RCP< const Number > &coef, umap_basic_num &&d)
Create an appropriate instance from dictionary quickly.
Definition: add.cpp:140
static void coef_dict_add_term(const Ptr< RCP< const Number >> &coef, umap_basic_num &d, const RCP< const Number > &c, const RCP< const Basic > &term)
Updates the numerical coefficient and the dictionary.
Definition: add.cpp:261
const RCP< const Number > & get_coef() const
Definition: add.h:142
The lowest unit of symbolic representation.
Definition: basic.h:97
virtual vec_basic get_args() const =0
Returns the list of arguments.
ComplexBase Class for deriving all complex classes.
Definition: complex.h:16
RCP< T > rcp_from_this()
Get RCP<T> pointer to self (it will cast the pointer to T)
static RCP< const Basic > from_dict(const RCP< const Number > &coef, map_basic_basic &&d)
Create a Mul from a dict.
Definition: mul.cpp:115
RCP< const Basic > get_exp() const
Definition: pow.h:42
RCP< const Basic > get_base() const
Definition: pow.h:37
virtual RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const =0
Method to construct classes with canonicalization.
RCP< const Basic > get_arg1() const
Definition: functions.h:91
RCP< const Basic > get_arg2() const
Definition: functions.h:96
Main namespace for SymEngine package.
Definition: add.cpp:19
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
Definition: basic-inl.h:29
Our comparison (==)
Definition: basic.h:219