sets.cpp
1 #include <symengine/add.h>
2 #include <symengine/logic.h>
3 #include <symengine/functions.h>
4 #include <symengine/symengine_casts.h>
5 #include <iterator>
6 
7 namespace SymEngine
8 {
9 
10 Interval::Interval(const RCP<const Number> &start, const RCP<const Number> &end,
11  const bool left_open, const bool right_open)
12  : start_(start), end_(end), left_open_(left_open), right_open_(right_open)
13 {
14  SYMENGINE_ASSIGN_TYPEID()
15  SYMENGINE_ASSERT(
16  Interval::is_canonical(start_, end_, left_open_, right_open_));
17 }
18 
19 bool Interval::is_canonical(const RCP<const Number> &s,
20  const RCP<const Number> &e, bool left_open,
21  bool right_open)
22 {
23  if (is_a<Complex>(*s) or is_a<Complex>(*e))
24  throw NotImplementedError("Complex set not implemented");
25  if (eq(*e, *s)) {
26  return false;
27  } else if (eq(*min({s, e}), *e)) {
28  return false;
29  }
30  return true;
31 }
32 
33 hash_t Interval::__hash__() const
34 {
35  hash_t seed = SYMENGINE_INTERVAL;
36  hash_combine<Basic>(seed, *start_);
37  hash_combine<Basic>(seed, *end_);
38  hash_combine<bool>(seed, left_open_);
39  hash_combine<bool>(seed, right_open_);
40  return seed;
41 }
42 
43 bool Interval::__eq__(const Basic &o) const
44 {
45  if (is_a<Interval>(o)) {
46  const Interval &s = down_cast<const Interval &>(o);
47  return ((this->left_open_ == s.left_open_)
48  and (this->right_open_ == s.right_open_)
49  and eq(*this->start_, *s.start_) and eq(*this->end_, *s.end_));
50  }
51  return false;
52 }
53 
54 int Interval::compare(const Basic &s) const
55 {
56  // compares two interval based on their length
57  SYMENGINE_ASSERT(is_a<Interval>(s))
58  const Interval &o = down_cast<const Interval &>(s);
59  if (left_open_ and not o.left_open_) {
60  return -1;
61  } else if (not left_open_ and o.left_open_) {
62  return 1;
63  } else if (right_open_ and not o.right_open_) {
64  return 1;
65  } else if (not right_open_ and o.right_open_) {
66  return -1;
67  } else {
68  auto temp = start_->__cmp__(*(o.start_));
69  if (temp != 0) {
70  return temp;
71  } else {
72  return end_->__cmp__(*(o.end_));
73  }
74  }
75 }
76 
77 RCP<const Set> Interval::open() const
78 {
79  return interval(start_, end_, true, true);
80 }
81 
82 RCP<const Set> Interval::Lopen() const
83 {
84  return interval(start_, end_, true, false);
85 }
86 
87 RCP<const Set> Interval::Ropen() const
88 {
89  return interval(start_, end_, false, true);
90 }
91 
92 RCP<const Set> Interval::close() const
93 {
94  return interval(start_, end_, false, false);
95 }
96 
97 RCP<const Boolean> Interval::contains(const RCP<const Basic> &a) const
98 {
99  if (not is_a_Number(*a)) {
100  if (is_a_Set(*a)) {
101  return boolean(false);
102  } else {
103  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
104  }
105  }
106  if (eq(*start_, *a))
107  return boolean(not left_open_);
108  if (eq(*end_, *a))
109  return boolean(not right_open_);
110  if (eq(*min({end_, a}), *end_) or eq(*max({start_, a}), *start_))
111  return boolean(false);
112  return boolean(true);
113 }
114 
115 static RCP<const Set> make_set_union(const set_set &in)
116 {
117  if (in.size() > 1) {
118  return make_rcp<const Union>(in);
119  }
120  return *in.begin();
121 }
122 
123 static RCP<const Set> make_set_intersection(const set_set &in)
124 {
125  if (in.size() > 1) {
126  return make_rcp<const Intersection>(in);
127  }
128  return *in.begin();
129 }
130 
131 RCP<const Set> Interval::set_intersection(const RCP<const Set> &o) const
132 {
133  if (is_a<Interval>(*o)) {
134  const Interval &other = down_cast<const Interval &>(*o);
135  RCP<const Number> start, end;
136  bool left_open, right_open;
137  RCP<const Basic> start_end, end_start;
138  start_end = min({this->start_, other.end_});
139  end_start = min({this->end_, other.start_});
140 
141  if (eq(*this->start_, *start_end) and eq(*other.start_, *end_start)) {
142  RCP<const Basic> start_start, end_end;
143  start_start = min({this->start_, other.start_});
144  end_end = min({this->end_, other.end_});
145  if (neq(*this->start_, *other.start_)) {
146  if (eq(*this->start_, *start_start)) {
147  start = other.start_;
148  left_open = other.left_open_;
149  } else {
150  start = this->start_;
151  left_open = this->left_open_;
152  }
153  } else {
154  start = this->start_;
155  left_open = this->left_open_ or other.left_open_;
156  }
157 
158  if (neq(*this->end_, *other.end_)) {
159  if (eq(*this->end_, *end_end)) {
160  end = this->end_;
161  right_open = this->right_open_;
162  } else {
163  end = other.end_;
164  right_open = other.right_open_;
165  }
166  } else {
167  end = this->end_;
168  right_open = this->right_open_ or other.right_open_;
169  }
170  return interval(start, end, left_open, right_open);
171  } else {
172  return emptyset();
173  }
174  }
175  if (is_a<Integers>(*o) or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
176  if (is_a_Number(*start_) and is_a_Number(*end_)) {
177  auto first = SymEngine::ceiling(start_);
178  auto last = SymEngine::floor(end_);
179  if (is_a<Naturals>(*o)
180  and not down_cast<const Integer &>(*first).is_positive()) {
181  first = integer(1);
182  } else if (is_a<Naturals0>(*o)
183  and down_cast<const Integer &>(*first).is_negative()) {
184  first = integer(0);
185  }
186  if (eq(*first, *start_) and left_open_) {
187  first = add(first, integer(1));
188  }
189  if (eq(*last, *end_) and right_open_) {
190  last = add(last, integer(-1));
191  }
192  if (eq(*Lt(last, first), *boolTrue)) {
193  return emptyset();
194  }
195  set_basic container;
196  while (eq(*Ge(last, first), *boolTrue)) {
197  container.insert(first);
198  first = add(first, integer(1));
199  }
200  return finiteset(container);
201  } else {
202  return SymEngine::set_intersection(
203  {rcp_from_this_cast<const Set>(), o});
204  }
205  }
206  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<FiniteSet>(*o)
207  or is_a<Union>(*o) or is_a<Rationals>(*o) or is_a<Reals>(*o)
208  or is_a<Complexes>(*o)) {
209  return (*o).set_intersection(rcp_from_this_cast<const Set>());
210  }
211  return make_set_intersection({rcp_from_this_cast<const Set>(), o});
212 }
213 
214 RCP<const Set> Interval::set_union(const RCP<const Set> &o) const
215 {
216  if (is_a<Interval>(*o)) {
217  const Interval &other = down_cast<const Interval &>(*o);
218  RCP<const Basic> start_start, end_end, m;
219  RCP<const Number> start, end;
220  bool left_open, right_open;
221  start_start = max({this->start_, other.start_});
222  end_end = min({this->end_, other.end_});
223  m = min({start_start, end_end});
224  if ((eq(*end_end, *start_start) and eq(*end_end, *m)
225  and ((eq(*end_end, *this->end_) and this->right_open_)
226  or (eq(*end_end, *other.end_) and other.right_open_)))
227  or (eq(*end_end, *m) and not eq(*end_end, *start_start))) {
228  return SymEngine::make_set_union(
229  {rcp_from_this_cast<const Set>(), o});
230  } else {
231  if (eq(*min({this->start_, other.start_}), *this->start_)) {
232  start = this->start_;
233  } else {
234  start = other.start_;
235  }
236  if (eq(*max({this->end_, other.end_}), *this->end_)) {
237  end = this->end_;
238  } else {
239  end = other.end_;
240  }
241  left_open = ((neq(*this->start_, *start) or this->left_open_)
242  and (neq(*other.start_, *start) or other.left_open_));
243  right_open = ((neq(*this->end_, *end) or this->right_open_)
244  and (neq(*other.end_, *end) or other.right_open_));
245  return interval(start, end, left_open, right_open);
246  }
247  }
248  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<FiniteSet>(*o)
249  or is_a<Union>(*o) or is_a<Complexes>(*o) or is_a<Reals>(*o)
250  or is_a<Rationals>(*o) or is_a<Integers>(*o) or is_a<Naturals>(*o)
251  or is_a<Naturals0>(*o)) {
252  return (*o).set_union(rcp_from_this_cast<const Set>());
253  }
254  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
255 }
256 
257 RCP<const Set> Interval::set_complement(const RCP<const Set> &o) const
258 {
259  if (is_a<Interval>(*o)) {
260  set_set cont;
261  const Interval &other = down_cast<const Interval &>(*o);
262  if (eq(*max({start_, other.start_}), *start_)) {
263  cont.insert(interval(other.get_start(), start_,
264  other.get_left_open(), not left_open_));
265  }
266  if (eq(*min({end_, other.end_}), *end_)) {
267  cont.insert(interval(end_, other.get_end(), not right_open_,
268  other.get_right_open()));
269  }
270  return SymEngine::set_union(cont);
271  }
272  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
273 }
274 
275 vec_basic Interval::get_args() const
276 {
277  return {start_, end_, boolean(left_open_), boolean(right_open_)};
278 }
279 
280 RCP<const Set> Complexes::set_intersection(const RCP<const Set> &o) const
281 {
282  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Complexes>(*o)
283  or is_a<Reals>(*o) or is_a<Rationals>(*o) or is_a<Integers>(*o)
284  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
285  return o;
286  } else if (is_a<FiniteSet>(*o)) {
287  return (*o).set_intersection(rcp_from_this_cast<const Set>());
288  } else {
289  return SymEngine::set_intersection(
290  {rcp_from_this_cast<const Set>(), o});
291  }
292 }
293 
294 RCP<const Set> Complexes::set_union(const RCP<const Set> &o) const
295 {
296  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Complexes>(*o)
297  or is_a<Reals>(*o) or is_a<Integers>(*o) or is_a<Rationals>(*o)
298  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
299  return complexes();
300  } else if (is_a<FiniteSet>(*o)) {
301  return (*o).set_union(rcp_from_this_cast<const Set>());
302  } else {
303  return SymEngine::set_union({rcp_from_this_cast<const Set>(), o});
304  }
305 }
306 
307 RCP<const Set> Complexes::set_complement(const RCP<const Set> &o) const
308 {
309  if (is_a<EmptySet>(*o) or is_a<Complexes>(*o) or is_a<Reals>(*o)
310  or is_a<Rationals>(*o) or is_a<Integers>(*o) or is_a<Interval>(*o)
311  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
312  return emptyset();
313  }
314  if (is_a<UniversalSet>(*o)) {
315  return make_rcp<const Complement>(o, complexes());
316  }
317  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
318 }
319 
320 RCP<const Boolean> Complexes::contains(const RCP<const Basic> &a) const
321 {
322  if (not is_a_Number(*a)) {
323  if (is_a_Set(*a)) {
324  return boolean(false);
325  } else {
326  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
327  }
328  }
329  return boolean(true);
330 }
331 
332 hash_t Complexes::__hash__() const
333 {
334  hash_t seed = SYMENGINE_COMPLEXES;
335  return seed;
336 }
337 
338 bool Complexes::__eq__(const Basic &o) const
339 {
340  if (is_a<Complexes>(o))
341  return true;
342  return false;
343 }
344 
345 int Complexes::compare(const Basic &o) const
346 {
347  SYMENGINE_ASSERT(is_a<Complexes>(o))
348  return 0;
349 }
350 
351 const RCP<const Complexes> &Complexes::getInstance()
352 {
353  const static auto a = make_rcp<const Complexes>();
354  return a;
355 }
356 
357 RCP<const Set> Reals::set_intersection(const RCP<const Set> &o) const
358 {
359  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Reals>(*o)
360  or is_a<Rationals>(*o) or is_a<Integers>(*o) or is_a<Naturals>(*o)
361  or is_a<Naturals0>(*o)) {
362  return o;
363  } else if (is_a<FiniteSet>(*o) or is_a<Complexes>(*o)) {
364  return (*o).set_intersection(rcp_from_this_cast<const Set>());
365  } else {
366  return SymEngine::set_intersection(
367  {rcp_from_this_cast<const Set>(), o});
368  }
369 }
370 
371 RCP<const Set> Reals::set_union(const RCP<const Set> &o) const
372 {
373  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Reals>(*o)
374  or is_a<Integers>(*o) or is_a<Rationals>(*o) or is_a<Naturals>(*o)
375  or is_a<Naturals0>(*o)) {
376  return reals();
377  } else if (is_a<FiniteSet>(*o) or is_a<Complexes>(*o)) {
378  return (*o).set_union(rcp_from_this_cast<const Set>());
379  } else {
380  return SymEngine::set_union({rcp_from_this_cast<const Set>(), o});
381  }
382 }
383 
384 RCP<const Set> Reals::set_complement(const RCP<const Set> &o) const
385 {
386  if (is_a<EmptySet>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)
387  or is_a<Integers>(*o) or is_a<Interval>(*o) or is_a<Naturals>(*o)
388  or is_a<Naturals0>(*o)) {
389  return emptyset();
390  }
391  if (is_a<UniversalSet>(*o) or is_a<Complexes>(*o)) {
392  return make_rcp<const Complement>(o, reals());
393  }
394  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
395 }
396 
397 RCP<const Boolean> Reals::contains(const RCP<const Basic> &a) const
398 {
399  if (not is_a_Number(*a)) {
400  if (is_a_Set(*a)) {
401  return boolean(false);
402  } else {
403  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
404  }
405  }
406  if (is_a<Complex>(*a)) {
407  return boolean(false);
408  }
409  return boolean(true);
410 }
411 
412 hash_t Reals::__hash__() const
413 {
414  hash_t seed = SYMENGINE_REALS;
415  return seed;
416 }
417 
418 bool Reals::__eq__(const Basic &o) const
419 {
420  if (is_a<Reals>(o))
421  return true;
422  return false;
423 }
424 
425 int Reals::compare(const Basic &o) const
426 {
427  SYMENGINE_ASSERT(is_a<Reals>(o))
428  return 0;
429 }
430 
431 const RCP<const Reals> &Reals::getInstance()
432 {
433  const static auto a = make_rcp<const Reals>();
434  return a;
435 }
436 
437 RCP<const Set> Rationals::set_intersection(const RCP<const Set> &o) const
438 {
439  if (is_a<EmptySet>(*o) or is_a<Rationals>(*o) or is_a<Integers>(*o)
440  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
441  return o;
442  } else if (is_a<FiniteSet>(*o) or is_a<Reals>(*o) or is_a<Complexes>(*o)) {
443  return (*o).set_intersection(rcp_from_this_cast<const Set>());
444  } else {
445  return SymEngine::set_intersection(
446  {rcp_from_this_cast<const Set>(), o});
447  }
448 }
449 
450 RCP<const Set> Rationals::set_union(const RCP<const Set> &o) const
451 {
452  if (is_a<EmptySet>(*o) or is_a<Integers>(*o) or is_a<Rationals>(*o)
453  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
454  return rationals();
455  } else if (is_a<FiniteSet>(*o) or is_a<Reals>(*o) or is_a<Complexes>(*o)) {
456  return (*o).set_union(rcp_from_this_cast<const Set>());
457  } else {
458  return SymEngine::set_union({rcp_from_this_cast<const Set>(), o});
459  }
460 }
461 
462 RCP<const Set> Rationals::set_complement(const RCP<const Set> &o) const
463 {
464  if (is_a<EmptySet>(*o) or is_a<Rationals>(*o) or is_a<Integers>(*o)
465  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
466  return emptyset();
467  }
468  if (is_a<UniversalSet>(*o) or is_a<Complexes>(*o) or is_a<Reals>(*o)
469  or is_a<Interval>(*o)) {
470  return make_rcp<const Complement>(o, rationals());
471  }
472  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
473 }
474 
475 RCP<const Boolean> Rationals::contains(const RCP<const Basic> &a) const
476 {
477  if (not is_a_Number(*a)) {
478  if (is_a_Set(*a)) {
479  return boolean(false);
480  } else {
481  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
482  }
483  }
484  if (is_a<Complex>(*a) or not down_cast<const Number &>(*a).is_exact()) {
485  return boolean(false);
486  }
487  return boolean(true);
488 }
489 
490 hash_t Rationals::__hash__() const
491 {
492  hash_t seed = SYMENGINE_RATIONALS;
493  return seed;
494 }
495 
496 bool Rationals::__eq__(const Basic &o) const
497 {
498  return (is_a<Rationals>(o));
499 }
500 
501 int Rationals::compare(const Basic &o) const
502 {
503  SYMENGINE_ASSERT(is_a<Rationals>(o))
504  return 0;
505 }
506 
507 const RCP<const Rationals> &Rationals::getInstance()
508 {
509  const static auto a = make_rcp<const Rationals>();
510  return a;
511 }
512 
513 RCP<const Set> Integers::set_intersection(const RCP<const Set> &o) const
514 {
515  if (is_a<EmptySet>(*o) or is_a<Integers>(*o) or is_a<Naturals>(*o)
516  or is_a<Naturals0>(*o)) {
517  return o;
518  } else if (is_a<Complexes>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)) {
519  return integers();
520  } else if (is_a<FiniteSet>(*o) or is_a<Interval>(*o)) {
521  return (*o).set_intersection(rcp_from_this_cast<const Set>());
522  } else {
523  return SymEngine::set_intersection(
524  {rcp_from_this_cast<const Set>(), o});
525  }
526 }
527 
528 RCP<const Set> Integers::set_union(const RCP<const Set> &o) const
529 {
530  if (is_a<Integers>(*o) or is_a<EmptySet>(*o) or is_a<Naturals>(*o)
531  or is_a<Naturals0>(*o)) {
532  return integers();
533  } else if (is_a<Complexes>(*o)) {
534  return complexes();
535  } else if (is_a<Reals>(*o)) {
536  return reals();
537  } else if (is_a<Rationals>(*o)) {
538  return rationals();
539  } else if (is_a<FiniteSet>(*o)) {
540  return (*o).set_union(rcp_from_this_cast<const Set>());
541  } else if (is_a<UniversalSet>(*o)) {
542  return universalset();
543  } else {
544  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
545  }
546 }
547 
548 RCP<const Set> Integers::set_complement(const RCP<const Set> &o) const
549 {
550  if (is_a<EmptySet>(*o) or is_a<Integers>(*o) or is_a<Naturals>(*o)
551  or is_a<Naturals0>(*o)) {
552  return emptyset();
553  }
554  if (is_a<UniversalSet>(*o) or is_a<Rationals>(*o) or is_a<Reals>(*o)
555  or is_a<Complexes>(*o)) {
556  return make_rcp<const Complement>(o, integers());
557  }
558  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
559 }
560 
561 RCP<const Boolean> Integers::contains(const RCP<const Basic> &a) const
562 {
563  if (not is_a_Number(*a)) {
564  if (is_a_Set(*a)) {
565  return boolean(false);
566  } else {
567  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
568  }
569  }
570  if (is_a<Integer>(*a)) {
571  return boolean(true);
572  }
573  return boolean(false);
574 }
575 
576 hash_t Integers::__hash__() const
577 {
578  hash_t seed = SYMENGINE_INTEGERS;
579  return seed;
580 }
581 
582 bool Integers::__eq__(const Basic &o) const
583 {
584  if (is_a<Integers>(o))
585  return true;
586  return false;
587 }
588 
589 int Integers::compare(const Basic &o) const
590 {
591  SYMENGINE_ASSERT(is_a<Integers>(o))
592  return 0;
593 }
594 
595 const RCP<const Integers> &Integers::getInstance()
596 {
597  const static auto a = make_rcp<const Integers>();
598  return a;
599 }
600 
601 RCP<const Set> Naturals::set_intersection(const RCP<const Set> &o) const
602 {
603  if (is_a<EmptySet>(*o) or is_a<Naturals>(*o)) {
604  return o;
605  } else if (is_a<Naturals0>(*o) or is_a<Integers>(*o) or is_a<Complexes>(*o)
606  or is_a<Reals>(*o) or is_a<Rationals>(*o)) {
607  return naturals();
608  } else if (is_a<FiniteSet>(*o) or is_a<Interval>(*o)) {
609  return (*o).set_intersection(rcp_from_this_cast<const Set>());
610  } else {
611  return SymEngine::set_intersection(
612  {rcp_from_this_cast<const Set>(), o});
613  }
614 }
615 
616 RCP<const Set> Naturals::set_union(const RCP<const Set> &o) const
617 {
618  if (is_a<EmptySet>(*o)) {
619  return naturals();
620  } else if (is_a<Naturals>(*o) or is_a<Naturals0>(*o) or is_a<Integers>(*o)
621  or is_a<Complexes>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)
622  or is_a<UniversalSet>(*o)) {
623  return o;
624  } else if (is_a<FiniteSet>(*o)) {
625  return (*o).set_union(rcp_from_this_cast<const Set>());
626  } else {
627  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
628  }
629 }
630 
631 RCP<const Set> Naturals::set_complement(const RCP<const Set> &o) const
632 {
633  if (is_a<EmptySet>(*o) or is_a<Naturals>(*o)) {
634  return emptyset();
635  }
636  if (is_a<Naturals0>(*o)) {
637  finiteset({zero});
638  }
639  if (is_a<UniversalSet>(*o) or is_a<Integers>(*o) or is_a<Rationals>(*o)
640  or is_a<Reals>(*o) or is_a<Complexes>(*o)) {
641  return make_rcp<const Complement>(o, naturals());
642  }
643  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
644 }
645 
646 RCP<const Boolean> Naturals::contains(const RCP<const Basic> &a) const
647 {
648  if (not is_a_Number(*a)) {
649  if (is_a_Set(*a)) {
650  return boolean(false);
651  } else {
652  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
653  }
654  } else if (is_a<Integer>(*a)
655  and down_cast<const Integer &>(*a).is_positive()) {
656  return boolean(true);
657  } else {
658  return boolean(false);
659  }
660 }
661 
662 hash_t Naturals::__hash__() const
663 {
664  hash_t seed = SYMENGINE_NATURALS;
665  return seed;
666 }
667 
668 bool Naturals::__eq__(const Basic &o) const
669 {
670  if (is_a<Naturals>(o))
671  return true;
672  return false;
673 }
674 
675 int Naturals::compare(const Basic &o) const
676 {
677  SYMENGINE_ASSERT(is_a<Naturals>(o))
678  return 0;
679 }
680 
681 const RCP<const Naturals> &Naturals::getInstance()
682 {
683  const static auto a = make_rcp<const Naturals>();
684  return a;
685 }
686 
687 RCP<const Set> Naturals0::set_intersection(const RCP<const Set> &o) const
688 {
689  if (is_a<EmptySet>(*o) or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
690  return o;
691  } else if (is_a<Integers>(*o) or is_a<Complexes>(*o) or is_a<Reals>(*o)
692  or is_a<Rationals>(*o)) {
693  return naturals0();
694  } else if (is_a<FiniteSet>(*o) or is_a<Interval>(*o)) {
695  return (*o).set_intersection(rcp_from_this_cast<const Set>());
696  } else {
697  return SymEngine::set_intersection(
698  {rcp_from_this_cast<const Set>(), o});
699  }
700 }
701 
702 RCP<const Set> Naturals0::set_union(const RCP<const Set> &o) const
703 {
704  if (is_a<EmptySet>(*o) or is_a<Naturals>(*o)) {
705  return naturals0();
706  } else if (is_a<Naturals0>(*o) or is_a<Integers>(*o) or is_a<Complexes>(*o)
707  or is_a<Reals>(*o) or is_a<Rationals>(*o)
708  or is_a<UniversalSet>(*o)) {
709  return o;
710  } else if (is_a<FiniteSet>(*o)) {
711  return (*o).set_union(rcp_from_this_cast<const Set>());
712  } else {
713  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
714  }
715 }
716 
717 RCP<const Set> Naturals0::set_complement(const RCP<const Set> &o) const
718 {
719  if (is_a<EmptySet>(*o) or is_a<Naturals0>(*o) or is_a<Naturals>(*o)) {
720  return emptyset();
721  }
722  if (is_a<UniversalSet>(*o) or is_a<Integers>(*o) or is_a<Rationals>(*o)
723  or is_a<Reals>(*o) or is_a<Complexes>(*o)) {
724  return make_rcp<const Complement>(o, naturals());
725  }
726  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
727 }
728 
729 RCP<const Boolean> Naturals0::contains(const RCP<const Basic> &a) const
730 {
731  if (not is_a_Number(*a)) {
732  if (is_a_Set(*a)) {
733  return boolean(false);
734  } else {
735  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
736  }
737  } else if (is_a<Integer>(*a)
738  and (not down_cast<const Integer &>(*a).is_negative())) {
739  return boolean(true);
740  } else {
741  return boolean(false);
742  }
743 }
744 
745 hash_t Naturals0::__hash__() const
746 {
747  hash_t seed = SYMENGINE_NATURALS0;
748  return seed;
749 }
750 
751 bool Naturals0::__eq__(const Basic &o) const
752 {
753  if (is_a<Naturals0>(o))
754  return true;
755  return false;
756 }
757 
758 int Naturals0::compare(const Basic &o) const
759 {
760  SYMENGINE_ASSERT(is_a<Naturals0>(o))
761  return 0;
762 }
763 
764 const RCP<const Naturals0> &Naturals0::getInstance()
765 {
766  const static auto a = make_rcp<const Naturals0>();
767  return a;
768 }
769 
770 RCP<const Set> EmptySet::set_intersection(const RCP<const Set> &o) const
771 {
772  return emptyset();
773 }
774 
775 RCP<const Set> EmptySet::set_union(const RCP<const Set> &o) const
776 {
777  return o;
778 }
779 
780 RCP<const Set> EmptySet::set_complement(const RCP<const Set> &o) const
781 {
782  return o;
783 }
784 
785 hash_t EmptySet::__hash__() const
786 {
787  hash_t seed = SYMENGINE_EMPTYSET;
788  return seed;
789 }
790 
791 bool EmptySet::__eq__(const Basic &o) const
792 {
793  if (is_a<EmptySet>(o))
794  return true;
795  return false;
796 }
797 
798 int EmptySet::compare(const Basic &o) const
799 {
800  SYMENGINE_ASSERT(is_a<EmptySet>(o))
801  return 0;
802 }
803 
804 const RCP<const EmptySet> &EmptySet::getInstance()
805 {
806  const static auto a = make_rcp<const EmptySet>();
807  return a;
808 }
809 
810 RCP<const Set> UniversalSet::set_intersection(const RCP<const Set> &o) const
811 {
812  return o;
813 }
814 
815 RCP<const Set> UniversalSet::set_union(const RCP<const Set> &o) const
816 {
817  return universalset();
818 }
819 
820 RCP<const Set> UniversalSet::set_complement(const RCP<const Set> &o) const
821 {
822  return emptyset();
823 }
824 
825 hash_t UniversalSet::__hash__() const
826 {
827  hash_t seed = SYMENGINE_UNIVERSALSET;
828  return seed;
829 }
830 
831 bool UniversalSet::__eq__(const Basic &o) const
832 {
833  if (is_a<UniversalSet>(o))
834  return true;
835  return false;
836 }
837 
838 int UniversalSet::compare(const Basic &o) const
839 {
840  SYMENGINE_ASSERT(is_a<UniversalSet>(o))
841  return 0;
842 }
843 
844 const RCP<const UniversalSet> &UniversalSet::getInstance()
845 {
846  const static auto a = make_rcp<const UniversalSet>();
847  return a;
848 }
849 
850 FiniteSet::FiniteSet(const set_basic &container) : container_(container)
851 {
852  SYMENGINE_ASSIGN_TYPEID()
853  SYMENGINE_ASSERT(FiniteSet::is_canonical(container_));
854 }
855 
856 bool FiniteSet::is_canonical(const set_basic &container)
857 {
858  return container.size() != 0;
859 }
860 
861 hash_t FiniteSet::__hash__() const
862 {
863  hash_t seed = SYMENGINE_FINITESET;
864  for (const auto &a : container_)
865  hash_combine<Basic>(seed, *a);
866  return seed;
867 }
868 
869 bool FiniteSet::__eq__(const Basic &o) const
870 {
871  if (is_a<FiniteSet>(o)) {
872  const FiniteSet &other = down_cast<const FiniteSet &>(o);
873  return unified_eq(container_, other.container_);
874  }
875  return false;
876 }
877 
878 int FiniteSet::compare(const Basic &o) const
879 {
880  // compares two FiniteSet based on their length
881  SYMENGINE_ASSERT(is_a<FiniteSet>(o))
882  const FiniteSet &other = down_cast<const FiniteSet &>(o);
883  return unified_compare(container_, other.container_);
884 }
885 
886 RCP<const Boolean> FiniteSet::contains(const RCP<const Basic> &a) const
887 {
888  set_basic rest;
889  for (const auto &elem : container_) {
890  auto cont = Eq(elem, a);
891  if (eq(*cont, *boolTrue))
892  return boolTrue;
893  if (not eq(*cont, *boolFalse))
894  rest.insert(elem);
895  }
896  if (rest.empty()) {
897  return boolFalse;
898  } else {
899  return make_rcp<Contains>(a, finiteset(rest));
900  }
901 }
902 
903 RCP<const Set> FiniteSet::set_union(const RCP<const Set> &o) const
904 {
905  if (is_a<FiniteSet>(*o)) {
906  const FiniteSet &other = down_cast<const FiniteSet &>(*o);
907  set_basic container;
908  std::set_union(container_.begin(), container_.end(),
909  other.container_.begin(), other.container_.end(),
910  std::inserter(container, container.begin()),
911  RCPBasicKeyLess{});
912  return finiteset(container);
913  }
914  if (is_a<Interval>(*o)) {
915  set_basic container;
916  const Interval &other = down_cast<const Interval &>(*o);
917  bool left = other.get_left_open(), right = other.get_right_open();
918  for (const auto &a : container_) {
919  auto contain = o->contains(a);
920  if (eq(*contain, *boolFalse)) {
921  if (left)
922  if (eq(*other.get_start(), *a)) {
923  left = false;
924  continue;
925  }
926  if (right)
927  if (eq(*other.get_end(), *a)) {
928  right = false;
929  continue;
930  }
931  container.insert(a);
932  } else if (is_a<Contains>(*contain)) {
933  container.insert(a);
934  }
935  }
936  if (not container.empty()) {
937  if (left == other.get_left_open()
938  and right == other.get_right_open()) {
939  return SymEngine::make_set_union({finiteset(container), o});
940  } else {
941  return SymEngine::make_set_union(
942  set_set({finiteset(container),
943  interval(other.get_start(), other.get_end(), left,
944  right)}));
945  }
946  } else {
947  if (left == other.get_left_open()
948  and right == other.get_right_open()) {
949  return o;
950  } else {
951  return interval(other.get_start(), other.get_end(), left,
952  right);
953  }
954  }
955  }
956  if (is_a<Complexes>(*o)) {
957  set_basic container;
958  for (const auto &elem : container_) {
959  if (!is_a_Number(*elem)) {
960  container.insert(elem);
961  }
962  }
963  if (container.empty()) {
964  return complexes();
965  } else {
966  return SymEngine::make_set_union(
967  {complexes(), finiteset(container)});
968  }
969  }
970  if (is_a<Reals>(*o)) {
971  set_basic container;
972  for (const auto &elem : container_) {
973  if (!is_a_Number(*elem)
974  || down_cast<const Number &>(*elem).is_complex()) {
975  container.insert(elem);
976  }
977  }
978  if (container.empty()) {
979  return reals();
980  } else {
981  return SymEngine::make_set_union({reals(), finiteset(container)});
982  }
983  }
984  if (is_a<Rationals>(*o)) {
985  set_basic container;
986  for (const auto &elem : container_) {
987  if (!is_a_Number(*elem)
988  || down_cast<const Number &>(*elem).is_complex()) {
989  container.insert(elem);
990  }
991  }
992  if (container.empty()) {
993  return rationals();
994  } else {
995  return SymEngine::make_set_union(
996  {rationals(), finiteset(container)});
997  }
998  }
999  if (is_a<Integers>(*o) or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
1000  set_basic container;
1001  for (const auto &elem : container_) {
1002  if (is_a<Integers>(*o)) {
1003  if (not is_a<Integer>(*elem)) {
1004  container.insert(elem);
1005  }
1006  } else if (is_a<Naturals>(*o)) {
1007  if (not(is_a<Integer>(*elem)
1008  and down_cast<const Integer &>(*elem).is_positive())) {
1009  container.insert(elem);
1010  }
1011  } else {
1012  if (not(is_a<Integer>(*elem)
1013  and not down_cast<const Integer &>(*elem)
1014  .is_negative())) {
1015  container.insert(elem);
1016  }
1017  }
1018  }
1019  if (container.empty()) {
1020  return o;
1021  } else {
1022  return SymEngine::make_set_union({o, finiteset(container)});
1023  }
1024  }
1025  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<Union>(*o)) {
1026  return (*o).set_union(rcp_from_this_cast<const Set>());
1027  }
1028  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
1029 }
1030 
1031 RCP<const Set> FiniteSet::set_intersection(const RCP<const Set> &o) const
1032 {
1033  if (is_a<FiniteSet>(*o)) {
1034  return SymEngine::set_intersection(
1035  {rcp_from_this_cast<const Set>(), o});
1036  }
1037  if (is_a<Interval>(*o)) {
1038  set_basic container;
1039  for (const auto &a : container_) {
1040  auto contain = o->contains(a);
1041  if (eq(*contain, *boolTrue))
1042  container.insert(a);
1043  if (is_a<Contains>(*contain))
1044  return make_set_intersection(
1045  {rcp_from_this_cast<const Set>(), o});
1046  }
1047  return finiteset(container);
1048  }
1049  if (is_a<Complexes>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)) {
1050  set_basic kept;
1051  set_basic others;
1052  for (const auto &elem : container_) {
1053  if (is_a_Number(*elem)) {
1054  if (!down_cast<const Number &>(*elem).is_complex()) {
1055  if (!is_a<Rationals>(*o)
1056  or down_cast<const Number &>(*elem).is_exact()) {
1057  kept.insert(elem);
1058  }
1059  } else {
1060  if (is_a<Complexes>(*o)) {
1061  kept.insert(elem);
1062  }
1063  }
1064  } else {
1065  others.insert(elem);
1066  }
1067  }
1068  if (kept.empty()) {
1069  if (others.empty()) {
1070  return emptyset();
1071  } else {
1072  return SymEngine::make_set_intersection({o, finiteset(others)});
1073  }
1074  } else {
1075  if (others.empty()) {
1076  return finiteset(kept);
1077  } else {
1078  others.insert(kept.begin(), kept.end());
1079  return SymEngine::make_set_intersection({o, finiteset(others)});
1080  }
1081  }
1082  }
1083  if (is_a<Integers>(*o) or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
1084  set_basic kept_integers;
1085  set_basic others;
1086  for (const auto &elem : container_) {
1087  if (is_a_Number(*elem)) {
1088  if (is_a<Integers>(*o) and is_a<Integer>(*elem)) {
1089  kept_integers.insert(elem);
1090  } else if (is_a<Naturals>(*o) and is_a<Integer>(*elem)
1091  and down_cast<const Integer &>(*elem)
1092  .is_positive()) {
1093  kept_integers.insert(elem);
1094  } else if (is_a<Naturals0>(*o) and is_a<Integer>(*elem)
1095  and (not down_cast<const Integer &>(*elem)
1096  .is_negative())) {
1097  kept_integers.insert(elem);
1098  }
1099  } else {
1100  others.insert(elem);
1101  }
1102  }
1103  if (kept_integers.empty()) {
1104  if (others.empty()) {
1105  return emptyset();
1106  } else {
1107  return SymEngine::make_set_intersection(
1108  {integers(), finiteset(others)});
1109  }
1110  } else {
1111  if (others.empty()) {
1112  return finiteset(kept_integers);
1113  } else {
1114  others.insert(kept_integers.begin(), kept_integers.end());
1115  return SymEngine::make_set_intersection(
1116  {integers(), finiteset(others)});
1117  }
1118  }
1119  }
1120  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<Union>(*o)) {
1121  return (*o).set_intersection(rcp_from_this_cast<const Set>());
1122  }
1123  return make_set_intersection({rcp_from_this_cast<const Set>(), o});
1124 }
1125 
1126 RCP<const Set> FiniteSet::set_complement(const RCP<const Set> &o) const
1127 {
1128  if (is_a<FiniteSet>(*o)) {
1129  const FiniteSet &other = down_cast<const FiniteSet &>(*o);
1130  set_basic container;
1131  std::set_difference(other.container_.begin(), other.container_.end(),
1132  container_.begin(), container_.end(),
1133  std::inserter(container, container.begin()),
1134  RCPBasicKeyLess{});
1135  return finiteset(container);
1136  }
1137 
1138  if (is_a<Interval>(*o)) {
1139  set_set intervals;
1140  auto &other = down_cast<const Interval &>(*o);
1141  RCP<const Number> last = other.get_start();
1142  RCP<const Number> a_num;
1143  set_basic rest;
1144  bool left_open = other.get_left_open(),
1145  right_open = other.get_right_open();
1146  for (auto it = container_.begin(); it != container_.end(); it++) {
1147  if (eq(*max({*it, other.get_start()}), *other.get_start())) {
1148  if (eq(**it, *other.get_start()))
1149  left_open = true;
1150  continue;
1151  }
1152  if (eq(*max({*it, other.get_end()}), **it)) {
1153  if (eq(**it, *other.get_end()))
1154  right_open = true;
1155  break;
1156  }
1157  if (is_a_Number(**it)) {
1158  a_num = rcp_static_cast<const Number>(*it);
1159  intervals.insert(interval(last, a_num, left_open, true));
1160  last = a_num;
1161  left_open = true;
1162  } else {
1163  rest.insert(*it);
1164  }
1165  }
1166 
1167  if (eq(*max({last, other.get_end()}), *other.get_end())) {
1168  intervals.insert(
1169  interval(last, other.get_end(), left_open, right_open));
1170  }
1171  if (rest.empty()) {
1172  return SymEngine::make_set_union(intervals);
1173  } else {
1174  return make_rcp<const Complement>(
1175  SymEngine::make_set_union(intervals), finiteset(rest));
1176  }
1177  }
1178 
1179  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
1180 }
1181 
1182 RCP<const Set> FiniteSet::create(const set_basic &container) const
1183 {
1184  return finiteset(container);
1185 }
1186 
1187 Union::Union(const set_set &in)
1188  : container_(in){SYMENGINE_ASSIGN_TYPEID()
1189  SYMENGINE_ASSERT(Union::is_canonical(in))}
1190 
1191  hash_t Union::__hash__() const
1192 {
1193  hash_t seed = SYMENGINE_UNION;
1194  for (const auto &a : container_)
1195  hash_combine<Basic>(seed, *a);
1196  return seed;
1197 }
1198 
1199 bool Union::__eq__(const Basic &o) const
1200 {
1201  if (is_a<Union>(o)) {
1202  const Union &other = down_cast<const Union &>(o);
1203  return unified_eq(container_, other.container_);
1204  }
1205  return false;
1206 }
1207 
1208 bool Union::is_canonical(const set_set &in)
1209 {
1210  if (in.size() <= 1)
1211  return false;
1212  int count = 0;
1213  for (const auto &s : in) {
1214  if (is_a<FiniteSet>(*s)) {
1215  count++;
1216  }
1217  if (count >= 2)
1218  return false;
1219  }
1220  return true;
1221 }
1222 
1223 int Union::compare(const Basic &o) const
1224 {
1225  SYMENGINE_ASSERT(is_a<Union>(o))
1226  const Union &other = down_cast<const Union &>(o);
1227  return unified_compare(container_, other.container_);
1228 }
1229 
1230 RCP<const Set> Union::set_union(const RCP<const Set> &o) const
1231 {
1232  set_set container(container_);
1233  for (auto iter = container.begin(); iter != container.end(); ++iter) {
1234  auto temp = o->set_union(*iter);
1235  // If we are able to do union with `*iter`, we replace `*iter` with
1236  // the result of union.
1237  auto un = SymEngine::make_set_union({o, *iter});
1238  if (not eq(*temp, *un)) {
1239  iter = container.erase(iter);
1240  container.insert(temp);
1241  return SymEngine::set_union(container);
1242  }
1243  }
1244  container.insert(o);
1245  return SymEngine::make_set_union(container);
1246 }
1247 
1248 RCP<const Set> Union::set_intersection(const RCP<const Set> &o) const
1249 {
1250  set_set container;
1251  for (auto &a : container_) {
1252  container.insert(a->set_intersection(o));
1253  }
1254  return SymEngine::set_union(container);
1255 }
1256 
1257 RCP<const Set> Union::set_complement(const RCP<const Set> &o) const
1258 {
1259  set_set container;
1260  for (auto &a : container_) {
1261  container.insert(a->set_complement(o));
1262  }
1263  return SymEngine::set_intersection(container);
1264 }
1265 
1266 RCP<const Boolean> Union::contains(const RCP<const Basic> &o) const
1267 {
1268  for (auto &a : container_) {
1269  auto contain = a->contains(o);
1270  if (eq(*contain, *boolTrue)) {
1271  return boolean(true);
1272  }
1273  if (is_a<Contains>(*contain))
1274  throw NotImplementedError("Not implemented");
1275  }
1276  return boolean(false);
1277 }
1278 
1279 RCP<const Set> Union::create(const set_set &in) const
1280 {
1281  return SymEngine::set_union(in);
1282 }
1283 
1285 {
1286  vec_basic v(container_.begin(), container_.end());
1287  return v;
1288 }
1289 
1290 Intersection::Intersection(const set_set &in)
1291  : container_(in){SYMENGINE_ASSIGN_TYPEID()
1292  SYMENGINE_ASSERT(Intersection::is_canonical(in))}
1293 
1294  hash_t Intersection::__hash__() const
1295 {
1296  hash_t seed = SYMENGINE_INTERSECTION;
1297  for (const auto &a : container_)
1298  hash_combine<Basic>(seed, *a);
1299  return seed;
1300 }
1301 
1302 bool Intersection::__eq__(const Basic &o) const
1303 {
1304  if (is_a<Intersection>(o)) {
1305  const Intersection &other = down_cast<const Intersection &>(o);
1306  return unified_eq(container_, other.container_);
1307  }
1308  return false;
1309 }
1310 
1311 bool Intersection::is_canonical(const set_set &in)
1312 {
1313  if (in.size() <= 1)
1314  return false;
1315  return true;
1316 }
1317 
1318 int Intersection::compare(const Basic &o) const
1319 {
1320  SYMENGINE_ASSERT(is_a<Intersection>(o))
1321  const Intersection &other = down_cast<const Intersection &>(o);
1322  return unified_compare(container_, other.container_);
1323 }
1324 
1325 RCP<const Set> Intersection::set_union(const RCP<const Set> &o) const
1326 {
1327  set_set container;
1328  for (auto &a : container_) {
1329  container.insert(a->set_union(o));
1330  }
1331  return SymEngine::set_intersection(container);
1332 }
1333 
1334 RCP<const Set> Intersection::set_intersection(const RCP<const Set> &o) const
1335 {
1336  set_set container(container_);
1337  for (auto iter = container.begin(); iter != container.end(); ++iter) {
1338  auto temp = o->set_intersection(*iter);
1339  // If we are able to do intersection with `*iter`, we replace `*iter`
1340  // with the result of intersection.
1341  auto un = SymEngine::make_set_intersection({o, *iter});
1342  if (not eq(*temp, *un)) {
1343  iter = container.erase(iter);
1344  container.insert(temp);
1345  return SymEngine::set_intersection(container);
1346  }
1347  }
1348  container.insert(o);
1349  return SymEngine::make_set_intersection(container);
1350 }
1351 
1352 RCP<const Set> Intersection::set_complement(const RCP<const Set> &o) const
1353 {
1354  set_set container;
1355  for (auto &a : container_) {
1356  container.insert(a->set_complement(o));
1357  }
1358  return SymEngine::set_intersection(container);
1359 }
1360 
1361 RCP<const Boolean> Intersection::contains(const RCP<const Basic> &o) const
1362 {
1363  for (auto &a : container_) {
1364  auto contain = a->contains(o);
1365  if (eq(*contain, *boolTrue)) {
1366  return boolean(true);
1367  }
1368  if (is_a<Contains>(*contain))
1369  throw NotImplementedError("Not implemented");
1370  }
1371  return boolean(false);
1372 }
1373 
1374 RCP<const Set> Intersection::create(const set_set &in) const
1375 {
1376  return SymEngine::set_intersection(in);
1377 }
1378 
1380 {
1381  vec_basic v(container_.begin(), container_.end());
1382  return v;
1383 }
1384 
1385 Complement::Complement(const RCP<const Set> &universe,
1386  const RCP<const Set> &container)
1387  : universe_(universe), container_(container){SYMENGINE_ASSIGN_TYPEID()}
1388 
1389  hash_t Complement::__hash__() const
1390 {
1391  hash_t seed = SYMENGINE_COMPLEMENT;
1392  hash_combine<Basic>(seed, *universe_);
1393  hash_combine<Basic>(seed, *container_);
1394  return seed;
1395 }
1396 
1397 bool Complement::__eq__(const Basic &o) const
1398 {
1399  if (is_a<Complement>(o)) {
1400  const Complement &other = down_cast<const Complement &>(o);
1401  return unified_eq(universe_, other.universe_)
1402  and unified_eq(container_, other.container_);
1403  }
1404  return false;
1405 }
1406 
1407 int Complement::compare(const Basic &o) const
1408 {
1409  SYMENGINE_ASSERT(is_a<Complement>(o))
1410  const Complement &other = down_cast<const Complement &>(o);
1411  int c1 = unified_compare(universe_, other.universe_);
1412  if (c1 != 0) {
1413  return c1;
1414  } else {
1415  return unified_compare(container_, other.container_);
1416  }
1417 }
1418 
1419 RCP<const Boolean> Complement::contains(const RCP<const Basic> &a) const
1420 {
1421  return logical_and(
1422  {universe_->contains(a), logical_not(container_->contains(a))});
1423 }
1424 
1425 RCP<const Set> Complement::set_union(const RCP<const Set> &o) const
1426 {
1427  // A' U C = (A n C')'
1428  RCP<const Set> ocomplement = o->set_complement(universe_);
1429  RCP<const Set> intersect
1430  = SymEngine::set_intersection({container_, ocomplement});
1431  return intersect->set_complement(universe_);
1432 }
1433 
1434 RCP<const Set> Complement::set_intersection(const RCP<const Set> &o) const
1435 {
1436  return SymEngine::set_intersection({rcp_from_this_cast<const Set>(), o});
1437 }
1438 
1439 RCP<const Set> Complement::set_complement(const RCP<const Set> &o) const
1440 {
1441  auto newuniv = SymEngine::set_union({o, universe_});
1442  return container_->set_complement(newuniv);
1443 }
1444 
1445 ConditionSet::ConditionSet(const RCP<const Basic> &sym,
1446  const RCP<const Boolean> &condition)
1447  : sym(sym), condition_(condition)
1448 {
1449  SYMENGINE_ASSIGN_TYPEID()
1450  SYMENGINE_ASSERT(ConditionSet::is_canonical(sym, condition))
1451 }
1452 
1453 bool ConditionSet::is_canonical(const RCP<const Basic> &sym,
1454  const RCP<const Boolean> &condition)
1455 {
1456  if (eq(*condition, *boolFalse) or eq(*condition, *boolTrue)
1457  or not is_a_sub<Symbol>(*sym)) {
1458  return false;
1459  } else if (is_a<Contains>(*condition)) {
1460  return false;
1461  }
1462  return true;
1463 }
1464 
1466 {
1467  hash_t seed = SYMENGINE_CONDITIONSET;
1468  hash_combine<Basic>(seed, *sym);
1469  hash_combine<Basic>(seed, *condition_);
1470  return seed;
1471 }
1472 
1473 bool ConditionSet::__eq__(const Basic &o) const
1474 {
1475  if (is_a<ConditionSet>(o)) {
1476  const ConditionSet &other = down_cast<const ConditionSet &>(o);
1477  return unified_eq(sym, other.get_symbol())
1478  and unified_eq(condition_, other.get_condition());
1479  }
1480  return false;
1481 }
1482 
1483 int ConditionSet::compare(const Basic &o) const
1484 {
1485  SYMENGINE_ASSERT(is_a<ConditionSet>(o))
1486  const ConditionSet &other = down_cast<const ConditionSet &>(o);
1487  int c1 = unified_compare(sym, other.get_symbol());
1488  if (c1 != 0) {
1489  return c1;
1490  } else {
1491  return unified_compare(condition_, other.get_condition());
1492  }
1493 }
1494 
1495 RCP<const Set> ConditionSet::set_union(const RCP<const Set> &o) const
1496 {
1497  return SymEngine::make_set_union({o, rcp_from_this_cast<const Set>()});
1498 }
1499 
1500 RCP<const Set> ConditionSet::set_intersection(const RCP<const Set> &o) const
1501 {
1502  if (not is_a<ConditionSet>(*o)) {
1503  return conditionset(sym, logical_and({condition_, o->contains(sym)}));
1504  }
1505  return make_set_intersection({rcp_from_this_cast<const Set>(), o});
1506 }
1507 
1508 RCP<const Set> ConditionSet::set_complement(const RCP<const Set> &o) const
1509 {
1510  return make_rcp<const Complement>(o, rcp_from_this_cast<const Set>());
1511 }
1512 
1513 RCP<const Boolean> ConditionSet::contains(const RCP<const Basic> &o) const
1514 {
1515  map_basic_basic d;
1516  d[sym] = o;
1517  auto cond = condition_->subs(d);
1518  if (not is_a_Boolean(*cond)) {
1519  throw SymEngineException("expected an object of type Boolean");
1520  }
1521  return rcp_static_cast<const Boolean>(cond);
1522 }
1523 
1524 ImageSet::ImageSet(const RCP<const Basic> &sym, const RCP<const Basic> &expr,
1525  const RCP<const Set> &base)
1526  : sym_(sym), expr_(expr), base_(base)
1527 {
1528  SYMENGINE_ASSIGN_TYPEID()
1529  SYMENGINE_ASSERT(ImageSet::is_canonical(sym, expr, base));
1530 }
1531 
1532 hash_t ImageSet::__hash__() const
1533 {
1534  hash_t seed = SYMENGINE_IMAGESET;
1535  hash_combine<Basic>(seed, *sym_);
1536  hash_combine<Basic>(seed, *expr_);
1537  hash_combine<Basic>(seed, *base_);
1538  return seed;
1539 }
1540 
1541 bool ImageSet::__eq__(const Basic &o) const
1542 {
1543  if (is_a<ImageSet>(o)) {
1544  const ImageSet &other = down_cast<const ImageSet &>(o);
1545  return unified_eq(sym_, other.sym_) and unified_eq(expr_, other.expr_)
1546  and unified_eq(base_, other.base_);
1547  }
1548  return false;
1549 }
1550 
1551 int ImageSet::compare(const Basic &o) const
1552 {
1553  SYMENGINE_ASSERT(is_a<ImageSet>(o))
1554  const ImageSet &other = down_cast<const ImageSet &>(o);
1555  int c1 = unified_compare(sym_, other.sym_);
1556  if (c1 != 0) {
1557  return c1;
1558  } else {
1559  int c2 = unified_compare(expr_, other.expr_);
1560  if (c2 != 0) {
1561  return c2;
1562  } else {
1563  return unified_compare(base_, other.base_);
1564  }
1565  }
1566 }
1567 
1568 bool ImageSet::is_canonical(const RCP<const Basic> &sym,
1569  const RCP<const Basic> &expr,
1570  const RCP<const Set> &base)
1571 {
1572  if (not is_a_sub<Symbol>(*sym) or eq(*expr, *sym) or is_a_Number(*expr)
1573  or eq(*base, *emptyset()))
1574  return false;
1575  return true;
1576 }
1577 
1578 RCP<const Boolean> ImageSet::contains(const RCP<const Basic> &a) const
1579 {
1580  throw SymEngineException("Not implemented");
1581 }
1582 
1583 RCP<const Set> ImageSet::set_union(const RCP<const Set> &o) const
1584 {
1585  return make_set_union({rcp_from_this_cast<const Set>(), o});
1586 }
1587 
1588 RCP<const Set> ImageSet::set_intersection(const RCP<const Set> &o) const
1589 {
1590  return SymEngine::set_intersection({rcp_from_this_cast<const Set>(), o});
1591 }
1592 
1593 RCP<const Set> ImageSet::set_complement(const RCP<const Set> &o) const
1594 {
1595  return SymEngine::set_complement(rcp_from_this_cast<const Set>(), o);
1596 }
1597 
1598 RCP<const Set> ImageSet::create(const RCP<const Basic> &sym,
1599  const RCP<const Basic> &expr,
1600  const RCP<const Set> &base) const
1601 {
1602  return imageset(sym, expr, base);
1603 }
1604 
1605 RCP<const Set> set_union(const set_set &in)
1606 {
1607  set_set input;
1608  set_basic combined_FiniteSet;
1609  for (auto it = in.begin(); it != in.end(); ++it) {
1610  if (is_a<FiniteSet>(**it)) {
1611  const FiniteSet &other = down_cast<const FiniteSet &>(**it);
1612  combined_FiniteSet.insert(other.get_container().begin(),
1613  other.get_container().end());
1614  } else if (is_a<UniversalSet>(**it)) {
1615  return universalset();
1616  } else if (not is_a<EmptySet>(**it)) {
1617  input.insert(*it);
1618  }
1619  }
1620  if (input.empty()) {
1621  return finiteset(combined_FiniteSet);
1622  } else if (input.size() == 1 && combined_FiniteSet.empty()) {
1623  return *input.begin();
1624  }
1625  // Now we rely on respective containers' own rules
1626  // TODO: Improve it to O(log n)
1627  RCP<const Set> combined_Rest = finiteset(combined_FiniteSet);
1628  for (auto it = input.begin(); it != input.end(); ++it) {
1629  combined_Rest = combined_Rest->set_union(*it);
1630  }
1631  return combined_Rest;
1632 }
1633 
1634 RCP<const Set> set_intersection(const set_set &in)
1635 {
1636  // https://en.wikipedia.org/wiki/Intersection_(set_theory)#Nullary_intersection
1637  if (in.empty())
1638  return universalset();
1639 
1640  // Global rules
1641  // If found any emptyset then return emptyset
1642  set_set incopy;
1643  for (const auto &input : in) {
1644  if (is_a<EmptySet>(*input)) {
1645  return emptyset();
1646  } else if (not is_a<UniversalSet>(*input)) {
1647  incopy.insert(input);
1648  }
1649  }
1650 
1651  if (incopy.empty())
1652  return universalset();
1653  if (incopy.size() == 1)
1654  return *incopy.begin();
1655 
1656  // Handle finite sets
1657  std::vector<RCP<const Set>> fsets, othersets;
1658  for (const auto &input : incopy) {
1659  if (is_a<FiniteSet>(*input)) {
1660  fsets.push_back(input);
1661  } else {
1662  othersets.push_back(input);
1663  }
1664  }
1665  if (fsets.size() != 0) {
1666  const FiniteSet &fs = down_cast<const FiniteSet &>(**fsets.begin());
1667  auto cont = fs.get_container();
1668  fsets.erase(fsets.begin());
1669  set_basic finalfs;
1670  for (const auto &fselement : cont) {
1671  bool present = true;
1672  for (const auto &fset : fsets) {
1673  auto contain = fset->contains(fselement);
1674  if (not(eq(*contain, *boolTrue) or eq(*contain, *boolFalse))) {
1675  return make_set_intersection(incopy);
1676  }
1677  present = present and eq(*contain, *boolTrue);
1678  }
1679  if (!present)
1680  continue;
1681  for (const auto &oset : othersets) {
1682  auto contain = oset->contains(fselement);
1683  if (not(eq(*contain, *boolTrue) or eq(*contain, *boolFalse))) {
1684  return make_set_intersection(incopy);
1685  }
1686  present = present and eq(*contain, *boolTrue);
1687  }
1688  if (present)
1689  finalfs.insert(fselement);
1690  }
1691  return finiteset(finalfs);
1692  }
1693 
1694  // If any of the sets is union, then return a Union of Intersections
1695  for (auto it = incopy.begin(); it != incopy.end(); ++it) {
1696  if (is_a<Union>(**it)) {
1697  auto container = down_cast<const Union &>(**it).get_container();
1698  incopy.erase(it);
1699  auto other = SymEngine::set_intersection(incopy);
1700  set_set usets;
1701  for (const auto &c : container) {
1702  usets.insert(SymEngine::set_intersection({c, other}));
1703  }
1704  return SymEngine::set_union(usets);
1705  }
1706  }
1707 
1708  // Simplify and return a `Complement` if any of the sets is a complement
1709  for (auto it = incopy.begin(); it != incopy.end(); ++it) {
1710  if (is_a<Complement>(**it)) {
1711  auto container
1712  = down_cast<const Complement &>(**it).get_container();
1713  auto universe = down_cast<const Complement &>(**it).get_universe();
1714  incopy.erase(it);
1715  incopy.insert(universe);
1716  auto other = SymEngine::set_intersection(incopy);
1717  return SymEngine::set_complement(other, container);
1718  }
1719  }
1720 
1721  // Pair-wise rules
1722  // TO-DO: needs the following improvement once Intersection
1723  // class is implemented.
1724  // input_oset if found to be not simplified, then skip this
1725  // pair.
1726  if (incopy.size() > 1) {
1727  auto temp = *incopy.begin();
1728  auto it = std::next(incopy.begin());
1729  for (; it != incopy.end(); ++it) {
1730  temp = temp->set_intersection(*it);
1731  }
1732  return temp;
1733  }
1734 
1735  return make_set_intersection(incopy);
1736 }
1737 
1738 // helper to avoid redundant code
1739 RCP<const Set> set_complement_helper(const RCP<const Set> &container,
1740  const RCP<const Set> &universe)
1741 {
1742  if (is_a<Union>(*universe)) {
1743  auto univ = down_cast<const Union &>(*universe).get_container();
1744  set_set container_;
1745  for (auto &a : univ) {
1746  container_.insert(container->set_complement(a));
1747  }
1748  return SymEngine::set_union(container_);
1749  } else if (is_a<EmptySet>(*universe)) {
1750  return emptyset();
1751  } else if (is_a<FiniteSet>(*universe)) {
1752  const FiniteSet &other = down_cast<const FiniteSet &>(*universe);
1753  set_basic container_;
1754  set_basic rest;
1755  for (const auto &a : other.get_container()) {
1756  auto contain = container->contains(a);
1757  if (eq(*contain, *boolFalse)) {
1758  container_.insert(a);
1759  } else if (is_a<Contains>(*contain)) {
1760  rest.insert(a);
1761  }
1762  }
1763  if (rest.empty()) {
1764  return finiteset(container_);
1765  } else {
1766  return SymEngine::set_union(
1767  {finiteset(container_),
1768  make_rcp<const Complement>(finiteset(rest), container)});
1769  }
1770  }
1771  return make_rcp<const Complement>(universe, container);
1772 }
1773 
1774 RCP<const Set> set_complement(const RCP<const Set> &universe,
1775  const RCP<const Set> &container)
1776 {
1777  // represents universe - container
1778  return container->set_complement(universe);
1779 }
1780 
1781 RCP<const Set> conditionset(const RCP<const Basic> &sym,
1782  const RCP<const Boolean> &condition)
1783 {
1784  if (eq(*condition, *boolean(false))) {
1785  return emptyset();
1786  } else if (eq(*condition, *boolean(true))) {
1787  return universalset();
1788  }
1789  if (is_a<And>(*condition)) {
1790  auto cont = down_cast<const And &>(*condition).get_container();
1791  set_boolean newcont;
1792  set_basic present, others;
1793  for (auto it = cont.begin(); it != cont.end(); it++) {
1794  if (is_a<Contains>(**it)
1795  and eq(*down_cast<const Contains &>(**it).get_expr(), *sym)
1796  and is_a<FiniteSet>(
1797  *down_cast<const Contains &>(**it).get_set())) {
1798  auto fset = down_cast<const Contains &>(**it).get_set();
1799  auto fcont
1800  = down_cast<const FiniteSet &>(*fset).get_container();
1801  // use the result of simplification done in `logical_and()`
1802  for (const auto &elem : fcont) {
1803  if (not(is_a_Number(*elem) or is_a<Constant>(*elem))) {
1804  others.insert(elem);
1805  } else {
1806  // logical_and() doesn't guarantee that if element of a
1807  // finiteset is a number, then it satisfies other
1808  // conditions
1809  // it only assures that there doesn't exist any such
1810  // element of finiteset that surely fails in other
1811  // conditions.
1812  auto restCont = cont;
1813  restCont.erase(*it);
1814  auto restCond = logical_and(restCont);
1815  map_basic_basic d;
1816  d[sym] = elem;
1817  auto contain = restCond->subs(d);
1818  if (eq(*contain, *boolean(true))) {
1819  present.insert(elem);
1820  } else if (not eq(*contain, *boolean(false))) {
1821  others.insert(elem);
1822  } else {
1823  throw SymEngineException("element should have "
1824  "been removed within "
1825  "logical_and()");
1826  }
1827  }
1828  }
1829  } else {
1830  newcont.insert(*it);
1831  }
1832  }
1833  if (not present.empty()) {
1834  newcont.insert(finiteset(others)->contains(sym));
1835  return SymEngine::set_union(
1836  {finiteset(present), conditionset(sym, logical_and(newcont))});
1837  }
1838  }
1839  if (is_a<Contains>(*condition)) {
1840  return down_cast<const Contains &>(*condition).get_set();
1841  }
1842  return make_rcp<const ConditionSet>(sym, condition);
1843 }
1844 
1845 } // namespace SymEngine
Classes and functions relating to the binary operation of addition.
T begin(T... args)
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
Definition: add.cpp:425
The lowest unit of symbolic representation.
Definition: basic.h:97
Basic()
Constructor.
Definition: basic.h:120
int compare(const Basic &o) const override
Definition: sets.cpp:1407
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1397
hash_t __hash__() const override
Definition: sets.cpp:1389
int compare(const Basic &o) const override
Definition: sets.cpp:1483
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1473
hash_t __hash__() const override
Definition: sets.cpp:1465
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:869
int compare(const Basic &o) const override
Definition: sets.cpp:878
hash_t __hash__() const override
Definition: sets.cpp:861
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1541
int compare(const Basic &o) const override
Definition: sets.cpp:1551
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1302
vec_basic get_args() const override
Returns the list of arguments.
Definition: sets.cpp:1379
int compare(const Basic &o) const override
Definition: sets.cpp:1318
hash_t __hash__() const override
Definition: sets.cpp:1191
int compare(const Basic &o) const override
Definition: sets.cpp:1223
vec_basic get_args() const override
Returns the list of arguments.
Definition: sets.cpp:1284
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1199
T empty(T... args)
T end(T... args)
T erase(T... args)
T insert(T... args)
T inserter(T... args)
T left(T... args)
T max(T... args)
T min(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
bool is_a_Number(const Basic &b)
Definition: number.h:130
RCP< const Set > interval(const RCP< const Number > &start, const RCP< const Number > &end, const bool left_open=false, const bool right_open=false)
Definition: sets.h:611
RCP< const Boolean > Ge(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Convenience function returning LessThan object.
Definition: logic.cpp:733
RCP< const Complexes > complexes()
Definition: sets.h:554
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
Definition: integer.h:197
RCP< const Reals > reals()
Definition: sets.h:560
RCP< const Basic > max(const vec_basic &arg)
Canonicalize Max:
Definition: functions.cpp:3555
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21
RCP< const Boolean > Lt(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Returns the canonicalized StrictLessThan object from the arguments.
Definition: logic.cpp:757
RCP< const Naturals > naturals()
Definition: sets.h:578
RCP< const EmptySet > emptyset()
Definition: sets.h:590
RCP< const Basic > ceiling(const RCP< const Basic > &arg)
Canonicalize Ceiling:
Definition: functions.cpp:705
RCP< const Integers > integers()
Definition: sets.h:572
RCP< const UniversalSet > universalset()
Definition: sets.h:596
RCP< const Basic > floor(const RCP< const Basic > &arg)
Canonicalize Floor:
Definition: functions.cpp:611
RCP< const Set > conditionset(const RCP< const Basic > &sym, const RCP< const Boolean > &condition)
Definition: sets.cpp:1781
RCP< const Boolean > Eq(const RCP< const Basic > &lhs)
Returns the canonicalized Equality object from a single argument.
Definition: logic.cpp:642
RCP< const Set > finiteset(const set_basic &container)
Definition: sets.h:602
int unified_compare(const T &a, const T &b)
Definition: dict.h:205
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
Definition: basic-inl.h:29
RCP< const Naturals0 > naturals0()
Definition: sets.h:584
RCP< const Rationals > rationals()
Definition: sets.h:566
T next(T... args)
T push_back(T... args)
T set_difference(T... args)
T set_union(T... args)
T size(T... args)