Last active
June 30, 2016 12:10
-
-
Save Shekharrajak/851e086935e59e445f524bd5b0c9188e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# used in class Set(Basic):sets.py file | |
def _union_simplify(self, other): | |
""" | |
Try to reduce number of imageset in the args. Helper method for | |
ImageSet `_union `. It helps to get simpler imageset or | |
union of imageset. | |
First extract the expression of imageset and store in separate list | |
(self_expr for self and final_list for other). If there is any expr in | |
self_list have difference of pi or -pi with any final_expr expr. then | |
club them into one expr( (2*n + 1)*pi and 2*n*pi => n*pi). remove | |
previous expr from final_expr and self_expr. Add this new expr in | |
final_expr list. At the end final_list contains the minimum number of | |
expr that can generate all the expressions of `self` and `other`. | |
* Note: This should be used when there is linear expr in ImageSet(s). | |
Parameters | |
========== | |
self : S.EmptySet or imageset(s). | |
other : S.EmptySet or imageset(s) | |
. | |
Returns | |
======= | |
Simplified imageset(s) if possible otherwise `self` union `other`. | |
Examples | |
======== | |
>>> from sympy import Lambda | |
>>> from sympy.sets.fancysets import ImageSet | |
>>> from sympy import pprint | |
>>> from sympy.core import Dummy, pi, S, Symbol | |
>>> n = Dummy('n') | |
>>> pprint(\ | |
ImageSet(Lambda(n, 2*n*pi + 3*pi/4), S.Integers)._union_simplify(\ | |
ImageSet(Lambda(n, 2*n*pi + 7*pi/4), S.Integers)),\ | |
use_unicode = False) | |
3*pi | |
{n*pi + ---- | n in Integers()} | |
4 | |
>>> pprint((ImageSet(Lambda(n, 2*n*pi + pi/3), \ | |
S.Integers) + ImageSet(Lambda(n, 2*n*pi + pi), S.Integers)).\ | |
_union_simplify(ImageSet(Lambda(n, 2*n*pi), S.Integers)),\ | |
use_unicode = False) | |
pi | |
{n*pi | n in Integers()} U {2*n*pi + -- | n in Integers()} | |
3 | |
""" | |
from sympy.sets.fancysets import ImageSet | |
from sympy.core.function import Lambda | |
from sympy.core import pi | |
from sympy.polys import Poly | |
# don't try to reduce imageset(s) from the same union. | |
# (`_solve_trig` function defined in `solveset.py` | |
# solves the factors of trig eq and union of these soln is final ans, | |
# soln of one factor (say f1) should be clubbed with soln of another | |
# factor(say f2) and so on. ImageSet(s) of f1 or f2 should not be | |
# reduced(clubbed) with it's args. | |
if self is S.EmptySet: | |
return other | |
elif other is S.EmptySet: | |
return self | |
new_list = [] | |
# number of imageset | |
if isinstance(self, ImageSet): | |
new_img_len = 1 | |
new_list.append(self) | |
else: | |
new_img_len = len(self.args) | |
for i in range(0, new_img_len): | |
# list of imageset | |
new_list.append(self.args[i]) | |
self_expr = [] | |
final_expr = [] | |
# soln list | |
final_list = [] | |
final_len = 0 | |
if isinstance(other, ImageSet): | |
final_len = 1 | |
final_list.append(other) | |
else: | |
final_len = len(other.args) | |
for i in range(0, final_len): | |
# list of imageset | |
final_list.append(other.args[i]) | |
# use one dummy variable n_self | |
n_self = (new_list[0].lamda.expr).atoms(Dummy) | |
if len(n_self) > 1: | |
raise NotImplementedError( | |
'Use symbols only. \ | |
More than one dummy is present in ImageSet') | |
elif len(n_self) == 0: | |
raise NotImplementedError("use %s as Dummy" % | |
new_list[0].lamda.args[0][0]) | |
n_self = n_self.pop() | |
base = final_list[0].base_set | |
n_final = (final_list[0].lamda.expr).atoms(Dummy) | |
if len(n_final) > 1: | |
raise NotImplementedError( | |
'Use symbols only. \ | |
More than one dummy is present in ImageSet') | |
elif len(n_final) == 0: | |
raise NotImplementedError("use %s as Dummy" % | |
n_final[0].lamda.args[0][0]) | |
n_final = n_final.pop() | |
# Extracting expr | |
for s in new_list: | |
# lambda expression | |
lamb_expr = s.lamda.expr | |
base_2 = s.base_set | |
if Poly(lamb_expr, n_self).is_linear: | |
self_expr.append(lamb_expr) | |
else: | |
raise NotImplementedError('Implemented for linear ImageSet.\ | |
non linear expr found in imageSet') | |
if base_2.is_superset(base): | |
# take the bigger base set | |
base = base_2 | |
for s in final_list: | |
# lambda expression | |
lamb_expr = s.lamda.expr | |
base_2 = s.base_set | |
if Poly(lamb_expr, n_final).is_linear: | |
final_expr.append(lamb_expr.subs(n_final, n_self)) | |
else: | |
raise NotImplementedError('Implemented for linear ImageSet.\ | |
non linear expr found in imageSet') | |
if base_2.is_superset(base): | |
# take the bigger base set | |
base = base_2 | |
final = S.EmptySet | |
i = 0 | |
# there may be problem when there is multiple dummy variables present | |
# in the imageset expr but we don't get that case in _solve_trig. | |
while i < new_img_len: | |
done = False | |
for j in range(0, len(final_expr)): | |
if final_expr[j] - self_expr[i] == pi: | |
# (2*x*pi + pi + expr1) -( 2*x*pi + exp1) = pi | |
# can be => x*pi + expr1 | |
final_expr.extend( | |
[pi * n_self + self_expr[i].subs(n_self, 0)]) | |
final_expr.remove(final_expr[j]) | |
done = True | |
elif final_expr[j] - self_expr[i] == -pi: | |
# (2*x*pi + expr1) -( 2*x*pi + pi + exp1) = -pi | |
# can be => x*pi + expr1 | |
final_expr += [ | |
pi * n_self + final_expr[j].subs(n_self, 0) | |
] | |
final_expr.remove(final_expr[j]) | |
done = True | |
if not done: | |
final_expr.append(self_expr[i]) | |
i += 1 | |
final = Union(*[ | |
ImageSet(Lambda(n_self, s), base) | |
for s in final_expr], evaluate=False) | |
del n_self | |
del n_final | |
return final | |
def _union(self, other): | |
""" | |
This function should only be used internally | |
self._union(other) returns a new, joined set if self knows how | |
to join itself with other, otherwise it returns ``None``. | |
It may also return a python set of SymPy Sets if they are somehow | |
simpler. If it does this it must be idempotent i.e. the sets returned | |
must return ``None`` with _union'ed with each other | |
Used within the :class:`Union` class | |
""" | |
from sympy.polys.polyerrors import PolynomialError | |
from sympy.sets.fancysets import ImageSet | |
def _check_imageset(self): | |
# Returns True if all the args are ImageSet | |
# otherwise false | |
if isinstance(self, ImageSet): | |
return True | |
elif isinstance(self, Union): | |
for self_img in self.args: | |
if not isinstance(self_img, ImageSet): | |
return False | |
return True | |
else: | |
return False | |
try: | |
if _check_imageset(self) and _check_imageset(other): | |
return self._union_simplify(other) | |
else: | |
return None | |
except ( | |
NotImplementedError, | |
PolynomialError | |
): | |
# `_union_simplify` is for simplifying trigonometric eq. solution | |
# (Union of Imageset, solved from `_solve_trig` function present in | |
# solveset.py). So when it is not linear or contains more than one | |
# dummy variables, then just return None. Simplification of | |
# nonlinear imageset is not implemented. PolynomialError | |
# when there is non polynomial imageset present. | |
return None |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment