I am currently trying some functionalities of Julia regarding symbolic expressions. Coming from Matlab I searched the documentation for symbolic something with little success until I found some info about the expr = :(<content>) notation.
I started with the declaration of my first function : fun1 = :(1-x) which works fine. However, I need to reuse my expression or manipulations of it afterwards.
After searching a bit, I still did not find a way to say e.g fun2 = -fun1. How does one manipulate expressions once they are declared?
EDIT My example statement being a bit restrictive, an additional case would be the construction of a array of expression using pre-declared expresions as in exprarray = [fun1 0 -2*fun2+3]
you can interpolate expressions with $:
julia> fun1 = :(1-x)
:(1 - x)
julia> fun2 = :(-$fun1)
:(-((1 - x)))
EDIT
The same works for the array :
julia> exprarray = :([$fun1 0 -2*$fun2+3])
:([1 - x 0 -2 * -((1 - x)) + 3])
Related
I have the following equation:
and I'm trying to generate the analytic derivative .
I know you can use deriv() and D() for an expression , but I cannot seem to figure out how to actually implement a sum or a product notation into an expression.
partial/incomplete answer
The Deriv package offers a more robust (and extensible) alternative to the base R D and deriv functions, and appears to know about sum() already. prod() will be difficult, though (see below).
A very simple example:
library(Deriv)
Deriv(~ sum(b*x), "b")
## sum(x)
A slightly more complex answer that sort-of works:
Deriv(~ sum(rep(a, length(x)) + b*x), c("a","b"))
## c(a = sum(rep(x = 1, length(x))), b = sum(x))
Note here that sum(a+b*x) doesn't work (returns 1) for the derivative with respect to a, for reasons described in ?Deriv (search for "rep(" in the page): the rep() is needed to help Deriv sort out scalar/vector definitions. It's too bad that it can't simplify sum(rep(x=1, length(x))) to length(x) but ...
Trying
Deriv( ~ exp(sum(a+b*x))/prod(1+exp(a+b*x)))
gives an error
Could not retrieve body of 'prod()'
You might be able to add a rule for products to the derivatives table, but it will be tricky since prod() takes a ... argument. Let's try defining our own function Prod() which takes a single argument x (I think this is the right generalization of the product rule but didn't think about it too carefully.)
Prod <- function(x) product(x)
drule[["Prod"]] <- alist(for(i in 1:length(x)) { .dx[i]*Prod(x[-i]) })
Deriv(~Prod(beta*x), "x"))
Unsurprisingly (to me), this doesn't work: the result is 0 ... (the basic problem is that using .dx[i] to denote the derivative of x[i] doesn't work in the machinery).
I don't know of a way to solve this in R; if I had this problem (depending on more context, which I don't know), I might see if I could find a framework for automatic differentiation (rather than symbolic differentiation). Unfortunately most of the existing tools for autodiff in R use backends in C++ or Julia (e.g. see here (C++ + Rcpp + CppAD), here (Julia), the TMB package (C++/CppAD/user-friendly extensions). There's an ancient pure-R github project radx but it looks too incomplete to use ... (FWIW autodiffr requires a Julia installation but doesn't actually require you to write any Julia code, AFAICS ...)
It's amazing that the internet is totally void of this simple question (or similar). Or I'm just very bad at searching. Anyway, I simply want to store values generated by a for-loop in an array and print the array. Simple as that.
On every other language Matlab, R, Python, Java etc this is very simple. But in Julia I seem to be missing something.
using JuMP
# t = int64[] has also been tested
t = 0
for i in 1:5
vector[i]
println[vector]
end
I get the error
ERROR: LoadError: BoundsError
What am I missing?
You didn't initialize vector and you should call the method println like this following way, in Julia 1.0 :
vector = Array{Int,1}(undef, 5)
for i in 1:5
vector[i] = i
println(vector[i])
end
Or, more quickly, with a comprehension list :
vector = [i for i in 1:5]
for i in 1:5
println(vector[i])
end
Another possibility using push! method :
vector = []
for i in 1:5
push!(vector, i)
println(vector[i])
end
I have the following code that I'm using as part of an attempt to implement the most accurate equation of state for water in Julia 0.6.
struct parameterizedeos
Tc::Float64
ρc::Float64
R::Float64
#parameters for ideal gas portion
n₀::Vector{Float64}
γ₀::Vector{Float64}
end
h2o_n₀ = [-8.3204464837497, 6.6832105275932, 3.00632, 0.012436, 0.97315, 1.27950,
0.96956, 0.24873]
h2o_γ₀ = [1.28728967, 3.53734222, 7.74073708, 9.24437796, 27.5075105]
function Σ(expr)
return sum(eval(#. expr))
end
function ig(eos, δ, τ)
end_ = Σ(eos.n₀[4:8]*log(1-exp(-eos.γ₀)*τ))
return log(δ) + eos.n₀[1] + eos.n₀[2]*τ + eos.n₀[3]*log(τ) + end_
end
Tc = 647.096
ρc = 322
R = 0.46151805
eos = parameterizedeos(Tc,ρc,R,h2o_n₀,h2o_γ₀)
δ₁ = 838.025/ρc
τ₁ = Tc/500
print(ig(eos,δ₁,τ₁))
Σ is supposed to be a simple form of the corresponding operator from math, while δ and τ use the nomenclature from the linked reference (dimensionless density and temperature respectively). I get LoadError: DimensionMismatch("Cannot multiply two vectors").
I've played around with all sorts of subexamples in the Julia REPL and they all seem to work just as I'd expect. Σ(log(1-exp(-h2o_γ₀)*τ)) vectorizes and sums the elements as expected. Heck, eval(#. h2o_n₀[4:8]*log(1-exp(-h2o_γ₀)*τ) happily returns a 5-element vector. But calling Σ(h2o_n₀[4:8]*log(1-exp(-h2o_γ₀)*τ)) breaks.
I'm a noob at Julia and at arcane things like macros, so anyone could help me figure out what's going on here, that would be great.
Try this (using .* and log. and exp. instead)
function ig(eos, δ, τ)
end_ = Σ(eos.n₀[4:8] .* log.(1-exp.(-eos.γ₀)*τ))
return log(δ) + eos.n₀[1] + eos.n₀[2]*τ + eos.n₀[3]*log(τ) + end_
end
The error you get: DimensionMismatch("Cannot multiply two vectors") happens inside the function ig when eos.n₀[4:8]*log(1-exp(-eos.γ₀)*τ) is evaluated, before the result is supposed to be passed to Σ.
Furthermore: #. is expanded at parse time in global scope, it adds dots to function calls and operators. expr is just a variable, not an operator, not a function call, so therefore #. does nothing. eval also does nothing, so sum(eval(#. expr)) is identical to just plain sum(expr). But since the program fails before that point, this is not your problem.
(Edit: Actually eval does more than nothing. It does some work; the results are identical, but the extra work is completely wasted.)
Solution: Delete the function Σ, you don't need it. Re-write the function ig as follows:
function ig(eos, δ, τ)
end_ = sum(#. eos.n₀[4:8] * log(1 - exp(-eos.γ₀) * τ))
return log(δ) + eos.n₀[1] + eos.n₀[2]*τ + eos.n₀[3]*log(τ) + end_
end
Edit:
I've played around with all sorts of subexamples in the Julia REPL and
they all seem to work just as I'd expect. Σ(log(1-exp(-h2o_γ₀)*τ))
vectorizes and sums the elements as expected. Heck, eval(#. h2o_n₀[4:8]*log(1-exp(-h2o_γ₀)*τ) happily returns a 5-element vector.
But calling Σ(h2o_n₀[4:8]*log(1-exp(-h2o_γ₀)*τ)) breaks.
Everything here works as expected. log and exp vectorize automatically, for now, but that behaviour is deprecated. In version 1.0 calling log or exp (or sin or sqrt, etc.) on a vector will be an error.
eval(#. h2o_n₀[4:8]*log(1-exp(-h2o_γ₀)*τ) vectorizes this expression as expected. (But remove the eval, you're just calling it on a value, which it makes no sense to eval.)
And Σ(h2o_n₀[4:8]*log(1-exp(-h2o_γ₀)*τ)) fails because you're trying to multiply two vectors, something that has never worked (you can take the dot-product (using e.g. '* or dot), or do element-wise multiplication, though.) The fact that you later try to pass the result of this into Σis irrelevant.
I'm wondering whether it's possible to define a macro that can modify the values of an expression only if the values are of a specific type?
Here's a minimal example:
type Special
x::Int
end
f1(s, n::Special) = println("f1", s, n)
f2(s, n::Special) = println("f2", s, n)
x1 = Special(3)
x2 = Special(5)
expr = :(
f1("this is f1", x1),
f2("this is f2", x2)
)
Now a macro might be able to examine the values of the arguments to the functions, determine that x1 and x2 are of type Special, run some function to modify their values, say by changing 3 to 4 and 5 to 2 (it might involve comparing two values), then pass the expression back to the caller. The final result would be equivalent to calling:
f1("this is f1", 4)
f2("this is f2", 2)
I found that it's possible to access the values in a macro via:
eval(eval(filter(x -> typeof(eval(x)) == Special, expr.args[1].args))[1]).x
=> 3
but although this works it looks wrong, and I'm might either be doing it wrong or trying to do something too way out...
No, you should never try to check types or values inside macros. Using eval to figure out the type or value of something in a macro may work in very limited situations, but it'll break in almost every real use. Instead, just have the macro insert a call to a generic function — that's where Julia excels at picking apart types (as method dispatch) and values (within the method):
munge_special(x::Special) = Special(x.x + 42)
munge_special(x) = x
macro do_something_special(x)
return :(munge_special($(esc(x))))
end
julia> #do_something_special Special(2)
Special(44)
julia> #do_something_special 3
3
In the R-language I am able to declare a function and to see the body of the function like so:
> megafoobar = function(x){ return(x + 10000 )}
> body(megafoobar)
{
return(x + 10000)
}
Is something like this also possible in Julia? I wrote a function that was very useful and it is still in memory/callable but I forgot how I wrote it. I am hoping such a method exists in Julia so I can find out how I wrote it.
For functions defined in a package, you can use less or #less.
The former, takes a function name (and returns the first definition,
which need not be the one you want), the latter, a function call.
less(less) # First definition of less,
# with signature (String,Integer)
#less less(less) # Definition of less(f::Callable)
But this will not work with functions you defined yourself in the REPL.
For those, you can use code_typed, but it only returns the AST (abstract
syntax tree) of your code, which is less readable.
You also need to provide the type of the arguments,
because there can be several functions with the same name:
you can get them with methods.
f(x::Number) = x + 1
f(x::AbstractArray) = length(x)
methods(f)
# 2 methods for generic function "f":
# f(x::Number) at none:1
# f(x::AbstractArray{T,N}) at none:1
code_typed(f,(Number,)) # Give the argument types as a tuple
# 1-element Array{Any,1}:
# :($(Expr(:lambda, {:x}, {{},{{:x,Number,0}},{}}, :(begin # none, line 1:
# return x::Number + 1
# end))))
the answers said above are already good.
I personally use the good old ctrl+r in the REPL and write the name of the function as you define it to find the block of code when you define your function.