Plot complex inequality in Julia - julia

I have the mathematical expression |z - (-1)| < 1, with z element of Complexes, which is equivalent of a circle of radius 1 centered in (x,y)=(-1,0).
How can I plot this expression,
preserving the structure of the mathematical expression it was derived from, as much as
possible?
It should be an area.
What I tried so far:
using ImplicitEquations, Plots
f(a,b) = abs.(a+im*b - (-1))
plot(f<1)
The error I got:
ERROR: MethodError: no method matching isless(::typeof(f), ::Int64)
Closest candidates are:
isless(::Union{StatsBase.PValue, StatsBase.TestStat}, ::Real) at /home/buddhilw/.julia/packages/StatsBase/PGTj8/src/statmodels.jl:514
isless(::AbstractGray{T} where T, ::Real) at /home/buddhilw/.julia/packages/ColorTypes/6m8P7/src/operations.jl:31
isless(::ForwardDiff.Dual{Tx, V, N} where {V, N}, ::Integer) where
Tx at /home/buddhilw/.julia/packages/ForwardDiff/UDrkY/src/dual.jl:144
...
Stacktrace:
[1] <(x::Function, y::Int64)
# Base ./operators.jl:279
[2] top-level scope
# REPL[62]:1

There's not a lot of documentation for ImplicitEquations, but something stands out: you're not using the right operators. The package relies on unusual operators to represent math expressions with Julia functions: ≪ (\ll[tab]), ≦ (\leqq[tab]), ⩵ (\Equal[tab]), ≶ (\lessgtr[tab]) or ≷ (\gtrless[tab]), ≧ (\geqq[tab]), ≫ (\leqq[tab]).
So that fix would look like:
using ImplicitEquations, Plots
f(a,b) = sqrt((a+1)^2 + b^2)
plot(f ≪ 1)
Update:
f(a,b) = abs(a + im*b - (-1)) causes a method ambiguity error. f(a, b) = hypot(a+1, b), which is what abs calls, also causes the error. It looks like the issue is that at some point in hypot, OInterval(x::Ointerval) is called, but dispatch could not pick between (::Type{T})(x::T) where T<:Number in boot.jl or OInterval(a) in intervals.jl. Just redefining OInterval(a::Ointerval) = a won't work either because you run into another MethodError for decompose(::OInterval), which is a method intended for processing floats. Looking at the comments in intervals.jl, the dispatch seems like a work in progress.

Related

Understanding Forward.Diff issues

I got an apparently quite common Julia error when trying to use AD with forward.diff. The error messages vary a bit (sometimes matching function name sometimes Float64)
MethodError: no method matching logL_multinom(::Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(logL_multinom), Real}, Real, 7}})
My goal: Transform a probability vector to be unbounded (θ -> y), do some stuff (namely HMC sampling) and transform back to the simplex space whenever the unnormalized posterior (logL_multinom()) is evaluated. DA should be used to overome problems for later, more complex, models than this.
Unfortunately, neither the Julia documentation, not the solutions from other questions helped me figure the particular problem out. Especially, it seems to work when I do the first transformation (y -> z) outside of the function, but the first transformation is a 1-to-1 mapping via logistic and should not cause any harm to differentiation.
Here is an MWE:
using LinearAlgebra
using ForwardDiff
using Base
function logL_multinom(y)
# transform to constrained
K = length(y)+1
k = collect(1:(K-1))
# inverse logit:
z = 1 ./ (1 .+ exp.(-y .- log.(K .- k))) # if this is outside, it works
θ = zeros(eltype(y),K) ; x_cumsum = zeros(eltype(y),K-1)
typeof(θ)
for i in k
x_cumsum[i] = 1-sum(θ)
θ[i] = (x_cumsum[i]) * z[i]
end
θ[K] = x_cumsum[K-1] - θ[K-1]
#log_dens_correction = sum( log(z*(1-z)*x_cumsum) )
dot(colSums, log.(θ))
end
colSums = [835, 52, 1634, 3469, 3053, 2507, 2279, 1115]
y0 = [-0.8904013824298864, -0.8196709647741431, -0.2676845405543302, 0.31688184351556026, -0.870860684394019,0.15187821053559714,0.39888119498547964]
logL_multinom(y0)
∇L = y -> ForwardDiff.gradient(logL_multinom,y)
∇L(y0)
Thanks a lot and especially some further readings/ explanations for the problem are appreciated since I'll be working with it moreoften :D
Edit: I tried to convert the input and any intermediate variable into Real / arrays of these, but nothing helped so far.

