On Oct 5, 2012, at 9:52 AM, Matthew Rocklin <[email protected]> wrote:

I have to disagree, and believe me, I'm the last person to prefer an OO
> style over an imperative one when imperative would do just fine (this is
> one of the reasons that I hate Java). But in this case, I think it will
> remove a lot of code duplication. You run into problems with a functional
> interface in Python real fast because there are no attributes, and it's
> impossible to inspect the code of the function. So you'll end up creating
> functions that return dictionaries of the data you want. When that happens,
> you are better off just using a class, which is a much cleaner way to have
> a namespace (and you also get inheritance for free!).
>

What data would one send around? I don't understand.


In my example, the data is the identity, and the functions that the terms
in the identity represent. Equivalently, it could be the identity as tan(x)
- sin(x)/cos(x) and the free variable of identity, x.


How would my tan = sin/cos example look in your proposed functional model?
>

def break_tan(expr):
    if expr.is_Tan: return sin(expr.arg) / cos(expr.arg)
    else          : return expr

def combine_sincos(expr):
    # search for sins and cosines in a Mul, combine them and recreate the
Mul


You are going to have a ton of functions that look exactly the same:

if expr.is_whatever: apply rule
else: pass

My point is that we should write that once, in the IdentityRule class, and
just change the identity in the subclass.

Additionally, there is duplication by writing essentially the same identity
twice with tan -> sin/cos and sin/cos -> tan. So I think that since we have
a solve() function, we should be able to write it just once, and figure out
how to get what we want from what we have.

If all this is buried in function closures, we won't be able to use the
data (in this case, the identities) in any kind of intelligent way, other
than "try doing things (randomly) in different orders to see what you get".

Remember that sympy can do complex math. If we have a system of equations,
we can solve that system. If we have a set of logical statements, we can
make deductions from those statements. If some chain of rules somehow
telescopes to something far simpler, we can symbolically compute that.  We
should use this fact whenever possible, which means representing things
symbolically whenever possible.

Aaron Meurer



Now we need to think about how we apply these rules. We might not want to
include them both in the same system (we need to ensure that our rules
terminate). We might make a strategy that tries to greedily minimize some
function of an expression (an example might be the length of the string
representation of the expr). In this case both rules could be active and
only the results of the combine_sincos rule would be accepted.

In another situation you might want minimally complex atomic functions
(something like expand). In this case a strategy might be developed which
rejects the change that combine_sincos gives and instead prefers break_tan.

In this example again we've separated out a mathematical transformation
from how it is used. We can build a strategy
"apply-all-these-rules-cleverly-so-that-they-minimize-this-function(fn,
*rules)" and then just throw in the rules we care about. If we build a
registry we might tag both of these rules with a "trig" tag. This is a
separate issue though.

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

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

Reply via email to