symengine / SymEngine.jl

Julia wrappers of SymEngine
MIT License
192 stars 43 forks source link

More predictable order of parameters #94

Open kindlychung opened 7 years ago

kindlychung commented 7 years ago

For example here is a toy implementation of deepest descent algorithm:

using SymEngine
using Roots

x1, x2 = symbols("x1, x2")
x1_val = 1
x2_val = 1
@vars s t
F(x1, x2) = (x1 - 1)^2 + x2^3 - x1 * x2
dFx1 = diff(F(x1, x2), x1)
dFx2 = diff(F(x1, x2), x2)
dFx1(x1_val, x2_val)
dFx2(x1_val, x2_val)
newx1 = x1 - s * dFx1
newx2 = x2 - s * dFx2
newx1(s, x2_val, x1_val)
newx2(s, x2_val, x1_val)
ϕ = F(newx1, newx2)
dϕ = diff(ϕ, s)
dϕ(s, x2_val, x1_val)

while true 
  s_val = fzero(dϕ(s, x2_val, x1_val), 0.1)
  tmp1 = newx1(s_val, x2_val, x1_val)
  tmp2 = newx2(s_val, x2_val, x1_val)
  if abs(tmp1 - x1_val) < 1e-8 && abs(tmp2 - x2_val) < 1e-8 
    break
  else 
    x1_val = tmp1 
    x2_val = tmp2
  end
end

As you can see, the expression dFx1 takes x1, x2 as parameters, while newx1 takes s, x2, x1 as parameters, in that order. There is no logic in this and it is awkward to use.

Would be nice if the parameters are ordered by a certain rule.

isuruf commented 7 years ago

You should use dFx1(x1=>x1_val, x2=>x2_val) and similarly for newx1.

Problem with not using these keyword args (is that the Julia name?) is that without them the number of variables depend on the expression.

For example assume you order according to alphabetic order, x, y.

expr = x + y^2
print(expr(1, 2))
expr = diff(e, y)
print(expr(1, 2))

expr is 2*y at the end, but it would print 2 instead of 4, because SymEngine doesn't know about x and y and knows only about y.

I hope this clarifies the issue. Let me know if you have any doubts.