How do I evaluate an expression with trignometric functions & also complex numbers in Sagemath?

I wanted to verify if n-th roots of unity are actually the n-th roots of unity?
i.e. if (root)^n = 1
I was trying to use sagemath to do this.
For e.g. for regular expressions sage seems to evaluate stuff
For e.g.
sage: x = var('x')
sage: f(x) = (x+2)^3
sage: f(5)
343
But I am unable to do this
sage: a = var('a')
sage: b = var('b')
sage: f(a, b) = (a + i*b)^3
sage: f(cos((2*pi)/3) , sin((2*pi)/3))
(1/2*I*sqrt(3) - 1/2)^3
How do I make sage raise it to power 3 & evaluate?
A sage expression has several methods to manipulate it, including expanding, factoring and simplifying:
e = f(cos((2*pi)/3) , sin((2*pi)/3))
e.expand()
e.simplify()
e.full_simplify()
e.factor()
You can see the list of all available methods by typing the name of the variable, followed by a dot, followed by a tabulation: e.<tab>.
In your case, it would appear e.full_simplify() should do the trick.
Relevant documentation:
sage doc: Symbolic Expressions;
sage doc: Tutorial for Symbolics and Plotting

how to correctly pass a value to an included function?

I have 2 julia files, alpha.jl and beta.jl.
in alpha.jl, there are 2 functions:
der that returns a derivative using Zygote,
derPlot that plots the function as well as the derivative:
function der(f, x)
y = f'(x)
return y
end
function derPlt(der,z)
plot(f, aspect_ratio=:equal, label="f(x)")
g(f,x₀) = (x -> f(x₀) + f'(x₀)*(x-x₀))
plot!(g(f,x), label="dy",color="magenta")
xlims!(-z,z)
ylims!(-z,z)
end
everything comes out fine when i call these 2 functions in beta.jl, after including the files:
include("alpha.jl")
f(x)=-x^2+2
x = -1.3
derPlt(der(f, x), 6)
However, if i directly enter in a value for the function, the plotted derivative line doesnt update; i.e, if i enter 2.0 instead of passing in some variable named x,
derPlt(der(f, 2.0), 6)
no change is reflected on the plot. New to Julia, trying to understand and fix it.
I think it's because in your derPlt function, you call
plot!(g(f,x),...)
on x instead of the z argument. The problem is then that you define a x = -1.3, the value of which is used inside of derPlt, regardless of what z argument you feed it.
Maybe replace that line with
plot!(g(f,z),...)
and you should be fine.
Seeing as this is a follow up to a question I answered previously I thought I'd have to respond: Benoit is broadly speaking correct, you are running into a scoping issue here, but a few more changes are in order.
Note that your function signature is derPlot(der, z) but then:
You never actually use the der argument in your function body; and
You construct your tangent line as g(f,x₀) = (x -> f(x₀) + f'(x₀)*(x-x₀)) - note that there's no z in there, only an x
Now where does that x come from? In the absence of any x argument being passed to your function, Julia will look for it in the global scope (outside your function). Here, you define x = -1.3, and when you then call derPlt, that's the x that will be used to construct your tangent, irrespective of the z argument you're passing.
Here's a cleaned up and working version:
using Plots, Zygote
function derPlt(f,z)
plot(f, label="f(x)", aspect_ratio = :equal,
xlims = (-5,5), ylims = (-5,5))
g(f,x₀) = (z -> f(x₀) + f'(x₀)*(z-x₀))
plot!(i -> g(f, z)(i), label="dy",color="magenta")
end
f(x)=-x^2+2
derPlt(f, -1.5)
I would encourage you to read the relevant manual section on Scope of Variables to ensure you get an understanding of what's happening in your code - good luck!

plotting a line tangent to a function at a point

Heres a block of code that plots a function over a range, as well as the at a single input :
a = 1.0
f(x::Float64) = -x^2 - a
scatter(f, -3:.1:3)
scatter!([a], [f(a)])
i would like to plot the line, tangent to the point, like so:
Is there a pattern or simple tool for doing so?
That depends on what you mean by "pattern or simple tool" - the easiest way is to just derive the derivative by hand and then plot that as a function:
hand_gradient(x) = -2x
and then add plot!(hand_gradient, 0:0.01:3) to your plot.
Of course that can be a bit tedious with more complicated functions or when you want to plot lots of gradients, so another way would be to utilise Julia's excellent automatic differentiation capabilities. Comparing all the different options is a bit beyond the scope of this answer, but check out https://juliadiff.org/ if you're interested. Here, I will be using the widely used Zygote library:
julia> using Plots, Zygote
julia> a = 1.0;
julia> f(x) = -x^2 - a;
[NB I have slightly amended your f definition to be in line with the plot you posted, which is an inverted parabola]
note that here I am not restricting the type of input argument x to f - this is crucial for automatic differentiation to work, as it is implemented by runnning a different number type (a Dual) through your function. In general, restricting argument types in this way is an anti-pattern in Julia - it does not help performance, but makes your code less interoperable with other parts of the ecosystem, as you can see here if you try to automatically differentiate through f(x::Float64).
Now let's use Zygote to provide gradients for us:
julia> f'
#43 (generic function with 1 method)
as you can see, running f' now returns an anonymous function - this is the derivative of f, as you can verify by evaluating it at a specific point:
julia> f'(2)
-4.0
Now all we need to do is leverage this to construct a function that itself returns a function which traces out the line of the gradient:
julia> gradient_line(f, x₀) = (x -> f(x₀) + f'(x₀)*(x-x₀))
gradient_line (generic function with 1 method)
this function takes in a function f and a point x₀ for which we want to get the tangent, and then returns an anonymous function which returns the value of the tangent at each value of x. Putting this to use:
julia> default(markerstrokecolor = "white", linewidth = 2);
julia> scatter(f, -3:0.1:3, label = "f(x) = -x² - 1", xlabel = "x", ylabel = "f(x)");
julia> scatter!([1], [f(1)], label = "", markersize = 10);
julia> plot!(gradient_line(f, 1), 0:0.1:3, label = "f'(1)", color = 2);
julia> scatter!([-2], [f(-2)], label = "", markersize = 10, color = 3);
julia> plot!(gradient_line(f, -2), -3:0.1:0, label = "f'(-2)", color = 3)
It is overkill for this problem, but you could use the CalculusWithJulia package which wraps up a tangent operator (along with some other conveniences) similar to what is derived in the previous answers:
using CalculusWithJulia # ignore any warnings
using Plots
f(x) = sin(x)
a, b = 0, pi/2
c = pi/4
plot(f, a, b)
plot!(tangent(f,c), a, b)
Well, the tool is called high school math :)
You can simply calculate the slope (m) and intersect (b) of the tanget (mx + b) and then plot it. To determine the former, we need to compute the derivative of the function f in the point a, i.e. f'(a). The simplest possible estimator is the difference quotient (I assume that it would be cheating to just derive the parabola analytically):
m = (f(a+Δ) - f(a))/Δ
Having the slope, our tanget should better go through the point (a, f(a)). Hence we have to choose b accordingly as:
b = f(a) - m*a
Choosing a suitably small value for Δ, e.g. Δ = 0.01 we obtain:
Δ = 0.01
m = (f(a+Δ) - f(a))/Δ
b = f(a) - m*a
scatter(f, -3:.1:3)
scatter!([a], [f(a)])
plot!(x -> m*x + b, 0, 3)
Higher order estimators for the derivative can be found in FiniteDifferences.jl and FiniteDiff.jl for example. Alternatively, you could use automatic differentiation (AD) tools such as ForwardDiff.jl to obtain the local derivative (see Nils answer for an example).

1D integration with multivariable function input

To demonstrate, let's start with a simple multi-variable function f(x,y) = xy^2.
I am trying to find a command that would allow me to numerically integrate f(2, y) = 2y^2 from y = 0 to y = 2. (i.e. the original function is multi-variable, but only one variable remains when actually doing the integration)
I needed to define the function that way as I need to obtain the results using different values of x. (probably going to involve for-loop, but that is another story)
I have tried to walk through Cubature's user guide but apparently did not find anything useful. Maybe I have missed it
Can anyone help?
In such case it is simplest to use an anonymous function wrapper:
using QuadGK
f(x,y) = x*y^2
intf(x) = quadgk(y -> f(x, y), 0, 2)
if the anonymous function would be longer you could write:
intf(x) = quadgk(0, 2) do y
f(x, y)
end
This is an exact equivalent of the latter but do syntax allows you to write longer bodies of an anonymous function.
Now you can write e.g.:
julia> intf(1)
(2.6666666666666665, 4.440892098500626e-16)
julia> intf(2)
(5.333333333333333, 8.881784197001252e-16)
julia> intf(3)
(8.0, 0.0)

Resources