Am working on code to derive mathematical relations, its initial purpose 
was in the field of non-commutative geometry however it appears to have 
become generally useful, feels like a good idea if we make the base self 
contained and release it as a separate package upon which more specialized 
ones can be built.

The code is here: https://github.com/jhlq/fys/tree/master/ncg
quin@Nicol:~/fys/ncg$ julia -L equations -q

Let's start from the top, the most recent file is matchers.jl which 
currently contains one matcher function that checks if an equation matches 
the pattern ax^2+bx+c=0. By writing such matchers (and introducing types 
for new operators) the base can readily be extended to solve custom 
equations. The quadratic matcher in action: 

julia> @time solve(:a*(:x*:y*:z)^2+:b*:y*:z*:x+:c,Function)[end] #the type 
specifies which kind of operator to apply
elapsed time: 1.779767594 seconds (426648608 bytes allocated, 25.89% gc 
time)
Equation(Expression({:x,:z,:y}),Expression({-1,:b,÷(Expression({2,:a})),:+,-1,Sqrt(Expression({:b,:b,:+,-4,:a,:c})),÷(Expression({2,:a}))}))

The Equation type is specified in equations.jl, it has two fields, lhs and 
rhs. The solve function when given an expression assumes it is the lhs of 
an equation with rhs=0 and finds solutions by calling the matches function 
which so far also accepts the Sqrt and Div types as ops, these types 
implement their own simplify methods. The original matches passes terms and 
factors from left to right:

julia> matches(:x+:y)
6-element Array{Equation,1}:
 Equation(:y,Expression({-1,:x}))        
 Equation(1,Expression({-1,:x,÷(:y)}))   
 Equation(0,Expression({-1,:x,:+,-1,:y}))
 Equation(:x,Expression({-1,:y}))        
 Equation(1,Expression({-1,:y,÷(:x)}))   
 Equation(0,Expression({-1,:y,:+,-1,:x}))

Now we descend into the base at common.jl. The function simplify is 
essential and called everywhere (probably too manywhere), it resolves 
nested expressions and sums it all up:

julia> ex=(:x+3+9*:x)^3
Expression({Expression({:x,:+,3,:+,Expression({9,:x})}),Expression({Expression({:x,:+,3,:+,Expression({9,:x})}),Expression({:x,:+,3,:+,Expression({9,:x})})})})

julia> simex=simplify(ex)
Expression({1000,:x,:x,:x,:+,900,:x,:x,:+,270,:x,:+,27})

julia> evaluate(ex,[:x=>1])==evaluate(simex,[:x=>1])
true

A crucial component of simplify is componify which is the trustable cookie 
unwrapper (technical term), it extracts components without eating anyting:

julia> ex=:x-(:x-3)+(:y+3)^2
Expression({:x,:+,-1,:x,:+,-1,-1,3,:+,Expression({Expression({:y,:+,3}),Expression({:y,:+,3})})})

julia> ex=componify(ex)
Expression({:x,:+,-1,:x,:+,-1,-1,3,:+,:y,:y,:+,:y,3,:+,3,:y,:+,3,3})

One final frequently used internal function is addparse, it returns an 
array of arrays with factors. For many cases the iterative shorthand will 
be sufficient:

julia> for term in ex;print(term);end
{:x}{-1,:x}{-1,3}{:y,:y}{:y,3}{3,:y}{3,3}

There are a whole host of additional details that optimization pros 
presumably can have many field days, camping trips and holidays with. Will 
continue nurturing these wines to climb toward quantum gravity and desire 
the community to be involved so everyone is very welcome to hack away at 
the jungle, add branches and tread the paths created.

We have a choice to make, representing a structural birth for the code: 
What shall this package be named?

Reply via email to