Функция построения графика относительно аргумента ключевого слова приводит к ошибке в Юлии - PullRequest
2 голосов
/ 30 сентября 2019

У меня есть функция, которая включает в себя множество интегралов и сложных вычислений, таких как:

using HCubature
function func(v, x0, y0; rad=1.)

    L = hcubature(r->r[1]*v(x0+r[1]*cos(r[2]), y0+r[1]*sin(r[2])), [0., π/2], [rad, π])[1]
    R = hcubature(r->r[1]*v(x0+r[1]*cos(r[2]), y0+r[1]*sin(r[2])), [0., 0], [rad, π/2])[1]

    return L, R

end

Аргумент v является самой функцией. Когда я пытаюсь построить функцию относительно аргумента ключевого слова rad, я получаю сообщения об ошибках следующим образом:

x0_, y0_ = 0, 0

rad_ = 0.:0.1:9.

func_array_L = [func(v, x0_, y0_; rad = radius)[1] for radius in rad_]
func_array_R = [func(v, x0_, y0_; rad = radius)[2] for radius in rad_]

plot(rad_, func_array_L)
plot!(rad_, func_array_R)

Сообщение об ошибке содержит очень длинное сообщение об ошибке: Internal error: encountered unexpected error in runtime:, за которым следуетдлинный список каталогов, а затем все сводится к следующему:

MethodError: no method matching string(::Expr)
The applicable method may be too new: running in world age 3820, while current world is 26290.
Closest candidates are:
  string(::Any...) at strings/io.jl:168 (method too new to be called from this world context.)
  string(!Matched::String) at strings/substring.jl:152 (method too new to be called from this world context.)
  string(!Matched::SubString{String}) at strings/substring.jl:153 (method too new to be called from this world context.)
  ...

Я пробовал и другие методы, такие как объявление другой функции с rad в качестве единственного аргумента и т. д., но ни один из них не работал. Как решить проблему?

1 Ответ

2 голосов
/ 30 сентября 2019

Действительно, сообщение об ошибке странно, но причина проста. Вы не определили функцию v. Сначала вы должны определить его, а затем все должно работать как положено.

Кроме того, обратите внимание, что в using HCubature указан неправильный регистр (обратите внимание, что u должно быть в нижнем регистре). Также для того, чтобы прорисовка работала, вы должны сначала импортировать пакет прорисовки, например, using Plots.

РЕДАКТИРОВАТЬ

Основной код, который воспроизводит вашу проблему:

julia> using HCubature

julia> function func(v, x0, y0; rad=1.)
           L = hcubature(r->r[1]*v(x0+r[1]*cos(r[2]), y0+r[1]*sin(r[2])), [0., π/2], [rad, π])[1]
           R = hcubature(r->r[1]*v(x0+r[1]*cos(r[2]), y0+r[1]*sin(r[2])), [0., 0], [rad, π/2])[1]
           return L, R
       end
func (generic function with 1 method)

julia> v = (x,y) -> x
#27 (generic function with 1 method)

julia> x0_, y0_ = 0, 0
(0, 0)

julia> rad_ = 0.:0.1:9.
0.0:0.1:9.0

julia> func_array_L = [func(v, x0_, y0_; rad = radius)[1] for radius in rad_]
Internal error: encountered unexpected error in runtime:
MethodError(f=typeof(Base.string)(), args=(Expr(:<:, :t, :r),), world=0x0000000000000eec)

Это похоже на ошибку. Я сообщил об этом здесь .

Обходной путь

Теперь - способ решить эту проблему - сделать тип v стабильным. Есть три примера способов сделать это.

Вариант 1: определите его как const:

const v1 = v

и используйте понимание с переданным v1 вместо v.

Вариант 2: обернуть его в let блок:

func_array_L = let v=v
    [func(v, x0_, y0_; rad = radius)[1] for radius in rad_]
end

Вариант 3: определить функцию с именем, используя v:

v2(x,y) = v(x,y)

и использоватьпередано v2 вместо v.

В качестве альтернативы вы также можете сделать x0_ или y0_ постоянного типа (достаточно исправить одно из них), чтобы все работало,Например,

func_array_L = [func(v, 1, y0_; rad = radius) for radius in rad_]

работает должным образом.

Дополнительные примечания

У вас есть похожая проблема, если вы используете map вместо понимания, если в карте вы используетеанонимная функция:

map(radius -> func(v, x0_, y0_; rad = radius)[1], rad_)

, а также обычная функция с именем вызывает ту же ошибку:

v3(radius) = func(v, x0_, y0_; rad = radius)[1]
map(v3, rad_)

, но она начинает работать, если вы создаете внутреннюю функцию, которая вводится втаблица методов:

v3(radius) = (tmp(x...) = v(x...); func(tmp, x0_, y0_; rad = radius)[1])

и теперь map(v3, rad_) работает как положено.

...