JuliaMath / Calculus.jl

Calculus functions in Julia
Other
275 stars 78 forks source link

Tests of differentiate() compares expressions too strictly #14

Open ivarne opened 11 years ago

ivarne commented 11 years ago

Correct changes to the implementations of differentiate() and simpelify() breaks tests if the order of arguements are changed.

>>> isequal(:(a+b) , :(b+a))
false

The test should use a less strict comparison function for expressions than isequal, so that it wil be easier to write tests and easier to modify the code without having to modify tests. It is very easy to make mistakes when updating tests to new behaviour.

johnmyleswhite commented 11 years ago

This would be very helpful, but it's a large body of work: you need to build tests for expressions that are robust to operations that respect commutativity and associativity. Worth doing, but going to take some time.

ivarne commented 11 years ago

A first version that knows a short list of commutative operations (+, *) and checks if they are equal if the arguments reordered should not be too much work. It will be much harder if one also wants to make :(a+b-c) == :(a-c+b), but I think that canonicalizing the expressions to something like :(a+b+(-c)) might be an option.

A complicating factor might be that * is not commutative on materixes so that symbols and expressions can't be reorderd safely, because the dimensions is unknown.

I have some trouble finding a proper name for a comparison function, if we are not going to redefine isequal(a::Expr, b::Expr) or ==(a::Expr, b::Expr). What do you tink about usin isapprox(a::Expr, b::Expr), or do you have any better suggestions?

johnmyleswhite commented 11 years ago

Why not isequivalent or isequiv to indicate that it's not equality in the CS, but equality in the mathematical sense?

I don't think any of the existing code is likely to work correctly for matrices to begin with. Does it?

ivarne commented 11 years ago

isequivalent(a::Expr, b::Expr) feels like the right option.

I would expect that it works for vectors and matrix variables, at least in the simple cases i can think of, but it can't differentiate with respect to a vector, without some code changes.

Introducing differentiation with respect to a vector will probably introduce lots of possibility for user error and missunderstanding, so some verification algorithms might be needed. I am not sure if the automatic broadcasing rules would work as expected. The shortcuts and simplification routines would also need to be wetted. In the simplest sense the only modification would be to replace 0 with zeros(size(wrt)...), 1 with ones(size(wrt)...), dn/dn = eye(size(n)...).

ivarne commented 11 years ago

I tried to write a isequivalent(a::Expr, b::Expr) function but most of my ideas fitted better in the simplify() metods and it felt wrong to not write them there. The simple solution was

isequivalent(a::Expr, b::Expr) = isequal(simplify(a),simplify(b))

To make it more robust for comparison i implemented some canonicalization but I am not sure if the sorting of arguments to the + operator belongs in a simplify.

You can have a look at my changes at https://github.com/ivarne/Calculus.jl/commits/advanced_simpelify. Please comment.

johnmyleswhite commented 11 years ago

I'll get to this soon. Sorry for the delay: my mother is ill and I've spent the last week in the hospital with her.

ivarne commented 11 years ago

I'll be away from the internett for at least the next 1-3 weeks, so you don't have to hurry.

I really like the possibilities in Julia for manipulating expressions and evaluating them directly. It is makes it much easier to write code to manipulate equations and preparing for efficient computation. My plan is to make a framework for thermodynamic state equations, but the first step is to get the differentiation right.

I tried to search for a rationale for using the SymbolParameter{:op} approach with multiple dispatch in differentiation and simplification, but i did not find any discussion. The first thing I did when learning about Julia metaprogramming was to write differentiation routines, but I Dict{Symbol, Expr} that i referenced when I encountered a :call. If users are able to change that dict they migt use the differentiation routines for different purpuses and change rules if they does not think they are correctly implemented.

I hope Julia succeeds and reaches a point where universities stop teaching MATLAB. I feel so sorry for all the students who spent much time learning the commercial product, only to get an employer that does not think the price is worth it.