~ for Formulas was actually in in-place macro!
For differential equations packages, the standard way to define a differential equation like the Lorenz equation:
$$ \begin{align} x\prime &= \sigma (y-x)\\ y\prime &= x (\rho - z) - y\\ z\prime &= xy - \beta z\\ \end{align} $$is the following:
In [ ]:
f = (du,u,p,t) -> begin
σ, ρ, β = p
du[1] = σ*(u[2]-u[1])
du[2] = u[1]*(ρ-u[3]) - u[2]
du[3] = u[1]*u[2] - β*u[3]
end
However, we can define a DSL to make this easier to do:
In [ ]:
g = @ode_def begin
dx = σ*(y-x)
dy = x*(ρ-z) - y
dz = x*y - β*z
end σ ρ β
In [ ]:
using JuMP
m = Model()
@variable(m, 0 <= x <= 2 )
@variable(m, 0 <= y <= 30 )
@objective(m, Max, 5x + 3*y )
@constraint(m, 1x + 5y <= 3.0 )
print(m)
status = solve(m)
println("Objective value: ", getobjectivevalue(m))
println("x = ", getvalue(x))
println("y = ", getvalue(y))
An easy way to write macros is the "QuoteLater" method:
The Julia manual is very complete on Metaprogramming: http://docs.julialang.org/en/release-0.5/manual/metaprogramming/
One fact that it misses: How to interpolate an expression as an expression (not as a value) into another expression.
In [ ]:
ex_new = Meta.quot(ex)
quote
still_expression = $(esc(ex_new))
end
You have a way to compute least squares, how about letting it work like an R function? Define your own version solve_least_squares(Y,X) using your previous result, and define the @~ macro so that way solve_least_squares(Y~1+X1+X2+X4) solves the least square problem on the data matrix X on its columns 1, 2, and 4.
Metaprogramming is hard the first few times you do it. You might want to work in pairs!
Hints:
string to change a symbol to a stringparse a string to a numberargs field of an expression: it's an array that holds a bunch of goodies!
In [ ]:
y = rand(10)
X = rand(10,4)
y~1+X1+X2+X4 # Make a tuple
solve_least_squares(y~1+X1+X2+X4) # Solve the least square problem on a tuple