Skip to content

Commit 754e150

Browse files
committed
Added Tests and Wrapped solve()
1 parent d243265 commit 754e150

File tree

7 files changed

+336
-45
lines changed

7 files changed

+336
-45
lines changed

symengine/lib/symengine.pxd

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ cdef extern from "<symengine/basic.h>" namespace "SymEngine":
206206
ctypedef map[RCP[Integer], unsigned] map_integer_uint "SymEngine::map_integer_uint"
207207
cdef struct RCPIntegerKeyLess
208208
cdef struct RCPBasicKeyLess
209-
ctypedef set[RCP[Basic], RCPBasicKeyLess] set_basic "SymEngine::set_basic"
209+
ctypedef set[RCP[const_Basic], RCPBasicKeyLess] set_basic "SymEngine::set_basic"
210210
ctypedef multiset[RCP[const_Basic], RCPBasicKeyLess] multiset_basic "SymEngine::multiset_basic"
211211
cdef cppclass Basic:
212212
string __str__() nogil except +
@@ -1022,3 +1022,7 @@ cdef extern from "<symengine/sets.h>" namespace "SymEngine":
10221022
cdef RCP[const Set] set_complement(RCP[const Set] &universe, RCP[const Set] &container) nogil except +
10231023
cdef RCP[const Set] conditionset(RCP[const Basic] &sym, RCP[const Boolean] &condition) nogil except +
10241024
cdef RCP[const Set] imageset(RCP[const Basic] &sym, RCP[const Basic] &expr, RCP[const Set] &base) nogil except +
1025+
1026+
cdef extern from "<symengine/solve.h>" namespace "SymEngine":
1027+
cdef RCP[const Set] solve(RCP[const Basic] &f, RCP[const Symbol] &sym) nogil except +
1028+
cdef RCP[const Set] solve(RCP[const Basic] &f, RCP[const Symbol] &sym, RCP[const Set] &domain) nogil except +

symengine/lib/symengine_wrapper.pyx

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -183,25 +183,25 @@ cdef c2py(RCP[const symengine.Basic] o):
183183
elif (symengine.is_a_PyNumber(deref(o))):
184184
r = PyNumber.__new__(PyNumber)
185185
elif (symengine.is_a_Piecewise(deref(o))):
186-
r = Piecewise.__new__(Piecewise)
186+
r = Basic.__new__(Piecewise)
187187
elif (symengine.is_a_Contains(deref(o))):
188-
r = Contains.__new__(Contains)
188+
r = Boolean.__new__(Contains)
189189
elif (symengine.is_a_Interval(deref(o))):
190-
r = Interval.__new__(Interval)
190+
r = Set.__new__(Interval)
191191
elif (symengine.is_a_EmptySet(deref(o))):
192-
r = EmptySet.__new__(EmptySet)
192+
r = Set.__new__(EmptySet)
193193
elif (symengine.is_a_UniversalSet(deref(o))):
194-
r = UniversalSet.__new__(UniversalSet)
194+
r = Set.__new__(UniversalSet)
195195
elif (symengine.is_a_FiniteSet(deref(o))):
196-
r = FiniteSet.__new__(FiniteSet)
196+
r = Set.__new__(FiniteSet)
197197
elif (symengine.is_a_Union(deref(o))):
198-
r = Union.__new__(Union)
198+
r = Set.__new__(Union)
199199
elif (symengine.is_a_Complement(deref(o))):
200-
r = Complement.__new__(Complement)
200+
r = Set.__new__(Complement)
201201
elif (symengine.is_a_ConditionSet(deref(o))):
202-
r = ConditionSet.__new__(ConditionSet)
202+
r = Set.__new__(ConditionSet)
203203
elif (symengine.is_a_ImageSet(deref(o))):
204-
r = ImageSet.__new__(ImageSet)
204+
r = Set.__new__(ImageSet)
205205
elif (symengine.is_a_And(deref(o))):
206206
r = Boolean.__new__(And)
207207
elif (symengine.is_a_Not(deref(o))):
@@ -380,13 +380,11 @@ def sympy2symengine(a, raise_error=False):
380380
elif isinstance(a, sympy.Not):
381381
return logical_not(a.args[0])
382382
elif isinstance(a, sympy.Nor):
383-
return logical_nor(*a.args)
383+
return Nor(*a.args)
384384
elif isinstance(a, sympy.Nand):
385-
return logical_nand(*a.args)
385+
return Nand(*a.args)
386386
elif isinstance(a, sympy.Xor):
387387
return logical_xor(*a.args)
388-
elif isinstance(a, sympy.Xnor):
389-
return logical_xnor(*a.args)
390388
elif isinstance(a, sympy.gamma):
391389
return gamma(a.args[0])
392390
elif isinstance(a, sympy.Derivative):
@@ -400,10 +398,8 @@ def sympy2symengine(a, raise_error=False):
400398
return piecewise(*(a.args))
401399
elif isinstance(a, sympy.Interval):
402400
return interval(*(a.args))
403-
elif isinstance(a, sympy.S.EmptySet):
401+
elif isinstance(a, sympy.EmptySet):
404402
return emptyset()
405-
elif isinstance(a, sympy.S.UniversalSet):
406-
return universalset()
407403
elif isinstance(a, sympy.FiniteSet):
408404
return finiteset(*(a.args))
409405
elif isinstance(a, sympy.Contains):
@@ -414,8 +410,6 @@ def sympy2symengine(a, raise_error=False):
414410
return set_intersection(*(a.args))
415411
elif isinstance(a, sympy.Complement):
416412
return set_complement(*(a.args))
417-
elif isinstance(a, sympy.ConditionSet):
418-
return conditionset(*(a.args))
419413
elif isinstance(a, sympy.ImageSet):
420414
return imageset(*(a.args))
421415
elif isinstance(a, sympy.Function):
@@ -439,6 +433,8 @@ def sympy2symengine(a, raise_error=False):
439433
return acsch(a.args[0])
440434
elif isinstance(a, sympy.asech):
441435
return asech(a.args[0])
436+
elif isinstance(a, sympy.ConditionSet):
437+
return conditionset(*(a.args))
442438

