I see that the gods do not want me to get this in.  Apparently the
files did not make it to the last message.  I am just going to do what
I know works: below is the text copied and pasted from the 4 patches.
If it is easier, you can still pull from my github repo with the
commit hashes in the original thread.  Or, you could download the
patch files and convert them from Western (Mac OS Roman) to UTF-8.

Below are the 4 patches in the order that they should be applied.
They all go together, so please do not test until you have applied all
4.

Aaron Meurer

On May 25, 5:43 pm, "Aaron S. Meurer" <asmeu...@gmail.com> wrote:
> Those files had the wrong character encoding.  These files should have  
> the correct encoding.
>
> Aaron Meurer
>
> On May 23, 10:13 pm, "Aaron S. Meurer" <asmeu...@gmail.com> wrote:
>  > I tried sending these already through git, but they didn't seem to
>  > show up in the list.  Sorry if these are duplicates.  See this  
> thread:http://groups.google.com/group/sympy/browse_thread/thread/4622653ca05
> ...
>  >
>  > I have no idea how to make git reformat these as one patch, so I am
>  > just going to send them as one.  They do need to be applied in order,
>  > but they have the date and time stamps on them.  Also, you can pull
>  > the commits from their hashes from my github repo (right?).  The link
>  > is here:http://github.com/asmeurer/sympy/tree/odes
>  > The hashes are 0d5698640a17365c024c688748552795e4d5ad38
>  > 7c50da0e55a315d5a104ac1a31027cbe6094367e
>  > 0925083952426237794d7b3c67675f9977318b58
>  > 4ccdcd071075af238e522df0a1ef2adf86a59134.  Hopefully that works.
>  > Sorry if this is more work.  I hope the files work this time.
>  >
>  >  0001-Made-logcombine-more-robust.patch
>  > 7KViewDownload
>  >
>  >  0001-Added-function-logcombine.patch
>  > 10KViewDownload
>  >
>  >  0001-Added-Equality-support-in-logcombine.patch
>  > 3KViewDownload
>  >
>  >  0001-Added-an-XFAIL-test.patch
>  > 3KViewDownload



>From 4ccdcd071075af238e522df0a1ef2adf86a59134 Mon Sep 17 00:00:00 2001
From: Aaron Meurer <asmeu...@gmail.com>
Date: Wed, 20 May 2009 13:53:44 -0600
Subject: [PATCH 1/1] Added function logcombine.
 This function takes expressions like 2*log(x)-log(y) and turns them
into
 log(x**2/y), assuming that the arguments of the log are positive and
the coefficients are real.  This also adds several tests for the
function.

---
 sympy/simplify/__init__.py            |    3 +-
 sympy/simplify/simplify.py            |   97 +++++++++++++++++++++++++
+++++++-
 sympy/simplify/tests/test_simplify.py |   21 +++++++-
 3 files changed, 117 insertions(+), 4 deletions(-)

