Simplest form of dependence

21 views
Skip to first unread message

Aaron Meurer

unread,
Mar 15, 2012, 12:14:33 AM3/15/12
to sy...@googlegroups.com
Hi.

I just created http://code.google.com/p/sympy/issues/detail?id=3148.
The issue is related to constantsimp() in the ODE module. Basically,
right now, it converts things like 2*C1 + C1**2*x + (C1 + 1)*x**2 into
C1 + C2*x + C3*x**2. In other words, it absorbs C1, C2, ... constants
into other constants and into each other, and then renumbers them,
because they are no longer the same constant.

I think this is a bad idea, because it makes it look like C1, C2, and
C3 are independent of each other, when they really aren't (because, in
this example, C2 = C1**2/4 and C3 = C1/4 + 1). What I think it should
do instead is return something like C1 + C1**2/2**2 + (C1/4 + 1)*x**2.
In other words, simplify one constant, and rewrite the others in
terms of it.

The question is, how do you determine how to do this? Has anyone ever
considered such an algorithm? The idea is that you have an
over-determined system of several equations, and you want to rewrite
the equations in terms of some new unknowns so that the whole system
becomes simpler. I think that idea could also be useful in solve(),
except there you also need to care about the relationship between the
new system variables and the old ones, and how simple they are.

Does anyone have any thoughts on how this could be achieved?

Aaron Meurer

Chris Smith

unread,
Mar 15, 2012, 1:47:34 AM3/15/12
to sy...@googlegroups.com
On Thu, Mar 15, 2012 at 9:59 AM, Aaron Meurer <asme...@gmail.com> wrote:
Hi.

I just created http://code.google.com/p/sympy/issues/detail?id=3148.
The issue is related to constantsimp() in the ODE module.  Basically,
right now, it converts things like 2*C1 + C1**2*x + (C1 + 1)*x**2 into
C1 + C2*x + C3*x**2.  In other words, it absorbs C1, C2, ... constants
into other constants and into each other, and then renumbers them,
because they are no longer the same constant.

I think this is a bad idea, because it makes it look like C1, C2, and
C3 are independent of each other, when they really aren't (because, in
this example, C2 = C1**2/4 and C3 = C1/4 + 1).  What I think it should
do instead is return something like C1 + C1**2/2**2 + (C1/4 + 1)*x**2.
 In other words, simplify one constant, and rewrite the others in
terms of it.


What is simpler about that, though? Now you have C1/4 where before you had 2*C1.

<work below comes from my model branch which was pull request 598>

    >>> var('C:4')
    (C0, C1, C2, C3)
    >>> condense(S('2*C1 + C1**2*x + (C1 + 1)*x**2'),x)
    (C0 + C1*x + C2*x**2, {C2: C1 + 1, C0: 2*C1, C1: C1**2})

There is only 1 constant on the right; additive and multiplicative absorbing occurred in defining C0 and C2 so we are free to re-write the C0-C2 in term of C1 from either of those expressions:

    >>> e, r = _
    >>> ri=r.items()
    >>> e.subs([(o,n.subs(C1,solve(Eq(*ri[0]),C1)[0])) for o,n in ri])
    C2*x**2 + 2*C2 + x*(C2 - 1)**2 - 2
    >>> e.subs([(o,n.subs(C1,solve(Eq(*ri[1]),C1)[0])) for o,n in ri])
    C0**2*x/4 + C0 + x**2*(C0/2 + 1) 

Again...neither of these is really simpler than you started with, are they?

/c

Aaron Meurer

unread,
Mar 16, 2012, 11:06:06 PM3/16/12
to sy...@googlegroups.com
OK, that was a bad example. I tried to come up with an example that
demonstrated all the ways that constants could simplify, but as a
result, I made something that can't really be simplified.

The example in the issue has C1**3 and C1**6. Clearly, this should be
simplified to C1 and C1**2. We could also do things like pull out
common factors, like 4*C1, 6*C1 => 2*C1, 3*C1. And I guess sometimes
removing terms from an Add can be beneficial, like C1 + 1, C1 + 2 =>
C1, C1 + 1.

It looks like your condense function already has much of the needed
machinery here, namely, computing the mapping. All that is needed now
I guess is to compute all the mappings (maybe with some heuristics,
like gcds), and use something expression size heuristics to find the
simplest one. The logic also needs to be modified a little for
dsolve(), because I think that constants should no longer be
renumbered (except maybe to put them in order in an expression). See
the issue I linked to.

Aaron Meurer

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

Chris Smith

unread,
Mar 16, 2012, 11:10:29 PM3/16/12
to sy...@googlegroups.com
On Sat, Mar 17, 2012 at 8:51 AM, Aaron Meurer <asme...@gmail.com> wrote:
OK, that was a bad example.  I tried to come up with an example that
demonstrated all the ways that constants could simplify, but as a
result, I made something that can't really be simplified.

The example in the issue has C1**3 and C1**6.  Clearly, this should be
simplified to C1 and C1**2.  We could also do things like pull out
common factors, like 4*C1, 6*C1 => 2*C1, 3*C1.  And I guess sometimes
removing terms from an Add can be beneficial, like C1 + 1, C1 + 2 =>
C1, C1 + 1.


Yes: all the Adds can be put together and the smallest additive constant removed; all powers (including bare symbols) can be put together and the lowers power greater than 1 removed. 

Abhishek Aggarwal

unread,
Mar 17, 2012, 12:24:46 AM3/17/12
to sy...@googlegroups.com
Hi,
 If we can treat C1 also as a variable 'y' then it won't lost its properties, as variable do not couple up and simplify to form a new variable. So may be this can work.

regards--
Abhishek Aggarwal
Computer Science 2nd year IIT DELHI

Aaron Meurer

unread,
Mar 17, 2012, 12:36:22 AM3/17/12
to sy...@googlegroups.com
I'm sorry, I don't follow what you are saying.

Aaron Meurer

> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.

> To view this discussion on the web visit
> https://groups.google.com/d/msg/sympy/-/ToiFX5e1vb8J.

Reply all
Reply to author
Forward
0 new messages