details:   http://hg.sympy.org/sympy/rev/e4bd1b23bc34
changeset: 1836:e4bd1b23bc34
user:      Andy R. Terrel <[EMAIL PROTECTED]>
date:      Fri Oct 17 08:33:24 2008 +0200
description:
This patch implements computation for antiderivatives, and integration for one 
variable with limits.

diffs (157 lines):

diff -r 1ec456a9f32a -r e4bd1b23bc34 sympy/functions/elementary/piecewise.py
--- a/sympy/functions/elementary/piecewise.py   Fri Oct 17 08:33:19 2008 +0200
+++ b/sympy/functions/elementary/piecewise.py   Fri Oct 17 08:33:24 2008 +0200
@@ -103,6 +103,89 @@
             new_ecpairs.append( (new_expr, new_cond) )
         return Piecewise(*new_ecpairs)
 
+    def _eval_integral(self,x):
+        from sympy.integrals import integrate
+        return  Piecewise(*[(integrate(expr, x),cond) \
+                                for expr, cond in self.args])
+
+    def _eval_interval(self, sym, ab):
+        """Evaluates the function along the sym in a given interval ab"""
+        # FIXME: Currently only supports conds of type sym < Num, or Num < sym
+        int_expr = []
+        a, b = ab
+        mul = 1
+        if a > b:
+            a = ab[1]; b = ab[0]; mul = -1
+        default = None
+
+        # Determine what intervals the expr,cond pairs affect.
+        # 1) If cond is True, then log it as default
+        # 1.1) Currently if cond can't be evaluated, throw NotImplentedError.
+        # 2) For each inequality, if previous cond defines part of the interval
+        #    update the new conds interval.
+        #    -  eg x < 1, x < 3 -> [oo,1],[1,3] instead of [oo,1],[oo,3]
+        # 3) Sort the intervals to make it easier to find correct exprs
+        for expr, cond in self.args:
+            if type(cond) == bool:
+                if cond:
+                    default = expr
+                    break
+                else:
+                    continue
+            curr = list(cond.args)
+            if cond.args[0] == sym:
+                curr[0] = S.NegativeInfinity
+            elif cond.args[1] == sym:
+                curr[1] = S.Infinity
+            else:
+                raise NotImplementedError, \
+                    "Currently only supporting evaluation with only "\
+                    "sym on one side fo the relation."
+            curr = [max(a,curr[0]),min(b,curr[1])]
+            for n in xrange(len(int_expr)):
+                if self.__eval_cond(curr[0] < int_expr[n][1]) and \
+                        self.__eval_cond(curr[0] >= int_expr[n][0]):
+                    curr[0] = int_expr[n][1]
+                if self.__eval_cond(curr[1] > int_expr[n][0]) and \
+                        self.__eval_cond(curr[1] <= int_expr[n][1]):
+                    curr[1] = int_expr[n][0]
+            if self.__eval_cond(curr[0] < curr[1]):
+                int_expr.append(curr+[expr])
+        int_expr.sort(lambda x,y:1 if x[0] > y[0] else -1)
+
+        # Add holes to list of intervals if there is a default value,
+        # otherwise raise a ValueError.
+        holes = []
+        curr_low = a
+        for int_a, int_b, expr in int_expr:
+            if curr_low < int_a:
+                holes.append([curr_low, min(b,int_a), default])
+            curr_low = int_b
+            if curr_low > b:
+                break
+        if holes and default != None:
+            int_expr.extend(holes)
+        elif holes and default == None:
+            raise ValueError, "Called interval evaluation over piecewise "\
+                              "function on undefined intervals %s" %\
+                              ", ".join([str((h[0],h[1])) for h in holes])
+
+        # Finally run through the intervals and sum the evaluation.
+        ret_fun = 0
+        for int_a, int_b, expr in int_expr:
+            B = expr.subs(sym, min(b,int_b))
+            if B is S.NaN:
+                B = limit(expr, sym, min(b,int_b))
+            if B is S.NaN:
+                return self
+            A = expr.subs(sym, max(a,int_a))
+            if A is S.NaN:
+                A = limit(expr, sym, max(a,int_a))
+            if A is S.NaN:
+                return self
+            ret_fun += B - A
+        return mul * ret_fun
+
     def _eval_derivative(self, s):
         return Piecewise(*[(diff(expr,s),cond) for expr, cond in self.args])
 
diff -r 1ec456a9f32a -r e4bd1b23bc34 
sympy/functions/elementary/tests/test_piecewise.py
--- a/sympy/functions/elementary/tests/test_piecewise.py        Fri Oct 17 
08:33:19 2008 +0200
+++ b/sympy/functions/elementary/tests/test_piecewise.py        Fri Oct 17 
08:33:24 2008 +0200
@@ -59,3 +59,26 @@
     assert p + f == f + p
     assert p + dp == dp + p
     assert p - dp == -(dp - p)
+
+    # Test _eval_interval
+    f1 = x*y + 2
+    f2 = x*y**2 + 3
+    peval = Piecewise( (f1, x<0), (f2, x>0))
+    peval_interval = f1.subs(x,0) - f1.subs(x,-1) + f2.subs(x,1) - f2.subs(x,0)
+    assert peval._eval_interval(x,(-1,1)) == peval_interval
+
+    # Test integration
+    p_int =  Piecewise((-x,x < -1), (x**3/3.0, x < 0), (-x + x*log(x), x >= 0))
+    assert integrate(p,x) == p_int
+    p = Piecewise((x, x < 1),(x**2, -1 <= x),(x,3<x))
+    assert integrate(p,(x,-2,2)) == 5.0/6.0
+    assert integrate(p,(x,2,-2)) == -5.0/6.0
+    p = Piecewise((0, x < 0), (1,x < 1), (0, x < 2), (1, x < 3), (0, True))
+    assert integrate(p, (x,-oo,oo)) == 2
+    p = Piecewise((x, x < -10),(x**2, x <= -1),(x, 1 < x))
+    exception_called = False
+    try:
+        integrate(p,(x,-2,2))
+    except ValueError:
+        exception_called = True
+    assert exception_called
diff -r 1ec456a9f32a -r e4bd1b23bc34 sympy/integrals/integrals.py
--- a/sympy/integrals/integrals.py      Fri Oct 17 08:33:19 2008 +0200
+++ b/sympy/integrals/integrals.py      Fri Oct 17 08:33:24 2008 +0200
@@ -9,7 +9,7 @@
 from sympy.series import limit
 from sympy.polys import Poly
 from sympy.solvers import solve
-from sympy.functions import DiracDelta, Heaviside
+from sympy.functions import DiracDelta, Heaviside, Piecewise
 
 class Integral(Basic):
     """Represents unevaluated integral."""
@@ -132,6 +132,10 @@
                 if ab is None:
                     function = antideriv
                 else:
+                    if isinstance(antideriv,Piecewise):
+                        function = antideriv._eval_interval(x,ab)
+                        continue
+
                     a,b = ab
                     A = antideriv.subs(x, a)
 
@@ -241,6 +245,10 @@
         # see Polynomial for details.
         if isinstance(f, Poly):
             return f.integrate(x)
+
+        # Piecewise antiderivatives need to call special integrate.
+        if isinstance(f,Piecewise):
+            return f._eval_integral(x)
 
         # let's cut it short if `f` does not depend on `x`
         if not f.has(x):

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sympy-commits" group.
To post to this group, send email to sympy-commits@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sympy-commits?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to