443439
if raise_error:
444440
raise SympifyError("sympy2symengine: Cannot convert '%r' to a symengine type." % a)
@@ -1171,7 +1167,8 @@ class Not(Boolean):
11711167

11721168
def _sympy_(self):
11731169
import sympy
1174-
return sympy.Not(c2py(<RCP[const symengine.Basic]>(self.args[0])._sympy_()))
1170+
s = self.args_as_sympy()[0]
1171+
return sympy.Not(s)
11751172

11761173

11771174
class Xor(Boolean):
@@ -2577,6 +2574,10 @@ class EmptySet(Set):
25772574
import sympy
25782575
return sympy.EmptySet()
25792576

2577+
@property
2578+
def func(self):
2579+
return self.__class__
2580+
25802581

25812582
class UniversalSet(Set):
25822583

@@ -2585,7 +2586,11 @@ class UniversalSet(Set):
25852586

25862587
def _sympy_(self):
25872588
import sympy
2588-
return sympy.UniversalSet()
2589+
return sympy.S.UniversalSet
2590+
2591+
@property
2592+
def func(self):
2593+
return self.__class__
25892594

25902595

25912596
class FiniteSet(Set):
@@ -2633,19 +2638,12 @@ class ConditionSet(Set):
26332638
def __new__(self, sym, condition):
26342639
return conditionset(sym, condition)
26352640

2636-
def _sympy_(self):
2637-
import sympy
2638-
return sympy.ConditionSet(*[arg._sympy_() for arg in self.args])
2639-
26402641

26412642
class ImageSet(Set):
26422643

26432644
def __new__(self, sym, expr, base):
26442645
return imageset(sym, expr, base)
26452646

2646-
def _sympy_(self):
2647-
import sympy
2648-
return sympy.ImageSet(*[arg._sympy_() for arg in self.args])
26492647

26502648

26512649
cdef class MatrixBase:
@@ -3556,29 +3554,27 @@ def logical_or(*args):
35563554
s.insert(symengine.rcp_static_cast_Boolean(e_.thisptr))
35573555
return c2py(<RCP[const symengine.Basic]>(symengine.logical_or(s)))
35583556

3559-
def logical_nor(*args):
3557+
def Nor(*args):
35603558
cdef symengine.set_boolean s
35613559
cdef Boolean e_
35623560
for e in args:
35633561
e_ = sympify(e)
35643562
s.insert(symengine.rcp_static_cast_Boolean(e_.thisptr))
35653563
return c2py(<RCP[const symengine.Basic]>(symengine.logical_nor(s)))
35663564

