Juliaパッケージの関数やフィールドの探索の仕方

Juliaは貪欲な言語で、C言語並のスピードをモダンな記法で書いていける点が魅力的だ。一方でJuliaコミュニティの本当に良くない点は、開発や状況の進展が早すぎて、ドキュメンテーションが追いついてないことだ。往々にして必要な関数や要素の取り出し方が全く分からないことがあり、GitHubのソースコードまで辿ったり、issuesを漁ったり、discourseを見て回ったりする。ものすごいストレスフル。MCMCで有名なTuring.jlなんて古い公式サイトのドメインの管理権を失いサイトを更新出来なくなる事件が発生したりしている。(Most tutorial links on website are broken #2041)

さて、そんなわけで僕なりのコード探索の方法を紹介していく。

Pythonだったら?

まず、Pythonだったら話は簡単ということを少しだけ触れておく。PythonはすべてのObjectはClassとみなせる状態なので、基本的にパッケージでやりたいことがあったら、入り口の関数、そして返されるクラスをいじる方法はクラスのメソッドとして実装されることが多い。なのでdir関数を用いてattributesやメソッドを見ていけば問題は解決することが多い。使えそうなメソッドに対しても、ドキュメントの説明を確認していける。

Juliaは関数型言語

Juliaは関数型言語でMultiple-dispatchが特徴だ。そして、関数型の宿命か、ドキュメントだよりになりがちだ。どのStructをどの関数が取るかの繋ぎ合わせが薄くなりがちだからだ。これから紹介する方法も、網羅的な解決ではなく、偶に早く解決できる方法だとみなしてほしい。

以下ではOptim.jlのFittingした後にfitした値と、そのときの最小値を取り出したいとする。公式ドキュメントにある通り以下のコードにより達成出来る。

using Optim
f(x) = (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2
x0 = [0.0, 0.0]
res = optimize(f, x0)

Optim.minimizer(res) |> println
Optim.minimum(res) |> println

ドキュメントではすぐ書いてあるが、この記事ではminimzer, minimumをドキュメントからではなくコードから探し出せるか試してみることとする。

Structの構造体から直接取り出す

今回の場合は、struct自体に値がセットしてあるため、structの構造を除きフィールド名を直接取得しにいく方法が取れる。

structの名前を知りたければ

 fieldnames(res |> typeof) 

によってres (Optim.MultivariateOptimizationResultsというstruct)のフィールド名を取得できる。それぞれの実際の値と共に知りたい場合は、次を回す。

 res |> dump 
#> ~~~~~ #> minimizer: Array{Float64}((2,)) [0.9999634355313174, 0.9999315506115275] #> minimum: Float64 3.5255270584829996e-9 #> ~~~~

個人的には、fieldnamesよりもdumpを多用する。今回は構造体自体に値が保有されていることが確認できるのでgetfield で直接、値を取得することができる。

getfield(res, :minimizer)
getfield(res, :minimum)

Moduleでexportされている関数から

Moduleにexportされている関数を一覧にして、それらしい名前を探しに行く方法が挙げられる。

[println(i) for i in names(Optim; all=true)] 

ただ、デメリットとしては、関数がexportされていない可能性は十分にあるので、ここを目を皿にして探しても見つからない可能性は大いにある。実際、Optim.jlの場合、minimum関数はあるが、minmizer関数は出力されていない。

構造体を指定している関数を見つけ出す

関数の変数宣言の部分で型を指定している場合、methodswith で興味のあるstructの型を引数にとる関数を引き出すことが出来る。

 methodswith(res |> typeof, supertypes=true)
#> append!(a::Optim.MultivariateOptimizationResults, b::Optim.MultivariateOptimizationResults) in Optim at C:\Users\aflub\.julia\packages\Optim\V8ZEC\src\types.jl:294
#> maximum(r::Union{Optim.MultivariateOptimizationResults, Optim.UnivariateOptimizationResults}) in Optim at C:\Users\aflub\.julia\packages\Optim\V8ZEC\src\maximize.jl:48
#> minimum(r::Optim.OptimizationResults) in Optim at C:\Users\aflub\.julia\packages\Optim\V8ZEC\src\api.jl:3
#> show(io::IO, r::Optim.MultivariateOptimizationResults) in Optim at C:\Users\aflub\.julia\packages\Optim\V8ZEC\src\types.jl:235
#> summary(r::Optim.OptimizationResults) in Optim at C:\Users\aflub\.julia\packages\Optim\V8ZEC\src\api.jl:1

———-雑感(`・ω・´)———-

こ、これでドキュメンテーションが雑なことが多いJulia言語のパッケージを漁ることが出来る。

他の方法としては、

・欲しい関数が使われていそうな、ソースコードの該当部分を探しにいく。
・GitHubのIssuesを検索する。
・JuliaのDiscourseのプラットフォームで質問する。

が挙げられる。

コメント

タイトルとURLをコピーしました