sesodesa
sesodesa

Reputation: 1603

Problem with combining ForwardDiff and PyPlot in Julia 1.0.5

In Julia 1.0.5, I have a function f(x::Vector{<:Real}), defined as

f(x::Vector{<:Real}) = (x[1] - 2)^2 + ( x[2] - 1 )^2

The signature is like this, because I would like to use it with the ForwardDiff package, and it works with it just fine. I give the function to ForwardDiff.gradient, and everything works like a charm.

However, I would also like to do some visualizations with PyPlot, using this same function f. Namely, I would like to draw its contour with contourf. For this purpose, I have constructed two vectors X::Vector{<:Real} and Y::Vector{<:Real}, and would like to call the same function f with them to produce the contour.

However, making the call f.([X, Y]) is not broadcasting the vectors as I would like, as I get the error

LoadError: MethodError: no method matching (::getfield(Main, Symbol("#f#1044")))(::Int64)
Closest candidates are:
  f(!Matched::Array{#s25,1} where #s25<:Real)

This of course prevents me from using the contourf function, as it needs the values of f on a 2D-grid.

Do I need to define an entirely different f(x::Vector{<:Real}, y::Vector{<:Real}) to be able to plot the contour as I would like, or is there an alternative where I can avoid this?

Upvotes: 1

Views: 68

Answers (1)

longemen3000
longemen3000

Reputation: 1313

this problem can be resolved by the power of multiple dispatch:

f(x::Vector{<:Real}) = (x[1] - 2)^2 + ( x[2] - 1 )^2
f(x::Real,y::Real) = f([x,y])
nx = 10
ny = 20
X = rand(nx) #mesh of x points
Y = rand(ny) #mesh of y points
Z = f.(transpose(X),Y) #nx x ny matrix

for the two argument gradient:

two_point_gradient(f,x,y) = ForwardDiff.gradient(f,[x,y])
G = two_point_gradient.(f,transpose(X),Y) #returns a vector of gradients, where G[i..] = gradient(f,X[i..],Y[i...])

Upvotes: 2

Related Questions