diff --git a/sympy/simplify/__init__.py b/sympy/simplify/__init__.py
index fa4d035..c883cbf 100644
--- a/sympy/simplify/__init__.py
+++ b/sympy/simplify/__init__.py
@@ -5,7 +5,8 @@
 the expression (x+x)**2 will be converted into 4*x**2
 """
 from simplify import collect, separate, together, radsimp, ratsimp,
fraction, \
-    simplify, trigsimp, powsimp, combsimp, hypersimp, hypersimilar,
nsimplify
+    simplify, trigsimp, powsimp, combsimp, hypersimp, hypersimilar,
nsimplify, \
+    logcombine

 from rewrite import cancel, trim, apart

diff --git a/sympy/simplify/simplify.py b/sympy/simplify/simplify.py
index 59a1d56..44558f1 100644
--- a/sympy/simplify/simplify.py
+++ b/sympy/simplify/simplify.py
@@ -1,12 +1,12 @@
 from sympy import SYMPY_DEBUG

 from sympy.core import Basic, S, C, Add, Mul, Pow, Rational, Integer,
\
-        Derivative, Wild, Symbol, sympify
+        Derivative, Wild, Symbol, sympify, expand

 from sympy.core.numbers import igcd

 from sympy.utilities import make_list, all
-from sympy.functions import gamma, exp, sqrt
+from sympy.functions import gamma, exp, sqrt, log

 from sympy.simplify.cse_main import cse

@@ -1155,4 +1155,97 @@ def nsimplify_real(x):

     return re + im*S.ImaginaryUnit

+def logcombine(expr, assumePosReal=False):
+    """
+    Takes logarithms and combines them using the following rules:
+
+    - log(x)+log(y) == log(x*y)
+    - a*log(x) == log(x**a)
+
+    These identities are only valid if x and y are positive and if a
is real, so
+    the function will not combine the terms unless the arguments have
the proper
+    assumptions on them.  Use logcombine(func, assumePosReal=True) to
+    automatically assume that the arguments of logs are positive and
that
+    coefficents are real.  Note that this will not change any
assumptions
+    already in place, so if the coefficient is imaginary or the
argument
+    negative, combine will still not combine the equations.  Change
the
+    assumptions on the variables to make them combine.
+
+    Examples:
+    >>> from sympy import *
+    >>> a,x,y,z = symbols('axyz')
+    >>> logcombine(a*log(x)+log(y)-log(z))
+    -log(z) + a*log(x) + log(y)
+    >>> logcombine(a*log(x)+log(y)-log(z), assumePosReal=True)
+    log(y*x**a/z)
+    >>> x,y,z = symbols('xyz', positive=True)
+    >>> a = Symbol('a', real=True)
+    >>> logcombine(a*log(x)+log(y)-log(z))
+    log(y*x**a/z)
+    """
+    # Try to make (a+bi)*log(x) == a*log(x)+bi*log(x).  This needs to
be a
+    # seperate function call to avoid infinite recursion.
+    return _logcombine(expand(expr), assumePosReal=assumePosReal)
+
+def _logcombine(expr, assumePosReal=False):
+
+    def _getlogargs(expr):
+        """
+        Returns the arguments of the logarithm in an expression.
+        Example:
+        _getlogargs(a*log(x*y) -> x*y
+        """
+        if expr.is_Function and expr.func == log:
+            return expr.args[0]
+        else:
+            for i in expr.args:
+                if i.has(log):
+                    return _getlogargs(i)
+        return None
+
+    if type(expr) in (int, float) or expr.is_Number or
expr.is_Rational or \
+    expr.is_NumberSymbol:
+       return expr
+    if expr.is_Add:
+        argslist = 1
+        notlogs = 0
+        coeflogs = 0
+        for i in expr.args:
+            if i.is_Function and i.func == log:
+                if (i.args[0].is_positive or (assumePosReal and not \
+                i.args[0].is_nonpositive)):
+                    argslist *= _logcombine(i.args[0],
assumePosReal=assumePosReal)
+                else:
+                    notlogs += i
+            elif i.has(log):
+                largs = _getlogargs(i)
+                if largs.is_positive and i.extract_multiplicatively
(log(largs)).\
+                is_real or (assumePosReal and not
largs.is_nonpositive and not \
+                i.extract_multiplicatively(log
(largs)).is_real==False):
+                    coeflogs += _logcombine(i,
assumePosReal=assumePosReal)
+                else:
+                    notlogs += i
+            else:
+                notlogs += i
+        alllogs = _logcombine(log(argslist)+coeflogs,
assumePosReal=assumePosReal)
+        return notlogs + alllogs
+
+    if expr.is_Mul:
+        a = Wild('a', exclude=[log])
+        x = Wild('x')
+        coef = expr.match(a*log(x))
+        if coef and (coef[a].is_real or expr.is_Number or
expr.is_NumberSymbol \
+        or type(coef[a]) in (int, float) or (assumePosReal and not \
+        coef[a].is_imaginary)):
+            return log(coef[x]**coef[a])
+        else:
+            return expr
+    if expr.is_Function:
+        return expr.func(_logcombine(expr.args[0],
assumePosReal=assumePosReal))
+    if expr.is_Pow:
+        return _logcombine(expr.args[0], assumePosReal=assumePosReal)
**\
+        _logcombine(expr.args[1], assumePosReal=assumePosReal)
+    else:
+        return expr
+

diff --git a/sympy/simplify/tests/test_simplify.py b/sympy/simplify/
tests/test_simplify.py
index d3dc547..c601f40 100644
--- a/sympy/simplify/tests/test_simplify.py
+++ b/sympy/simplify/tests/test_simplify.py
@@ -1,7 +1,8 @@
 from sympy import Symbol, symbols, together, hypersimp, factorial,
binomial, \
         collect, Function, powsimp, separate, sin, exp, Rational,
fraction, \
         simplify, trigsimp, cos, tan, cot, log, ratsimp, Matrix, pi,
integrate, \
-        solve, nsimplify, GoldenRatio, sqrt, E, I, sympify, atan,
Derivative, S, diff
+        solve, nsimplify, GoldenRatio, sqrt, E, I, sympify, atan,
Derivative, \
+        S, diff, logcombine

 from sympy.utilities.pytest import XFAIL

@@ -363,3 +364,21 @@ def test_diff():
     assert simplify(2*f(x)*f(x).diff(x)-diff(f(x)**2,x)) == 0
     assert simplify(diff(1/f(x),x)+f(x).diff(x)/f(x)**2) == 0
     assert simplify(f(x).diff(x,y)-f(x).diff(y,x)) == 0
+
+def test_logcombine():
+    x, y = symbols("xy")
+    a = Symbol("a")
+    z, w = symbols("zw", positive=True)
+    b = Symbol("b", real=True)
+    assert logcombine(log(x)+2*log(y)) == log(x) + 2*log(y)
+    assert logcombine(log(x)+2*log(y), assumePosReal=True) == log
(x*y**2)
+    assert logcombine(a*log(w)+log(z)) == a*log(w) + log(z)
+    assert logcombine(b*log(z)+b*log(x)) == log(z**b) + b*log(x)
+    assert logcombine(b*log(z)-log(w)) == log(z**b/w)
+    assert logcombine(cos(-2*log(z)+b*log(w))) == cos(log(w**b/z**2))
+    assert logcombine(log(log(x)-log(y))-log(z), assumePosReal=True)
== log(log((x/y)**(1/z)))
+    assert logcombine((2+I)*log(x), assumePosReal=True) == I*log(x)
+log(x**2)
+    assert logcombine((x**2+log(x)-log(y))/(x*y), assumePosReal=True)
== log(x**(1/(x*y))*y**(-1/(x*y)))+x/y
+    assert logcombine(log(x)*2*log(y)+log(z), assumePosReal=True) ==
log(z*y**log(x**2))
+
+
--
1.6.2


>From 0925083952426237794d7b3c67675f9977318b58 Mon Sep 17 00:00:00 2001
From: Aaron Meurer <asmeu...@gmail.com>
Date: Wed, 20 May 2009 23:32:33 -0600
Subject: [PATCH 1/1] Added an XFAIL test.
 This is similar to Issue 1274; match fails because 2/3 is used
instead of Rational(2,3).  Also made the match variables dummy, which
is tested by the passing version of the XFAIL test.

---
 sympy/simplify/simplify.py            |    4 ++--
 sympy/simplify/tests/test_simplify.py |   11 ++++++++++-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/sympy/simplify/simplify.py b/sympy/simplify/simplify.py
index f95184d..861d858 100644
--- a/sympy/simplify/simplify.py
+++ b/sympy/simplify/simplify.py
@@ -1231,8 +1231,8 @@ def _getlogargs(expr):
         return notlogs + alllogs

     if expr.is_Mul:
-        a = Wild('a', exclude=[log])
-        x = Wild('x')
+        a = Wild('a', exclude=[log], dummy=True)
+        x = Wild('x', dummy=True)
         coef = expr.match(a*log(x))
         if coef and (coef[a].is_real or expr.is_Number or
expr.is_NumberSymbol \
         or type(coef[a]) in (int, float) or (assumePosReal and not \
diff --git a/sympy/simplify/tests/test_simplify.py b/sympy/simplify/
tests/test_simplify.py
index c601f40..ba6a73a 100644
--- a/sympy/simplify/tests/test_simplify.py
+++ b/sympy/simplify/tests/test_simplify.py
@@ -365,7 +365,7 @@ def test_diff():
     assert simplify(diff(1/f(x),x)+f(x).diff(x)/f(x)**2) == 0
     assert simplify(f(x).diff(x,y)-f(x).diff(y,x)) == 0

-def test_logcombine():
+def test_logcombine_1():
     x, y = symbols("xy")
     a = Symbol("a")
     z, w = symbols("zw", positive=True)
@@ -380,5 +380,14 @@ def test_logcombine():
     assert logcombine((2+I)*log(x), assumePosReal=True) == I*log(x)
+log(x**2)
     assert logcombine((x**2+log(x)-log(y))/(x*y), assumePosReal=True)
== log(x**(1/(x*y))*y**(-1/(x*y)))+x/y
     assert logcombine(log(x)*2*log(y)+log(z), assumePosReal=True) ==
log(z*y**log(x**2))
+    assert logcombine((x*y+sqrt(x**4+y**4)+log(x)-log(y))/
(pi*x**Rational(2,3)*y**Rational(3,2)), assumePosReal=True) == log(x**
(1/(pi*x**Rational(2,3)*y**Rational(3,2)))*y**(-1/(pi*x**Rational(2,3)
*y**Rational(3,2)))) + (x**4 + y**4)**Rational(1,2)/(pi*x**Rational
(2,3)*y**Rational(3,2)) + x**Rational(1,3)/(pi*y**Rational(1,2))
+
+
+...@xfail
+def test_logcombine_2():
+    # The same as one of the tests above, but with Rational(a,b)
replaced with a/b.
+    # This fails because of a bug in matches.  See issue 1274.
+    x, y = symbols("xy")
+    assert logcombine((x*y+sqrt(x**4+y**4)+log(x)-log(y))/(pi*x**(2/3)
*y**(3/2)), assumePosReal=True) == log(x**(1/(pi*x**(2/3)*y**(3/2)))
*y**(-1/(pi*x**(2/3)*y**(3/2)))) + (x**4 + y**4)**(1/2)/(pi*x**(2/3)
*y**(3/2)) + x**(1/3)/(pi*y**(1/2))


--
1.6.2



>From 7c50da0e55a315d5a104ac1a31027cbe6094367e Mon Sep 17 00:00:00 2001
From: Aaron Meurer <asmeu...@gmail.com>
Date: Fri, 22 May 2009 23:41:13 -0600
Subject: [PATCH 1/1] Added Equality support in logcombine.

---
 sympy/simplify/simplify.py            |    5 +++++
 sympy/simplify/tests/test_simplify.py |    3 ++-
 2 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/sympy/simplify/simplify.py b/sympy/simplify/simplify.py
index b3526f8..2fa8a6f 100644
--- a/sympy/simplify/simplify.py
+++ b/sympy/simplify/simplify.py
@@ -4,6 +4,7 @@
         Derivative, Wild, Symbol, sympify, expand

 from sympy.core.numbers import igcd
+from sympy.core.relational import Equality

 from sympy.utilities import make_list, all
 from sympy.functions import gamma, exp, sqrt, log
@@ -1207,6 +1208,10 @@ def _getlogargs(expr):
     if type(expr) in (int, float) or expr.is_Number or
expr.is_Rational or \
     expr.is_NumberSymbol:
        return expr
+
+    if isinstance(expr, Equality):
+        return Equality(_logcombine(expr.lhs-expr.rhs,
assumePosReal=assumePosReal), Integer(0))
+
     if expr.is_Add:
         argslist = 1
         notlogs = 0
diff --git a/sympy/simplify/tests/test_simplify.py b/sympy/simplify/
tests/test_simplify.py
index ba6a73a..3f3d981 100644
--- a/sympy/simplify/tests/test_simplify.py
+++ b/sympy/simplify/tests/test_simplify.py
@@ -2,7 +2,7 @@
         collect, Function, powsimp, separate, sin, exp, Rational,
fraction, \
         simplify, trigsimp, cos, tan, cot, log, ratsimp, Matrix, pi,
integrate, \
         solve, nsimplify, GoldenRatio, sqrt, E, I, sympify, atan,
Derivative, \
-        S, diff, logcombine
+        S, diff, logcombine, Eq, Integer

 from sympy.utilities.pytest import XFAIL

@@ -381,6 +381,7 @@ def test_logcombine_1():
     assert logcombine((x**2+log(x)-log(y))/(x*y), assumePosReal=True)
== log(x**(1/(x*y))*y**(-1/(x*y)))+x/y
     assert logcombine(log(x)*2*log(y)+log(z), assumePosReal=True) ==
log(z*y**log(x**2))
     assert logcombine((x*y+sqrt(x**4+y**4)+log(x)-log(y))/
(pi*x**Rational(2,3)*y**Rational(3,2)), assumePosReal=True) == log(x**
(1/(pi*x**Rational(2,3)*y**Rational(3,2)))*y**(-1/(pi*x**Rational(2,3)
*y**Rational(3,2)))) + (x**4 + y**4)**Rational(1,2)/(pi*x**Rational
(2,3)*y**Rational(3,2)) + x**Rational(1,3)/(pi*y**Rational(1,2))
+    assert logcombine(Eq(log(x), -2*log(y)), assumePosReal=True) == Eq
(log(x*y**2), Integer(0))


 @XFAIL
--
1.6.2



>From 0d5698640a17365c024c688748552795e4d5ad38 Mon Sep 17 00:00:00 2001
From: Aaron Meurer <asmeu...@gmail.com>
Date: Sat, 23 May 2009 16:34:43 -0600
Subject: [PATCH] Made logcombine more robust,
 in particular, with equalities and logs inside of functions (like acos
(-log(x))).  Also added tests for everything that I fixed.

---
 sympy/simplify/simplify.py            |   33 +++++++++++++++++++++++++
+-------
 sympy/simplify/tests/test_simplify.py |    7 ++++++-
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/sympy/simplify/simplify.py b/sympy/simplify/simplify.py
index 2fa8a6f..9ae5ec3 100644
--- a/sympy/simplify/simplify.py
+++ b/sympy/simplify/simplify.py
@@ -1210,7 +1210,16 @@ def _getlogargs(expr):
        return expr

     if isinstance(expr, Equality):
-        return Equality(_logcombine(expr.lhs-expr.rhs,
assumePosReal=assumePosReal), Integer(0))
+        retval = Equality(_logcombine(expr.lhs-expr.rhs,
assumePosReal=\
+        assumePosReal), Integer(0))
+        # If logcombine couldn't do much with the equality, try to
make it like
+        # it was.  Hopefully extract_additively won't become smart
enought to
+        # take logs apart :)
+        right = retval.lhs.extract_additively(expr.lhs)
+        if right:
+            return Equality(expr.lhs, logcombine(-right))
+        else:
+            return retval

     if expr.is_Add:
         argslist = 1
@@ -1220,20 +1229,26 @@ def _getlogargs(expr):
             if i.is_Function and i.func == log:
                 if (i.args[0].is_positive or (assumePosReal and not \
                 i.args[0].is_nonpositive)):
-                    argslist *= _logcombine(i.args[0],
assumePosReal=assumePosReal)
+                    argslist *= _logcombine(i.args[0], assumePosReal=
\
+                    assumePosReal)
                 else:
                     notlogs += i
-            elif i.has(log):
+            elif i.is_Mul and any(map(lambda t: getattr(t,'func',
False)==log,\
+            i.args)):
                 largs = _getlogargs(i)
                 if largs.is_positive and i.extract_multiplicatively
(log(largs)).\
                 is_real or (assumePosReal and not
largs.is_nonpositive and not \
-                i.extract_multiplicatively(log
(largs)).is_real==False):
+                getattr(i.extract_multiplicatively(log
(largs)),'is_real',\
+                False)==False):
                     coeflogs += _logcombine(i,
assumePosReal=assumePosReal)
                 else:
                     notlogs += i
+            elif i.has(log):
+                notlogs += _logcombine(i,
assumePosReal=assumePosReal)
             else:
                 notlogs += i
-        alllogs = _logcombine(log(argslist)+coeflogs,
assumePosReal=assumePosReal)
+        alllogs = _logcombine(log(argslist)+coeflogs, assumePosReal=\
+        assumePosReal)
         return notlogs + alllogs

     if expr.is_Mul:
@@ -1245,9 +1260,13 @@ def _getlogargs(expr):
         coef[a].is_imaginary)):
             return log(coef[x]**coef[a])
         else:
-            return expr
+            return _logcombine(expr.args[0],
assumePosReal=assumePosReal)*\
+            reduce(lambda x, y: _logcombine(x,
assumePosReal=assumePosReal)*\
+            _logcombine(y, assumePosReal=assumePosReal), expr.args
[1:], 1)
+
     if expr.is_Function:
-        return expr.func(_logcombine(expr.args[0],
assumePosReal=assumePosReal))
+        return apply(expr.func,map(lambda t: _logcombine(t,
assumePosReal=\
+        assumePosReal), expr.args))
     if expr.is_Pow:
         return _logcombine(expr.args[0], assumePosReal=assumePosReal)
**\
         _logcombine(expr.args[1], assumePosReal=assumePosReal)
diff --git a/sympy/simplify/tests/test_simplify.py b/sympy/simplify/
tests/test_simplify.py
index 3f3d981..89891d9 100644
--- a/sympy/simplify/tests/test_simplify.py
+++ b/sympy/simplify/tests/test_simplify.py
@@ -2,7 +2,7 @@
         collect, Function, powsimp, separate, sin, exp, Rational,
fraction, \
         simplify, trigsimp, cos, tan, cot, log, ratsimp, Matrix, pi,
integrate, \
         solve, nsimplify, GoldenRatio, sqrt, E, I, sympify, atan,
Derivative, \
-        S, diff, logcombine, Eq, Integer
+        S, diff, logcombine, Eq, Integer, gamma, acos

 from sympy.utilities.pytest import XFAIL

@@ -382,6 +382,11 @@ def test_logcombine_1():
     assert logcombine(log(x)*2*log(y)+log(z), assumePosReal=True) ==
log(z*y**log(x**2))
     assert logcombine((x*y+sqrt(x**4+y**4)+log(x)-log(y))/
(pi*x**Rational(2,3)*y**Rational(3,2)), assumePosReal=True) == log(x**
(1/(pi*x**Rational(2,3)*y**Rational(3,2)))*y**(-1/(pi*x**Rational(2,3)
*y**Rational(3,2)))) + (x**4 + y**4)**Rational(1,2)/(pi*x**Rational
(2,3)*y**Rational(3,2)) + x**Rational(1,3)/(pi*y**Rational(1,2))
     assert logcombine(Eq(log(x), -2*log(y)), assumePosReal=True) == Eq
(log(x*y**2), Integer(0))
+    assert logcombine(Eq(y, x*acos(-log(x/y))), assumePosReal=True)
== Eq(y, x*acos(log(y/x)))
+    assert logcombine(gamma(-log(x/y))*acos(-log(x/y)),
assumePosReal=True) == acos(log(y/x))*gamma(log(y/x))
+    assert logcombine((2+3*I)*log(x), assumePosReal=True) == log
(x**2)+3*I*log(x)
+    assert logcombine(Eq(y, -log(x)), assumePosReal=True) == Eq(y, log
(1/x))
+


 @XFAIL
--
1.6.2

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

Reply via email to