-
Notifications
You must be signed in to change notification settings - Fork 76
[for discussion] an abstract symbolic type and chain rule code #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Lubin's chainRule code.
|
There's something strange about using operator overloading to build up expression trees when the Julia parser can already give you them through macros. While operator overloading is the only possible approach in many languages, it's especially slow and creates lots of temporary objects. We can completely avoid it by using some Julia magic: function processExpr(x::Expr)
if x.head == :call
quoted = Expr(:quote,x.args[1])
code = :(Expr(:call,$quoted))
for y in x.args[2:end]
push!(code.args,processExpr(y))
end
return code
else
return x
end
end
processExpr(x::Any) = x
macro sexpr(x)
esc(processExpr(x))
endThen julia> x = BasicVariable(:x)
x
julia> y = BasicVariable(:y)
y
julia> @sexpr x^3 + sin(x^2 + 1)
:(+(^($(x),3),sin(+(^($(x),2),1))))This is a simplified version of what's implemented in https://github.com/IainNZ/NLTester/blob/master/julia/nlp.jl. (Note I didn't actually test the above code, and the escaping behavior isn't precisely correct.) The macro-fu is a bit heavy but what the macro does is generate code that regenerates the input expression with the values of all symbols spliced in. This approach will give improvements of orders of magnitude over using operator overloading. The current approach also defines the complete set of operator overloads for anything that inherits from |
|
Good points, Miles. I'll play around with implementing that approach. In my On Fri, Mar 29, 2013 at 6:07 PM, Miles Lubin notifications@github.comwrote:
|
|
Miles, your |
|
In Devectorize.jl, I implemented the I would be nice to extract this common part to a package (e.g. SymbolicExpressions.jl) and merge the efforts there, so as to provide support to other packages that rely on symbolic expressions. (Now, I have known five packages rely on abstract expressions in one or the other way: Calculus, NLP, Devectorize, Sims, and DeMat) Actually, @StefanKarpinski once mentioned this idea in julia-dev (https://groups.google.com/forum/?fromgroups=#!searchin/julia-dev/common$20infrastructure/julia-dev/xIrPPMY-6qM/h1vhxjF7hwAJ) cc @ViralBShah |
|
Is vector calculus on the plan? If vector calculus is included, this may get real use in many practical problems. For example, in a regression problem, I would write |
|
I would be happy with such a package being called simply Symbolic. Seems like an excellent piece of foundational infrastructure for other packages to build on. |
|
I'll be away all weekend. I'm happy to look over this next week and merge a finished product or introduce a dependency on a new Symbolic package. |
|
@StefanKarpinski: What's the right way to escape expressions in @tshort Note you can also make multiple frontend macros like: macro differentiate(x,wrt)
:(differentiate($(esc(processExpr(x))),$(esc(wrt)))
endSo that you can do @differentiate(x^3 + sin(x^2 + 1),x) |
|
John's differentiation code was more complete than that in chainRule. I'm trying to merge them, but it's a work in progress. |
|
@lindahua, what do you think should be in here for a type SymbolicExpression <: Symbolic
ex::Expr
end
sexpr(hd::Symbol, args::ANY...) = SymbolicExpression(Expr(hd, args...))
typealias SExpr Union(Expr, SymbolicExpression)Is the idea that you could use SExpr anywhere you would use Expr for symbolic operations? Or, are you after something different? |
|
John, what's in here is now more or less ready for review. I basically ended up reworking Of course, more discussion is welcome on other symbolic features to include. |
|
Ok. This all looks good to me. I'll make a more thorough review tomorrow morning and then merge this. |
src/differentiate.jl
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be if xp != 0? There's also an instance of this for the bessel functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, Miles. Thanks for the review. I'll fix this tomorrow.
|
I made a couple inline comments, but otherwise looks great. |
|
I'm happy enough with this that I'm going to merge it. Any more changes you'd like to make? |
|
I don't have more immediate changes, John. Note that I did remove your On Mon, Apr 1, 2013 at 12:32 PM, John Myles White
|
|
It was very limited. This new code is a good impetus to rethinking what I had done. |
[for discussion] an abstract symbolic type and chain rule code
John,
This is based on the julia-dev discussion here:
https://groups.google.com/d/msg/julia-dev/3rqlCOf2TCw/cpRk1e7fKrMJ
This pull request includes:
https://github.com/IainNZ/NLTester/blob/master/julia/nlp.jl#L81
Here is an example:
Here are some items for discussion:
:+another for:cosand so on. It seems like it works well. It relies on types being able to be parametrized by a symbol.differentiatebetter.chainRuledoesn't have a simplifying step.x == 3return an expression ifxis a symbolic variable. I ended up usingisequalwhen I wanted to compare the actual contents rather than return an expression.:x^2 + cos(:z). That would be possible, but that'd be classified as monkey patching unless we got buy-in from Julia-core. Because we can't operate on Expr's, I added a SymbolicExpression type.