Plotting a function progressively with Julia - julia

I'm having a hard time doing an animation with Julia.
I have a function sf(t)=t^(1/2) going from tmin=0 to tmax=40, and I don't understand how to show the solution progressively from tmin to tmax. I have tried multiple approaches using the Julia docs and tutos I found online but they almost all use predefined functions (mainly sin and cos). The error Julia returns with the code below is MethodError: no method matching getindex(::typeof(sf), ::Int64). I have two questions: Why is this error appearing? and Is Ithere a simpler way to create an animation than to access indices in a loop?
Thanks
using Plots
tmin=0
tmax=40
tvec= range(tmin,tmax,length=100)
# I define the function here, but I'm not sure this is really needed
function sf(t)
t^(1/2)
end
# I create an "empty" plot to use it in animation
p=plot(sf,0)
# To create the animation, I do a loop over all t's present in tvec
anim = #animate for i ∈ 0:length(tvec)-1
push!(p,tvec(i),sf(i))
frame(anim)
end
# And finally I (try to) display the result
gif(anim,"scale_factor.gif",fps=30)

IIRC the #animate or #gif macro expects a plot at the end of the loop, so you want to do something like this:
anim = #animate for i ∈ eachindex(tvec)
plot(sf, tvec[begin:i])
end
gif(anim,"scale_factor.gif",fps=30)

Related

Replicating a Julia example

I am trying to learn Julia and I read this article about the quick success of Julia. In the last page of the article the author works a small example showing the benefits of multiple dispatch. They define a custom class Spect and define a plot() function for it. Then for an object sqw of type Spect they can call plot(sqw) without having to edit the original plot function. Moreover, this definition also affects similar plotting functions so that you can also call scatter(sqw) without problems. My issue is that author does not show the code, so I do not understand how can you achieve this. I am specially interested in the fact that just defining plot() for this new class is enough to also call other functions like scatter() without defining them for the new class.
Can someone write a small example of this like that of the article so that I can understand how all of this is achieved? Thank you in advance.
Cross posting my answer from Discourse:
It’s a shame the article doesn’t link to the code. Here’s my rough reproduction attempt. My version uses the dct and idct so I’m not getting the nice harmonics, but I think it shows the ideas pretty well.
using RecipesBase, FFTW
struct Spect
points :: AbstractRange
weights :: Vector{Float64}
end
function Spect(f::Function, min, max, n)
points = range(min, max, n)
Spect(points, dct(f.(points)))
end
#recipe function f(S::Spect)
S.points, idct(S.weights)
end
These definitions are enough for
using Plots
squarewave(x) = iseven(floor(x)) ? 1.0 : 0.0
sqw = Spect(squarewave, 0, 5, 20);
plot(sqw)
scatter(sqw)
and

Function taking Vectors and Scalars

I have a function that takes a vector
function foo(x::Vector{Int64})
x
end
How can I make it work also for scalars (i.e. turn them into one-element vectors)?
I know that I can do this:
foo(x::Int64) = foo([x])
but this stops being cool when there are more arguments, because you're writing multiple methods to achieve only one thing.
I think I something like foo(x::Union{Int64, Vector{Int64}}), but I don't know where or how it works or if it is the right thing to do.
Can anyone help?
You can make a helper function which either converts or does nothing. Then the main function can accept any combination:
_vec(x::Number) = [x]
_vec(x::AbstractVector) = x
function f(x, y, z) # could specify ::Union{Number, AbstractVector}
xv = _vec(x)
yv = _vec(y)
...
end
The ... could do the actual work, or could call f(xv, yv, zv) where another method f(x::AbstractVector, y::AbstractVector, z::AbstractVector) does the work --- whichever seems cleaner.
The main time this comes up is if the version of your function for vectors does the same thing for all of it's elements. In this case, what you want to do is define f(x::Int), and use broadcasting f.([1,2,3]) for the vector case.

Scilab optim function does not work

Can someone explain me how the optim function works in Scilab and give me a short example of that.
What I am trying to do is to maximize this function and find the optimal value
> function [f, g, ind]=cost(x, ind)
f= -x.^2
g=2*x
endfunction
// Simplest call
x0 = [1; -1; 1];
[fopt, xopt] = optim(cost, x0)
When I am trying to implement the function, I receive error
Variable returned by scilab argument function is incorrect.
I think I do some very basic mistake but can't understand where.
I think the answer is that -x.^2 does not return a scalar but a vector (x is a vector and x.^2 is an elementwise operation). You probably want to say something like x'*x. The objective function of an optimization problem should always be scalar (otherwise we end up with a multi-objective or multi-criteria problem which is a whole different type of problem).
Minimizing -x'*x is probably not a good idea
The gradient is not correct for f=-x'*x (but see previous point).

How to make nonsymbolic plot_vector_field in sage?

I have a function f(x,y) whose outcome is random (I take mean from 20 random numbers depending on x and y). I see no way to modify this function to make it symbolic.
And when I run
x,y = var('x,y')
d = plot_vector_field((f(x),x), (x,0,1), (y,0,1))
it says it can't cast symbolic expression to real or rationa number. In fact it stops when I write:
a=matrix(RR,1,N)
a[0]=x
What is the way to change this variable to real numbers in the beginning, compute f(x) and draw a vector field? Or just draw a lot of arrows with slope (f(x),x)?
I can create something sort of like yours, though with no errors. At least it doesn't do what you want.
def f(m,n):
return m*randint(100,200)-n*randint(100,200)
var('x,y')
plot_vector_field((f(x,y),f(y,x)),(x,0,1),(y,0,1))
The reason is because Python functions immediately evaluate - in this case, f(x,y) was 161*x - 114*y, though that will change with each invocation.
My suspicion is that your problem is similar, the immediate evaluation of the Python function once and for all. Instead, try lambda functions. They are annoying but very useful in this case.
var('x,y')
plot_vector_field((lambda x,y: f(x,y), lambda x,y: f(y,x)),(x,0,1),(y,0,1))
Wow, I now I have to find an excuse to show off this picture, cool stuff. I hope your error ends up being very similar.

R optim same function for fn and gr

I would like to use optim() to optimize a cost function (fn argument), and I will be providing a gradient (gr argument). I can write separate functions for fn and gr. However, they have a lot of code in common and I don't want the optimizer to waste time repeating those calculations. So is it possible to provide one function that computes both the cost and the gradient? If so, what would be the calling syntax to optim()?
As an example, suppose the function I want to minimize is
cost <- function(x) {
x*exp(x)
}
Obviously, this is not the function I'm trying to minimize. That's too complicated to list here, but the example serves to illustrate the issue. Now, the gradient would be
grad <- function(x) {
(x+1)*exp(x)
}
So as you can see, the two functions, if called separately, would repeat some of the work (in this case, the exponential function). However, since optim() takes two separate arguments (fn and gr), it appears there is no way to avoid this inefficiency, unless there is a way to define a function like
costAndGrad <- function(x) {
ex <- exp(x)
list(cost=x*ex, grad=(x+1)*ex)
}
and then pass that function to optim(), which would need to know how to extract the cost and gradient.
Hope that explains the problem. Like I said my function is much more complicated, but the idea is the same: there is considerable code that goes into both calculations (cost and gradient), which I don't want to repeat unnecessarily.
By the way, I am an R novice, so there might be something simple that I'm missing!
Thanks very much
The nlm function does optimization and it expects the gradient information to be returned as an attribute to the value returned as the original function value. That is similar to what you show above. See the examples in the help for nlm.

Resources