1 """Base class for all objects in sympy"""
6 from basic_methods
import BasicMeths
, cache_it
, cache_it_immutable
, BasicType
8 class SympifyError(ValueError):
9 def __init__(self
, expr
, base_exc
):
11 self
.base_exc
= base_exc
13 return "Sympify of expression '%s' failed, because of exception being raised:\n%s: %s" % (self
.expr
, self
.base_exc
.__class
__.__name
__, str(self
.base_exc
))
20 def __init__(self
, allowed_types
, converter
= None, name
= None):
21 self
._allowed
_types
= allowed_types
22 self
.converter
= converter
25 def fix_allowed_types(self
, have_been_here
={}):
27 if have_been_here
.get(i
): return
28 allowed_types
= self
._allowed
_types
29 if isinstance(allowed_types
, str):
30 self
.allowed_types
= getattr(Basic
, allowed_types
)
31 elif isinstance(allowed_types
, (tuple, list)):
32 new_allowed_types
= []
33 for t
in allowed_types
:
34 if isinstance(t
, str):
36 new_allowed_types
.append(t
)
37 self
.allowed_types
= tuple(new_allowed_types
)
39 self
.allowed_types
= allowed_types
40 have_been_here
[i
] = True
43 def process(self
, obj
, func
, index
= None):
44 if isinstance(obj
, self
.allowed_types
):
45 if self
.converter
is not None:
46 obj
= self
.converter(obj
)
48 func_src
= '%s:%s:function %s' % (func
.func_code
.co_filename
, func
.func_code
.co_firstlineno
, func
.func_name
)
50 raise ValueError('%s return value must be of type %r but got %r' % (func_src
, self
.allowed_types
, obj
))
51 if isinstance(index
, (int,long)):
52 raise ValueError('%s %s-th argument must be of type %r but got %r' % (func_src
, index
, self
.allowed_types
, obj
))
53 if isinstance(index
, str):
54 raise ValueError('%s %r keyword argument must be of type %r but got %r' % (func_src
, index
, self
.allowed_types
, obj
))
55 raise NotImplementedError(`index
,type(index
)`
)
58 """ Memoizer function decorator generator.
61 - checks that function arguments have allowed types
62 - optionally apply converters to arguments
63 - cache the results of function calls
64 - optionally apply converter to function values
68 @Memoizer(<allowed types for argument 0>,
69 MemoizerArg(<allowed types for argument 1>),
70 MemoizerArg(<allowed types for argument 2>, <convert argument before function call>),
71 MemoizerArg(<allowed types for argument 3>, <convert argument before function call>, name=<kw argument name>),
73 return_value_converter = <None or converter function, usually makes a copy>
75 def function(<arguments>, <kw_argumnets>):
79 - if allowed type is string object then there Basic must have attribute
80 with the string name that is used as the allowed type --- this is needed
81 for applying Memoizer decorator to Basic methods when Basic definition
85 - arguments must be immutable
86 - when function values are mutable then one must use return_value_converter to
87 deep copy the returned values
89 Ref: http://en.wikipedia.org/wiki/Memoization
92 def __init__(self
, *arg_templates
, **kw_arg_templates
):
93 new_arg_templates
= []
94 for t
in arg_templates
:
95 if not isinstance(t
, MemoizerArg
):
97 new_arg_templates
.append(t
)
98 self
.arg_templates
= tuple(new_arg_templates
)
99 return_value_converter
= kw_arg_templates
.pop('return_value_converter', None)
100 self
.kw_arg_templates
= kw_arg_templates
.copy()
101 for template
in self
.arg_templates
:
102 if template
.name
is not None:
103 self
.kw_arg_templates
[template
.name
] = template
104 if return_value_converter
is None:
105 self
.return_value_converter
= lambda obj
: obj
107 self
.return_value_converter
= return_value_converter
109 def fix_allowed_types(self
, have_been_here
={}):
111 if have_been_here
.get(i
): return
112 for t
in self
.arg_templates
:
113 t
.fix_allowed_types()
114 for k
,t
in self
.kw_arg_templates
.items():
115 t
.fix_allowed_types()
116 have_been_here
[i
] = True
118 def __call__(self
, func
):
121 def wrapper(*args
, **kw_args
):
122 kw_items
= tuple(kw_args
.items())
124 return self
.return_value_converter(cache
[args
,kw_items
])
127 self
.fix_allowed_types()
128 new_args
= tuple([template
.process(a
,func
,i
) for (a
, template
, i
) in zip(args
, self
.arg_templates
, range(len(args
)))])
129 assert len(args
)==len(new_args
)
131 for k
, v
in kw_items
:
132 template
= self
.kw_arg_templates
[k
]
133 v
= template
.process(v
, func
, k
)
135 new_kw_items
= tuple(new_kw_args
.items())
137 return self
.return_value_converter(cache
[new_args
, new_kw_items
])
139 r
= func(*new_args
, **new_kw_args
)
147 cache
[new_args
, new_kw_items
] = cache
[args
, kw_items
] = r
148 return self
.return_value_converter(r
)
153 class Basic(BasicMeths
):
155 Base class for all objects in sympy.
161 When you want to access parameters of some instance, always use [].
177 2) Never use internal methods or variables (the ones prefixed with "_").
180 In [6]: cot(x)._args #don't use this, use cot(x)[:] instead
186 def __new__(cls
, *args
, **assumptions
):
187 obj
= object.__new
__(cls
)
188 obj
.assume(**assumptions
)
189 obj
._mhash
= None # will be set by BasicMeths.__hash__ method.
190 obj
._args
= args
# all items in args must be Basic objects
194 def sympify(a
, sympify_lists
=False):
195 """Converts an arbitrary expression to a type that can be used
196 inside sympy. For example, it will convert python int's into
197 instance of sympy.Rational, floats into intances of sympy.Real,
198 etc. It is also able to coerce symbolic expressions which does
199 inherit after Basic. This can be useful in cooperation with SAGE.
201 It currently accepts as arguments:
202 - any object defined in sympy (except maybe matrices [TODO])
203 - standard numeric python types: int, long, float, Decimal
204 - strings (like "0.09" or "2e-19")
206 If sympify_lists is set to True then sympify will also accept
207 lists, tuples and sets. It will return the same type but with
208 all of the entries sympified.
210 If the argument is already a type that sympy understands, it will do
211 nothing but return that value. This can be used at the begining of a
212 function to ensure you are working with the correct type.
214 >>> from sympy import *
216 >>> sympify(2).is_integer
218 >>> sympify(2).is_real
221 >>> sympify(2.0).is_real
223 >>> sympify("2.0").is_real
225 >>> sympify("2e-45").is_real
229 if isinstance(a
, BasicType
):
231 if isinstance(a
, Basic
):
233 elif isinstance(a
, bool):
234 raise NotImplementedError("bool support")
235 elif isinstance(a
, (int, long)):
236 return Basic
.Integer(a
)
237 elif isinstance(a
, (float, decimal
.Decimal
)):
239 elif isinstance(a
, complex):
240 real
, imag
= map(Basic
.sympify
, (a
.real
, a
.imag
))
241 ireal
, iimag
= int(real
), int(imag
)
243 if ireal
+ iimag
*1j
== a
:
244 return ireal
+ iimag
*Basic
.ImaginaryUnit()
245 return real
+ Basic
.ImaginaryUnit() * imag
246 elif isinstance(a
, (list,tuple)) and len(a
) == 2:
247 return Basic
.Interval(*a
)
248 elif isinstance(a
, (list,tuple,set)) and sympify_lists
:
249 return type(a
)([Basic
.sympify(x
, True) for x
in a
])
250 elif hasattr(a
, "_sympy_"):
251 # the "a" implements _sympy_() method, that returns a SymPy
252 # expression (by definition), so we just use it
255 # XXX this is here because of cyclic-import issues
256 from sympy
.matrices
import Matrix
257 from sympy
.polynomials
import Polynomial
259 if isinstance(a
, Polynomial
):
261 if isinstance(a
, Matrix
):
262 raise NotImplementedError('matrix support')
264 if not isinstance(a
, str):
265 # At this point we were given an arbitrary expression
266 # which does not inherit from Basic and doesn't implement
267 # _sympy_ (which is a canonical and robust way to convert
268 # anything to SymPy expression).
270 # As a last chance, we try to take "a"'s normal form via str()
271 # and try to parse it. If it fails, then we have no luck and
272 # return an exception
276 return ast_parser
.SymPyParser().parse_expr(a
)
277 except Exception, exc
:
278 raise SympifyError(a
, exc
)
279 raise ValueError("%r is NOT a valid SymPy expression" % a
)
281 @Memoizer('Basic', MemoizerArg((type, type(None), tuple), name
='type'), return_value_converter
= lambda obj
: obj
.copy())
282 def atoms(self
, type=None):
283 """Returns the atoms that form current object.
286 >>> from sympy import *
289 >>> (x+y**2+ 2*x*y).atoms()
292 You can also filter the results by a given type(s) of object
293 >>> (x+y+2+y**2*sin(x)).atoms(type=Symbol)
296 >>> (x+y+2+y**2*sin(x)).atoms(type=Number)
299 >>> (x+y+2+y**2*sin(x)).atoms(type=(Symbol, Number))
303 if type is not None and not isinstance(type, (type_class
, tuple)):
304 type = Basic
.sympify(type).__class
__
305 if isinstance(self
, Atom
):
306 if type is None or isinstance(self
, type):
310 result
= result
.union(obj
.atoms(type=type))
313 def is_hypergeometric(self
, arg
):
314 from sympy
.simplify
import hypersimp
315 return hypersimp(self
, arg
, simplify
=False) is not None
319 """Returns True if self is a number (like 1, or 1+log(2)), and False
320 otherwise (e.g. 1+x)."""
321 return len(self
.atoms(Basic
.Symbol
)) == 0
325 """Returns a tuple of arguments of "self".
329 In [2]: cot(x).args[:]
332 In [3]: cot(x).args[0]
335 In [4]: (x*y).args[:]
338 In [5]: (x*y).args[1]
341 Note for developers: Never use self._args, always use self.args.
342 Only when you are creating your own new function, use _args
343 in the __new__. Don't override .args() from Basic (so that it's
344 easy to change the interface in the future if needed).
348 def is_fraction(self
, *syms
):
349 p
, q
= self
.as_numer_denom()
351 if p
.is_polynomial(*syms
):
352 if q
.is_polynomial(*syms
):
357 def _eval_is_polynomial(self
, syms
):
360 def is_polynomial(self
, *syms
):
362 syms
= map(Basic
.sympify
, syms
)
364 syms
= list(self
.atoms(type=Basic
.Symbol
))
366 if not syms
: # constant polynomial
369 return self
._eval
_is
_polynomial
(syms
)
371 def as_polynomial(self
, *syms
, **kwargs
):
372 return Basic
.Polynomial(self
, var
=(syms
or None), **kwargs
)
374 def _eval_subs(self
, old
, new
):
380 def subs(self
, old
, new
):
381 """Substitutes an expression old -> new."""
382 old
= Basic
.sympify(old
)
383 new
= Basic
.sympify(new
)
385 # TODO This code is a start for issue 264. Currently, uncommenting
386 # this code will break A LOT of tests!
388 #if not old.is_dummy:
389 # exclude = ['dummy', 'comparable']
390 # for x in self._assume_defined:
391 # if x in exclude: continue
392 # old_val = getattr(old, 'is_' + x)
393 # if old_val is not None and old_val != getattr(new, 'is_' + x):
394 # raise ValueError("Cannot substitute '%s' for '%s' because assumptions do not match" % (str(new), str(old)))
396 #print self, old, new
397 return self
._eval
_subs
(old
, new
)
399 def _seq_subs(self
, old
, new
):
402 #new functions are initialized differently, than old functions
403 from sympy
.core
.function
import FunctionClass
404 if isinstance(self
.func
, FunctionClass
):
407 args
= (self
.func
,)+self
[:]
408 return self
.__class
__(*[s
.subs(old
, new
) for s
in args
])
410 def has(self
, *patterns
):
412 Return True if self has any of the patterns.
420 raise TypeError("has() requires at least 1 argument (got none)")
421 p
= Basic
.sympify(patterns
[0])
422 if isinstance(p
, Basic
.Symbol
) and not isinstance(p
, Basic
.Wild
): # speeds up
423 return p
in self
.atoms(p
.__class
__)
424 if isinstance(p
, BasicType
):
425 #XXX hack, this is very fragile:
426 if str(self
).find(str(p
.__name
__)) == -1:
427 #didn't find p in self
431 if p
.matches(self
) is not None:
436 args
= (self
.func
,)+self
[:]
442 def _eval_power(self
, other
):
445 def _eval_derivative(self
, s
):
448 def _eval_integral(self
, s
):
451 def _eval_defined_integral(self
, s
, a
, b
):
454 def _eval_fapply(self
, *args
, **assumptions
):
457 def _eval_fpower(b
, e
):
460 def _eval_apply_evalf(self
,*args
):
463 def _eval_eq_nonzero(self
, other
):
467 def _eval_apply_subs(cls
, *args
):
470 def _calc_apply_positive(self
, *args
):
473 def _calc_apply_real(self
, *args
):
476 def _eval_conjugate(self
):
481 from sympy
.functions
.elementary
.complexes
import conjugate
as c
484 def subs_dict(self
, old_new_dict
):
485 """Substitutes "self" using the keys and values from the "old_new_dict".
487 This correctly handles "overlapping" keys,
488 e.g. when doing substituion like:
490 e.subs_dict(x: y, exp(x): y)
492 exp(x) is always substituted before x
496 oldnew
= [(o
,n
) for (o
,n
) in old_new_dict
.items()]
499 # Care needs to be taken for cases like these:
505 # e.subs_dict(x: y, exp(x): y)
507 # the result depends in which order elementary substitutions are done.
509 # So we *have* to proceess 'exp(x)' first. This is achieved by topologically
510 # sorting substitutes by 'in' criteria - if "exp(x)" contains "x", it
511 # gets substituted first.
514 # let's topologically sort oldnew, so we have more general terms in the
515 # beginning (e.g. [exp(x), x] is not the same as [x, exp(x)] when
516 # doing substitution)
523 oldnew
.sort(cmp=in_cmp
)
525 for old
,new
in oldnew
:
530 def matches(pattern
, expr
, repl_dict
={}, evaluate
=False):
532 Helper method for match() - switches the pattern and expr.
534 Can be used to solve linear equations:
535 >>> from sympy import Symbol, Wild
536 >>> a,b = map(Symbol, 'ab')
538 >>> (a+b*x).matches(0)
542 from sympy
.core
.mul
import Mul
543 from sympy
.core
.power
import Pow
545 # weed out negative one prefixes
547 if isinstance(pattern
,Mul
) and pattern
[0] == -1:
548 pattern
= -pattern
; sign
= -sign
549 if isinstance(expr
, Mul
) and expr
[0] == -1:
550 expr
= -expr
; sign
= -sign
554 for old
,new
in repl_dict
.items():
555 pat
= pat
.subs(old
, new
)
557 return pat
.matches(expr
, repl_dict
)
558 expr
= Basic
.sympify(expr
)
559 if not isinstance(expr
, pattern
.__class
__):
560 from sympy
.core
.numbers
import Rational
561 # if we can omit the first factor, we can match it to sign * one
562 if isinstance(pattern
, Mul
) and Mul(*pattern
[1:]) == expr
:
563 return pattern
[0].matches(Rational(sign
), repl_dict
, evaluate
)
564 # two-factor product: if the 2nd factor matches, the first part must be sign * one
565 if isinstance(pattern
, Mul
) and len(pattern
[:]) == 2:
566 dd
= pattern
[1].matches(expr
, repl_dict
, evaluate
)
567 if dd
== None: return None
568 dd
= pattern
[0].matches(Rational(sign
), dd
, evaluate
)
572 if len(pattern
[:])==0:
578 # weed out identical terms
584 if e
in ee
: ee
.remove(e
)
585 if p
in pp
: pp
.remove(p
)
587 # only one symbol left in pattern -> match the remaining expression
588 from sympy
.core
.symbol
import Wild
589 if len(pp
) == 1 and isinstance(pp
[0], Wild
):
590 if len(ee
) == 1: d
[pp
[0]] = sign
* ee
[0]
591 else: d
[pp
[0]] = sign
* (type(expr
)(*ee
))
594 if len(ee
) != len(pp
):
598 for p
,e
in zip(pp
, ee
):
599 if i
== 0 and sign
!= 1:
601 except TypeError: return None
602 d
= p
.matches(e
, d
, evaluate
=not i
)
608 def match(self
, pattern
):
612 Wild symbols match all.
614 Return None when expression (self) does not match
615 with pattern. Otherwise return a dictionary such that
617 pattern.subs_dict(self.match(pattern)) == self
620 pattern
= Basic
.sympify(pattern
)
621 return pattern
.matches(self
, {})
623 def solve4linearsymbol(eqn
, rhs
, symbols
= None):
626 with respect to some linear symbol in eqn.
627 Returns (symbol, solution). If eqn is nonlinear
628 with respect to all symbols, then return
629 trivial solution (eqn, rhs).
631 if isinstance(eqn
, Basic
.Symbol
):
634 symbols
= eqn
.atoms(type=Basic
.Symbol
)
639 if isinstance(deqn
.diff(s
), Basic
.Zero
):
640 # eqn = a + b*c, a=eqn(c=0),b=deqn(c=0)
641 return s
, (rhs
- eqn
.subs(s
,0))/deqn
.subs(s
,0)
642 # no linear symbol, return trivial solution
645 def _calc_splitter(self
, d
):
648 r
= self
.__class
__(*[t
._calc
_splitter
(d
) for t
in self
])
651 s
= d
[r
] = Basic
.Temporary()
656 r
= self
._calc
_splitter
(d
)
657 l
= [(s
.dummy_index
,s
,e
) for e
,s
in d
.items()]
659 return [(s
,e
) for i
,s
,e
in l
]
662 def count_ops(self
, symbolic
=True):
663 """ Return the number of operations in expressions.
666 >>> (1+a+b**2).count_ops()
668 >>> (sin(x)*x+sin(x)**2).count_ops()
669 ADD + MUL + POW + 2 * SIN
671 return Basic
.Integer(len(self
[:])-1) + sum([t
.count_ops(symbolic
=symbolic
) for t
in self
])
673 def doit(self
, **hints
):
674 """Evaluate objects that are not evaluated by default like limits,
675 integrals, sums and products. All objects of this kind will be
676 evaluated unless some species were excluded via 'hints'.
678 >>> from sympy import *
679 >>> x, y = symbols('xy')
684 >>> (2*Integral(x, x)).doit()
688 terms
= [ term
.doit(**hints
) for term
in self
]
689 return self
.__class
__(*terms
, **self
._assumptions
)
691 ###########################################################################
692 ################# EXPRESSION REPRESENTATION METHODS #######################
693 ###########################################################################
695 def _eval_expand_basic(self
, *args
):
696 if isinstance(self
, Atom
):
699 terms
= [ term
._eval
_expand
_basic
(*args
) for term
in sargs
]
700 return self
.__class
__(*terms
, **self
._assumptions
)
702 def _eval_expand_power(self
, *args
):
703 if isinstance(self
, Atom
):
705 if not isinstance(self
, Basic
.Apply
): # FIXME Apply -> Function
708 sargs
= (self
.func
,)+self
[:]
709 terms
= [ term
._eval
_expand
_power
(*args
) for term
in sargs
]
710 return self
.__class
__(*terms
, **self
._assumptions
)
712 def _eval_expand_complex(self
, *args
):
713 if isinstance(self
, Atom
):
716 terms
= [ term
._eval
_expand
_complex
(*args
) for term
in sargs
]
717 return self
.__class
__(*terms
, **self
._assumptions
)
719 def _eval_expand_trig(self
, *args
):
720 if isinstance(self
, Atom
):
723 terms
= [ term
._eval
_expand
_trig
(*args
) for term
in sargs
]
724 return self
.__class
__(*terms
, **self
._assumptions
)
726 def _eval_expand_func(self
, *args
):
727 if isinstance(self
, Atom
):
730 terms
= [ term
._eval
_expand
_func
(*args
) for term
in sargs
]
731 return self
.__class
__(*terms
, **self
._assumptions
)
733 def expand(self
, *args
, **hints
):
734 """Expand an expression based on different hints. Currently
735 supported hints are basic, power, complex, trig and func.
740 if hints
[hint
] == True:
741 func
= getattr(obj
, '_eval_expand_'+hint
, None)
746 if hints
.get('basic', True):
747 obj
= obj
._eval
_expand
_basic
()
751 def _eval_rewrite(self
, pattern
, rule
, **hints
):
752 if isinstance(self
, Atom
):
755 terms
= [ t
._eval
_rewrite
(pattern
, rule
, **hints
) for t
in sargs
]
756 return self
.__class
__(*terms
, **self
._assumptions
)
758 def rewrite(self
, *args
, **hints
):
759 """Rewrites expression containing applications of functions
760 of one kind in terms of functions of different kind. For
761 example you can rewrite trigonometric functions as complex
762 exponentials or combinatorial functions as gamma function.
764 As a pattern this function accepts a list of functions to
765 to rewrite (instances of DefinedFunction class). As rule
766 you can use string or a destinaton function instance (in
767 this cas rewrite() will use tostr() method).
769 There is also possibility to pass hints on how to rewrite
770 the given expressions. For now there is only one such hint
771 defined called 'deep'. When 'deep' is set to False it will
772 forbid functions to rewrite their contents.
774 >>> from sympy import *
775 >>> x, y = symbols('xy')
777 >>> sin(x).rewrite(sin, exp)
778 -1/2*I*(-exp(-I*x) + exp(I*x))
781 if isinstance(self
, Atom
) or not args
:
784 pattern
, rule
= args
[:-1], args
[-1]
786 if not isinstance(rule
, str):
787 # XXX move me out of here (cyclic imports)
788 from function
import FunctionClass
790 if rule
== Basic
.tan
:
792 elif rule
== Basic
.exp
:
794 elif isinstance(rule
, FunctionClass
): # new-style functions
796 rule
= rule
.__name
__ # XXX proper attribute for name?
801 rule
= '_eval_rewrite_as_' + rule
804 return self
._eval
_rewrite
(None, rule
, **hints
)
806 if isinstance(pattern
[0], (tuple, list)):
809 pattern
= [ p
.__class
__ for p
in pattern
if self
.has(p
) ]
812 return self
._eval
_rewrite
(tuple(pattern
), rule
, **hints
)
816 def as_coefficient(self
, expr
):
817 """Extracts symbolic coefficient at the given expression. In
818 other words, this functions separates 'self' into product
819 of 'expr' and 'expr'-free coefficient. If such separation
820 is not possible it will return None.
822 >>> from sympy import *
823 >>> x, y = symbols('xy')
825 >>> E.as_coefficient(E)
827 >>> (2*E).as_coefficient(E)
830 >>> (2*E + x).as_coefficient(E)
831 >>> (2*sin(E)*E).as_coefficient(E)
833 >>> (2*pi*I).as_coefficient(pi*I)
836 >>> (2*I).as_coefficient(pi*I)
839 if isinstance(expr
, Basic
.Add
):
844 coeff
= self
.match(w
* expr
)
846 if coeff
is not None:
847 if isinstance(expr
, Basic
.Mul
):
852 if coeff
[w
].has(*expr
):
859 def as_independent(self
, *deps
):
860 """Returns a pair with separated parts of a given expression
861 independent of specified symbols in the first place and
862 dependend on them in the other. Both parts are valid
865 >>> from sympy import *
866 >>> x, y = symbols('xy')
868 >>> (x*sin(x)*cos(y)).as_independent(x)
872 indeps
, depend
= [], []
874 if isinstance(self
, (Basic
.Add
, Basic
.Mul
)):
885 return Basic
.Mul(*indeps
), Basic
.Mul(*depend
)
887 def as_real_imag(self
):
888 """Performs complex expansion on 'self' and returns a tuple
889 containing collected both real and imaginary parts. This
890 method can't be confused with re() and im() functions,
891 which does not perform complex expansion at evaluation.
893 However it is possible to expand both re() and im()
894 functions and get exactly the same results as with
895 a single call to this function.
897 >>> from sympy import *
899 >>> x, y = symbols('xy', real=True)
901 >>> (x + y*I).as_real_imag()
904 >>> z, w = symbols('zw')
906 >>> (z + w*I).as_real_imag()
907 (-im(w) + re(z), im(z) + re(w))
910 expr
= self
.expand(complex=True)
912 if not isinstance(expr
, Basic
.Add
):
915 re_part
, im_part
= [], []
918 coeff
= term
.as_coefficient(S
.ImaginaryUnit
)
923 im_part
.append(coeff
)
925 return (Basic
.Add(*re_part
), Basic
.Add(*im_part
))
927 def as_powers_dict(self
):
928 return { self
: S
.One
}
930 def as_base_exp(self
):
932 return self
, Basic
.One()
934 def as_coeff_terms(self
, x
=None):
939 return Basic
.One(), [self
]
941 def as_indep_terms(self
, x
):
942 coeff
, terms
= self
.as_coeff_terms()
950 return Basic
.Mul(*indeps
), Basic
.Mul(*new_terms
)
952 def as_coeff_factors(self
, x
=None):
957 return Basic
.Zero(), [self
]
959 def as_numer_denom(self
):
961 base
, exp
= self
.as_base_exp()
962 coeff
, terms
= exp
.as_coeff_terms()
963 if coeff
.is_negative
:
965 return Basic
.One(), base
** (-exp
)
966 return self
, Basic
.One()
968 def as_expr_orders(self
):
969 """ Split expr + Order(..) to (expr, Order(..)).
973 if isinstance(self
, Basic
.Add
):
975 if isinstance(f
, Basic
.Order
):
979 elif isinstance(self
, Basic
.Order
):
983 return Basic
.Add(*l1
), Basic
.Add(*l2
)
986 n
, d
= self
.as_numer_denom()
987 if isinstance(d
, Basic
.One
):
991 ###################################################################################
992 ##################### DERIVATIVE, INTEGRAL, FUNCTIONAL METHODS ####################
993 ###################################################################################
995 def diff(self
, *symbols
, **assumptions
):
999 if isinstance(s
, Basic
.Integer
) and new_symbols
:
1000 last_s
= new_symbols
.pop()
1002 new_symbols
+= [last_s
] * i
1003 elif isinstance(s
, Basic
.Symbol
):
1004 new_symbols
.append(s
)
1006 raise TypeError(".diff() argument must be Symbol|Integer instance (got %s)" % (s
.__class
__.__name
__))
1007 if not assumptions
.has_key("evaluate"):
1008 assumptions
["evaluate"] = True
1009 ret
= Basic
.Derivative(self
, *new_symbols
, **assumptions
)
1012 def fdiff(self
, *indices
):
1014 return Basic
.FApply(Basic
.FDerivative(*indices
), self
)
1016 def integral(self
, *symbols
, **assumptions
):
1019 s
= Basic
.sympify(s
)
1020 if isinstance(s
, Basic
.Integer
) and new_symbols
:
1021 last_s
= new_symbols
[-1]
1023 new_symbols
+= [last_s
] * (i
-1)
1024 elif isinstance(s
, (Basic
.Symbol
, Basic
.Equality
)):
1025 new_symbols
.append(s
)
1027 raise TypeError(".integral() argument must be Symbol|Integer|Equality instance (got %s)" % (s
.__class
__.__name
__))
1028 return Basic
.Integral(self
, *new_symbols
, **assumptions
)
1030 #XXX fix the removeme
1031 def __call__(self
, *args
, **removeme
):
1032 return Basic
.Function(self
[0])(*args
)
1034 def _eval_evalf(self
):
1037 def _seq_eval_evalf(self
):
1038 return self
.__class
__(*[s
.evalf() for s
in self
])
1040 def __float__(self
):
1041 result
= self
.evalf(precision
=16)
1043 if isinstance(result
, Basic
.Number
):
1044 return float(result
)
1046 raise ValueError("Symbolic value, can't compute")
1048 def evalf(self
, precision
=None):
1049 if precision
is None:
1050 r
= self
._eval
_evalf
()
1052 old_precision
= Basic
.set_precision(precision
)
1053 r
= self
._eval
_evalf
()
1054 Basic
.set_precision(old_precision
)
1059 ###################################################################################
1060 ##################### SERIES, LEADING TERM, LIMIT, ORDER METHODS ##################
1061 ###################################################################################
1063 def series(self
, x
, n
= 6):
1067 Return the Taylor (Laurent or generalized) series around 0 of self
1068 with respect to x until the n-th term (default n is 6).
1072 This method is the most high level method and it returns the
1073 series including the O(x**n) term.
1075 Internally, it executes a method oseries(), which takes an
1076 O instance as the only parameter and it is responsible for
1077 returning a series (without the O term) up to the given order.
1079 x
= Basic
.sympify(x
)
1080 o
= Basic
.Order(x
**n
,x
)
1087 def oseries(self
, order
, _cache
={}):
1089 Return the series of an expression upto given Order symbol (without the
1092 The general philosophy is this: simply start with the most simple
1093 taylor (laurent) term and calculate one be one and use
1094 order.contains(term) method to determine if your term is still
1095 significant and should be added to the series, or we should stop.
1097 The _cache parameter is not meant to be used by a user. It is here only
1098 to detect an infinite recursion.
1100 #is the _cache mechanism really necessary? I think it could be removed
1101 #completely, it's only slowing things down (well, probably negligibly).
1102 #python can also detect an infinite recursion, so I am for removing
1104 if _cache
.has_key((self
, order
)):
1105 raise RuntimeError('Detected recursion while computing oseries(%s, %s)' % (self
, order
))
1106 order
= Basic
.Order(order
)
1107 _cache
[(self
, order
)] = 1
1108 if isinstance(order
, Basic
.Zero
):
1109 del _cache
[(self
, order
)]
1111 if order
.contains(self
):
1112 del _cache
[(self
, order
)]
1114 if len(order
.symbols
)>1:
1116 for s
in order
.symbols
:
1117 o
= Basic
.Order(order
.expr
, s
)
1119 del _cache
[(self
, order
)]
1121 x
= order
.symbols
[0]
1123 del _cache
[(self
, order
)]
1125 obj
= self
._eval
_oseries
(order
)
1127 #obj2 = obj.expand(trig=True)
1130 r
= obj2
.oseries(order
)
1131 del _cache
[(self
, order
)]
1133 del _cache
[(self
, order
)]
1135 del _cache
[(self
, order
)]
1136 raise NotImplementedError('(%s).oseries(%s)' % (self
, order
))
1138 def _eval_oseries(self
, order
):
1141 def _compute_oseries(self
, arg
, order
, taylor_term
, unevaluated_func
, correction
= 0):
1143 compute series sum(taylor_term(i, arg), i=0..n-1) such
1144 that order.contains(taylor_term(n, arg)). Assumes that arg->0 as x->0.
1146 x
= order
.symbols
[0]
1148 o
= Basic
.Order(arg
, x
)
1149 if isinstance(o
, Basic
.Zero
):
1150 return unevaluated_func(arg
)
1152 e
= ln(order
.expr
*x
)/ln(x
)
1154 e
= ln(order
.expr
)/ln(o
.expr
)
1155 n
= e
.limit(x
,0) + 1 + correction
1157 # requested accuracy gives infinite series,
1158 # order is probably nonpolynomial e.g. O(exp(-1/x), x).
1159 return unevaluated_func(arg
)
1163 #well, the n is something more complicated (like 1+log(2))
1164 n
= int(n
.evalf()) + 1
1168 for i
in xrange(n
+2):
1169 g
= taylor_term(i
, arg
, g
)
1170 g
= g
.oseries(order
)
1172 return Basic
.Add(*l
)
1174 def limit(self
, x
, xlim
, direction
='<'):
1175 """ Compute limit x->xlim.
1177 from sympy
.series
.limits_series
import Limit
1178 return Limit(self
, x
, xlim
, direction
)
1180 def inflimit(self
, x
): # inflimit has its own cache
1181 x
= Basic
.sympify(x
)
1182 from sympy
.series
.limits_series
import InfLimit
1183 return InfLimit(self
, x
)
1186 def as_leading_term(self
, *symbols
):
1190 c
= c
.as_leading_term(x
)
1194 x
= Basic
.sympify(symbols
[0])
1195 assert isinstance(x
, Basic
.Symbol
),`x`
1198 expr
= self
.expand(trig
=True)
1199 obj
= expr
._eval
_as
_leading
_term
(x
)
1202 raise NotImplementedError('as_leading_term(%s, %s)' % (self
, x
))
1204 def as_coeff_exponent(self
, x
):
1205 """ c*x**e -> c,e where x can be any symbolic expression.
1207 x
= Basic
.sympify(x
)
1210 c
, terms
= self
.as_coeff_terms()
1215 return self
, Basic
.Zero()
1217 def ldegree(self
, x
):
1218 x
= Basic
.sympify(x
)
1219 c
,e
= self
.as_leading_term(x
).as_coeff_exponent(x
)
1222 raise ValueError("cannot compute ldegree(%s, %s), got c=%s" % (self
, x
, c
))
1224 def leadterm(self
, x
):
1225 x
= Basic
.sympify(x
)
1226 c
,e
= self
.as_leading_term(x
).as_coeff_exponent(x
)
1229 raise ValueError("cannot compute ldegree(%s, %s), got c=%s" % (self
, x
, c
))
1231 ##########################################################################
1232 ##################### END OF BASIC CLASS #################################
1233 ##########################################################################
1237 precedence
= Basic
.Atom_precedence
1239 def _eval_derivative(self
, s
):
1240 if self
==s
: return Basic
.One()
1243 def pattern_match(pattern
, expr
, repl_dict
):
1248 def as_numer_denom(self
):
1249 return self
, Basic
.One()
1251 def _calc_splitter(self
, d
):
1254 def count_ops(self
, symbolic
=True):
1257 def doit(self
, **hints
):
1260 def _eval_integral(self
, s
):
1265 def _eval_defined_integral(self
, s
, a
, b
):
1267 return (b
**2-a
**2)/2
1270 def _eval_is_polynomial(self
, syms
):
1273 def _eval_oseries(self
, order
):
1274 # .oseries() method checks for order.contains(self)
1277 def _eval_as_leading_term(self
, x
):
1281 class Singleton(Basic
):
1282 """ Singleton object.
1285 def __new__(cls
, *args
, **assumptions
):
1286 # if you need to overload __new__, then
1287 # use the same code as below to ensure
1288 # that only one instance of Singleton
1290 obj
= Singleton
.__dict
__.get(cls
.__name
__)
1292 obj
= Basic
.__new
__(cls
,*args
,**assumptions
)
1293 setattr(Singleton
, cls
.__name
__, obj
)
1296 class SingletonFactory
:
1298 A map between singleton classes and the corresponding instances.
1299 E.g. S.Exp == Basic.Exp()
1302 def __getattr__(self
, clsname
):
1303 if clsname
== "__repr__":
1305 obj
= Singleton
.__dict
__.get(clsname
)
1307 cls
= getattr(Basic
, clsname
)
1308 assert issubclass(cls
, Singleton
),`cls`
1310 setattr(self
, clsname
, obj
)
1313 S
= SingletonFactory()