3567-
Nor = logical_nor
3568-
3569-
def logical_nand(*args):
3565+
def Nand(*args):
35703566
cdef symengine.set_boolean s
35713567
cdef Boolean e_
35723568
for e in args:
35733569
e_ = sympify(e)
35743570
s.insert(symengine.rcp_static_cast_Boolean(e_.thisptr))
35753571
return c2py(<RCP[const symengine.Basic]>(symengine.logical_nand(s)))
35763572

3577-
Nand = logical_nand
3578-
35793573
def logical_not(x):
3580-
cdef Boolean X = sympify(x)
3581-
return c2py(<RCP[const symengine.Basic]>(symengine.logical_not(symengine.rcp_static_cast_Boolean(X.thisptr))))
3574+
cdef Basic x_ = sympify(x)
3575+
require(x_, Boolean)
3576+
cdef RCP[const symengine.Boolean] _x = symengine.rcp_static_cast_Boolean(x_.thisptr)
3577+
return c2py(<RCP[const symengine.Basic]>(symengine.logical_not(_x)))
35823578

35833579
def logical_xor(*args):
35843580
cdef symengine.vec_boolean v
@@ -3588,16 +3584,14 @@ def logical_xor(*args):
35883584
v.push_back(symengine.rcp_static_cast_Boolean(e_.thisptr))
35893585
return c2py(<RCP[const symengine.Basic]>(symengine.logical_xor(v)))
35903586

3591-
def logical_xnor(*args):
3587+
def Xnor(*args):
35923588
cdef symengine.vec_boolean v
35933589
cdef Boolean e_
35943590
for e in args:
35953591
e_ = sympify(e)
35963592
v.push_back(symengine.rcp_static_cast_Boolean(e_.thisptr))
35973593
return c2py(<RCP[const symengine.Basic]>(symengine.logical_xnor(v)))
35983594

3599-
Xnor = logical_xnor
3600-
36013595
def eval_double(x):
36023596
cdef Basic X = sympify(x)
36033597
return c2py(<RCP[const symengine.Basic]>(symengine.real_double(symengine.eval_double(deref(X.thisptr)))))
@@ -3998,7 +3992,6 @@ def powermod(a, b, m):
39983992
cdef RCP[const symengine.Integer] m1 = symengine.rcp_static_cast_Integer(_m.thisptr)
39993993
cdef RCP[const symengine.Number] b1 = symengine.rcp_static_cast_Number(_b.thisptr)
40003994
cdef RCP[const symengine.Integer] root
4001-
40023995
cdef cppbool ret_val = symengine.powermod(symengine.outArg_Integer(root), a1, b1, m1)
40033996
if ret_val == 0:
40043997
return None
@@ -4405,6 +4398,10 @@ def piecewise(*v):
44054398

44064399

44074400
def interval(start, end, left_open=False, right_open=False):
4401+
if isinstance(start, NegativeInfinity):
4402+
left_open = True
4403+
if isinstance(end, Infinity):
4404+
right_open = True
44084405
cdef Number start_ = sympify(start)
44094406
cdef Number end_ = sympify(end)
44104407
cdef cppbool left_open_ = left_open
@@ -4427,7 +4424,7 @@ def finiteset(*args):
44274424
cdef Basic e_
44284425
for e in args:
44294426
e_ = sympify(e)
4430-
s.insert(e_.thisptr)
4427+
s.insert(<RCP[symengine.const_Basic]>(e_.thisptr))
44314428
return c2py(<RCP[const symengine.Basic]>(symengine.finiteset(s)))
44324429

44334430

@@ -4486,5 +4483,18 @@ def imageset(sym, expr, base):
44864483
cdef RCP[const symengine.Set] b = symengine.rcp_static_cast_Set(base_.thisptr)
44874484
return c2py(<RCP[const symengine.Basic]>(symengine.imageset(sym_.thisptr, expr_.thisptr, b)))
44884485

4486+
4487+
def solve(f, sym, domain=None):
4488+
cdef Basic f_ = sympify(f)
4489+
cdef Basic sym_ = sympify(sym)
4490+
require(sym_, Symbol)
4491+
cdef RCP[const symengine.Symbol] x = symengine.rcp_static_cast_Symbol(sym_.thisptr)
4492+
if domain is None:
4493+
return c2py(<RCP[const symengine.Basic]>(symengine.solve(f_.thisptr, x)))
4494+
cdef Set domain_ = sympify(domain)
4495+
cdef RCP[const symengine.Set] d = symengine.rcp_static_cast_Set(domain_.thisptr)
4496+
return c2py(<RCP[const symengine.Basic]>(symengine.solve(f_.thisptr, x, d)))
4497+
4498+
44894499
# Turn on nice stacktraces:
44904500
symengine.print_stack_on_segfault()

symengine/tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ install(FILES __init__.py
1111
test_printing.py
1212
test_sage.py
1313
test_series_expansion.py
14+
test_sets.py
15+
test_solve.py
1416
test_subs.py
1517
test_symbol.py
1618
test_sympify.py

symengine/tests/test_logic.py

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from symengine.utilities import raises
2-
from symengine.lib.symengine_wrapper import (true, false, Eq, Ne,
3-
Ge, Gt, Le, Lt, Symbol, I)
2+
from symengine.lib.symengine_wrapper import (true, false, Eq, Ne, Ge, Gt, Le, Lt, Symbol,
3+
I, And, Or, Not, Nand, Nor, Xor, Xnor, Piecewise,
4+
Contains, Interval, FiniteSet, oo, log)
45

56
x = Symbol("x")
67
y = Symbol("y")
8+
z = Symbol("z")
79

810
def test_relationals():
911
assert Eq(0) == true
@@ -26,8 +28,92 @@ def test_relationals():
2628
assert Eq(I, 2) == false
2729
assert Ne(I, 2) == true
2830

31+
2932
def test_rich_cmp():
3033
assert (x < y) == Lt(x, y)
3134
assert (x <= y) == Le(x, y)
3235
assert (x > y) == Gt(x, y)
3336
assert (x >= y) == Ge(x, y)
37+
38+
39+
def test_And():
40+
assert And() == true
41+
assert And(True) == true
42+
assert And(False) == false
43+
assert And(True, True ) == true
44+
assert And(True, False) == false
45+
assert And(False, False) == false
46+
assert And(True, True, True) == true
47+
48+
49+
def test_Or():
50+
assert Or() == false
51+
assert Or(True) == true
52+
assert Or(False) == false
53+
assert Or(True, True ) == true
54+
assert Or(True, False) == true
55+
assert Or(False, False) == false
56+
assert Or(True, False, False) == true
57+
58+
59+
def test_Nor():
60+
assert Nor() == true
61+
assert Nor(True) == false
62+
assert Nor(False) == true
63+
assert Nor(True, True ) == false
64+
assert Nor(True, False) == false
65+
assert Nor(False, False) == true
66+
assert Nor(True, True, True) == false
67+
68+
69+
def test_Nand():
70+
assert Nand() == false
71+
assert Nand(True) == false
72+
assert Nand(False) == true
73+
assert Nand(True, True) == false
74+
assert Nand(True, False) == true
75+
assert Nand(False, False) == true
76+
assert Nand(True, True, True) == false
77+
78+
79+
def test_Not():
80+
assert Not(True) == false
81+
assert Not(False) == true
82+
83+
84+
def test_Xor():
85+
assert Xor() == false
86+
assert Xor(True) == true
87+
assert Xor(False) == false
88+
assert Xor(True, True ) == false
89+
assert Xor(True, False) == true
90+
assert Xor(False, False) == false
91+
assert Xor(True, False, False) == true
92+
93+
94+
def test_Xnor():
95+
assert Xnor() == true
96+
assert Xnor(True) == false
97+
assert Xnor(False) == true
98+
assert Xnor(True, True ) == true
99+
assert Xnor(True, False) == false
100+
assert Xnor(False, False) == true
101+
assert Xnor(True, False, False) == false
102+
103+
104+
def test_Piecewise():
105+
assert Piecewise((x, x < 1), (0, True)) == Piecewise((x, x < 1), (0, True))
106+
int1 = Interval(1, 2, True, False)
107+
int2 = Interval(2, 5, True, False)
108+
int3 = Interval(5, 10, True, False)
109+
p = Piecewise((x, Contains(x, int1)), (y, Contains(x, int2)), (x + y, Contains(x, int3)))
110+
q = Piecewise((1, Contains(x, int1)), (0, Contains(x, int2)), (1, Contains(x, int3)))
111+
assert p.diff(x) == q
112+
113+
114+
def test_Contains():
115+
assert Contains(x, FiniteSet(0)) != false
116+
assert Contains(x, Interval(1, 1)) != false
117+
assert Contains(oo, Interval(-oo, oo)) == false
118+
assert Contains(-oo, Interval(-oo, oo)) == false
119+

0 commit comments

Comments
 (0)