Juliaメモ

開発に便利なpackage
AllocCheck.jl
ArgCheck.jl
BenchmarkTools.jl
Chairmarks.jl
ExplicitImports.jl
JuliaFormatter.jl
OhMyREPL.jl
Pluto.jl
PkgDependency.jl
PkgTemplates.jl
PProf.jl
ProfileView.jl
Reexport.jl
Revise.jl
TimerOutputs.jl
debug
テスト関係
Aqua.jl
JET.jl
ReferenceTests.jl
ReTest.jl
ReTestItems.jl
TestEnv.jl
TestSetExtensions.jl
TestReadme.jl
標準library
@test
-
@profile
https://docs.julialang.org/en/v1/manual/profile/
他言語support
-
CxxWrap.jl
: C++ -
PythonCall.jl
: Python -
jlrs
: Rust


HPC関連
- PartitionedArrays.jl: 分散疎行列

julia> Real <: Complex
false

julia> AbstractFloat <: Real
true

julia> Char <: String
false
julia> SubString <: String
false
julia> Char <: AbstractString
false
julia> SubString <: AbstractString
true
julia> Char <: AbstractChar
true
julia> String <: AbstractString
true

julia> [1, 1] == [1; 1]
true
julia> [1, 1] == [1 1]
false

julia> Union{Int, Nothing} == Union{Nothing, Int}
true

2進数⇔10進数
- 2進数は
a=0b11111
のように0b
prefixを書く - 16進数は
0x
prefix - 10→2: string(77,base=2) # "1001101"
- 2→10: string(0b1001101) # "77"
https://qiita.com/mametank/items/fa265ed3aa40825ea8e2

Juliaup
以下[channel]
は実際のchannelの名前で置換.
-
julia +[channel]
: juliaの起動(例:julia +release
) -
juliaup add [channel]
: channelの追加 -
juliaup rm [channel]
: channelの削除(juliaup remove
) -
juliaup default [channel]
: default channelの切り替え -
juliaup st
: installされたchannel一覧 (juliaup status
) -
juliaup ls
: install可能なchannel一覧(juliaup list
) -
juliaup up
: channelの更新(juliaup update
)
補足など
- juliaupの更新
- Homebrew以外:
juliaup self update
- Homebrew:
brew upgrade juliaup
- Homebrew以外:
- semantic versioning (x.y.z)以外のchannel
-
release
: 最新版, juliaupを入れた時点で入るdefault -
lts
: 安定版 -
alpha
,beta
,rc
: 開発版
-
あまり使わなさそう
-
juliaup link [channel] [julia_binary]
:既存の[julia_binary]を[channel]として登録(juliaupでinstallしていないchannelを作成可能)

user定義structに四則演算などBase
に定義されている演算子(method)を追加する場合はimport Base.+
のようにimportが必要

函数objectは::Function
でannotateできる

他所のPackageにmultiple dispatchを追加
using Hoge
Hoge.some_function(mystruct::MyStruct) = some_function(...)
- 自分が定義した
Mystruct
に対してHoge
が定義していたsome_function
にsome_function(mystruct::MyStruct)
を追加したい場合,Hoge.some_function(mystruct::MyStruct)
を定義しないといけない. -
some_function(mystruct::MyStruct) = some_function(...)
とした場合,Hoge
に元々定義されていたsome_function
のmultiple dispatchが消えてしまう.

Simulation directoryとsource code directoryの分離
/my/source/code/directory
にmain.jl
と依存先のincludes.jl
があるとして,/my/source/code/directory
とは別の場所で計算を実行したいとする.
そのまま絶対pathでmain.jl
を実行すると依存関係が解決できないので以下のように--project
で依存先を教えてあげる必要がある.
PROJ_DIR=/my/source/code/directory; julia --project=$PROJ_DIR $PROJ_DIR/main.jl

one liner
julia --eval "println(\"hello\")"
あるいは
julia -e "println(\"hello\")"

foldl
とfoldr
について
tensor_product(x::Vector{Matrix{T}}) where T = foldl(kron, x) :: Matrix{T}
-
kron(kron(kron(x[1], x[2])), x[3]), x[4])
と等価(x
の要素数を4
とした) -
foldr
を使うとkron(x[1], kron(x[2], kron(x[3], x[4])))
と等価になる
(kron
はKronecker積.要using LinearAlgebra
)

Avoid fields with abstract type
構造体を以下のように書くとパフォーマンスに良い
struct MyType{T<:AbstractFloat}
a::T
end
struct MySimpleContainer{A<:AbstractVector}
a::A
end

VScodeのJupyter拡張機能でpackageの環境を使う方法
- Jupyter notebookのkernel選択で分からなくなったのでメモ.
- Jupyter kernelは使いたいJuliaのversionのみ指定すれば良い.
- 最初(Julia環境を有効化したいタイミング)のセルで以下をJupyter notebookから実行すれば良い.
-
activate
する場所はpackageのdirectoryを作成してProject.toml
がある場所を絶対pathかnotebookがある場所からの相対pathで指定する.
using Pkg
Pkg.activate("../")
Pkg.instantiate()

package名の一意性に関する調査
package作成の際にroot dirの名前,Project.toml
のname
entry,src
以下のMyPackage.jl
の名前,moduleの名前が不一致のときどうなるのか調べ,何が一致しなければならないのかを確認する.
確認用のPackage作成
julia REPLを起動して以下を実行
# まだaddしていなければ以下を実行
# ] add PkgTemplates
using PkgTemplates
template = Template(; dir=".")
template("MyPackage.jl")
これでREPLを起動したdirectoryにMyPackage.jl
directoryが作成される.
MyPackage.jl
directoryにProject.tomlが作成され,
name = "MyPackage"
と記載されていることが確認できる.
またsrc
directoryにはMyPackage.jl
というjulia fileが作成されていることも確認できる.
MyPackage.jl
の中身は
module MyPackage
# Write your package code here.
end
となっている.
作成されたpackageの動作確認
REPLをMyPackage
directoryで起動し,以下を実行する
] activate .
using MyPackage
using MyPackage
から特にerror出力なく端末が返ってくることが分かる.
なお,] activate .
の後はpkg modeを抜けるためにbackspaceを押す必要があることに注意.
変更可能箇所の列挙
以下Package名をMyPackage.jl
とする.
- Packageのdirectory名
-
MyPackage.jl
下Project.toml
のname
entry -
MyPackage.jl/src
下MyPackage.jl
のfile名 -
MyPackage.jl/src
下MyPackage.jl
内のmodule名
packageのdirectory名の変更
まず一番無害そうなpackageのdirectory名を変更してみる
mv MyPackage.jl NewMyPackage.jl
特に問題なく動作する.
以下3パターンを検証する.
Project.toml のname
|
実行file名 | module名 |
---|---|---|
NewMyPackage |
MyPackage.jl |
MyPackage |
MyPackage |
NewMyPackage.jl |
MyPackage |
MyPackage |
MyPackage.jl |
NewMyPackage |
Project.toml
のname
entryの変更
以下のようにProject.toml
を修正する.
@@ -1,4 +1,4 @@
-name = "MyPackage"
+name = "NewMyPackage"
状況は以下のようになる.
Project.toml のname
|
実行file名 | module名 |
---|---|---|
NewMyPackage |
MyPackage.jl |
MyPackage |
以下のように動かなくなる.
(@v1.10) pkg> activate .
julia> using MyPackage
ERROR: ArgumentError: Package MyPackage not found in current path.
- Run `import Pkg; Pkg.add("MyPackage")` to install the MyPackage package.
julia> using NewMyPackage
ERROR: ArgumentError: Package NewMyPackage [0fa5efea-465b-4ecc-8393-0dad7f99f1d9] is required but does not seem to be installed:
- Run `Pkg.instantiate()` to install all recorded dependencies.
src/MyPackage.jl
のfile名の変更
続いて,Project.toml
は元に戻して,以下の修正を行う.
mv MyPackage.jl NewMyPackage.jl
状況は以下のようになる.
Project.toml のname
|
実行file名 | module名 |
---|---|---|
MyPackage |
NewMyPackage.jl |
MyPackage |
以下のように動かなくなる.
(@v1.10) pkg> activate .
julia> using MyPackage
ERROR: ArgumentError: Package MyPackage [0fa5efea-465b-4ecc-8393-0dad7f99f1d9] is required but does not seem to be installed:
- Run `Pkg.instantiate()` to install all recorded dependencies.
julia> using NewMyPackage
ERROR: ArgumentError: Package NewMyPackage not found in current path.
- Run `import Pkg; Pkg.add("NewMyPackage")` to install the NewMyPackage package.
module名の変更
実行file名を元に戻した後,以下のように修正を行う.
@@ -1,4 +1,4 @@
-module MyPackage
+module NewMyPackage
状況は以下のようになる.
Project.toml のname
|
実行file名 | module名 |
---|---|---|
MyPackage |
MyPackage.jl |
NewMyPackage |
以下のように動かなくなる.
(@v1.10) pkg> activate .
julia> using MyPackage
Precompiling MyPackage
1 dependency successfully precompiled in 5 seconds
[ Info: Precompiling MyPackage [0fa5efea-465b-4ecc-8393-0dad7f99f1d9]
┌ Warning: The call to compilecache failed to create a usable precompiled cache file for MyPackage [0fa5efea-465b-4ecc-8393-0dad7f99f1d9]
│ exception = Required dependency MyPackage [0fa5efea-465b-4ecc-8393-0dad7f99f1d9] failed to load from a cache file.
└ @ Base loading.jl:1992
┌ Warning: Replacing module `NewMyPackage`
└ @ Base loading.jl:1855
ERROR: package `MyPackage` did not define the expected module `MyPackage`, check for typos in package module name
julia> using NewMyPackage
ERROR: ArgumentError: Package NewMyPackage not found in current path.
- Run `import Pkg; Pkg.add("NewMyPackage")` to install the NewMyPackage package.
まとめ
Project.toml
のname
と実行file名とmodule名は揃えよう.

template Packageの生成
t = Template(user="USERNAME",dir=".";plugins=[ProjectFile(; version=v"0.1.0")])
毎回忘れる
- 自分の場合なぜか毎回GitHubのusernameを明示的に入れないとキレられるので入れてる
USERNAME
は自分のuser名 -
dir="."
はcurrent pathでpackage生成する用.ないと$HOME/.julia
下にdir作る


MyPackage.jl
を作成していて、Hoge.jl
の依存をextensionで入れたい場合、上記のやり方にしたがってMyPackageHogeExt.jl
を作成するとusing Hoge
をした場合にのみ MyPackageHogeExt.jl
の中身がロードされる

using Hoge
で名前空間をちゃんぽんさせていたのを明示的にusing
したい場合,一旦using Hoge: Hoge
にしてerrorにして使ってる名前を吐かせると便利
こうするとHoge
というmodule名しかusingされてない

複素数型の実部と虚部はx.re
とx.im
の形でアクセス可能だが、実数型の場合は各fieldが存在しないのでエラーになる。
複素数型も実数型も両方来る可能性がある場所はreal(x)
とimag(x)
でアクセスした方がよい。

スパコンなどユーザーが利用できるリソースが制限されている環境でパッケージをadd
しようとするとクラッシュする場合、export JULIA_NUM_PRECOMPILE_TASKS=1
のようにJULIA_NUM_PRECOMPILE_TASKS
を小さな値にするとクラッシュしなくなる可能性がある。

DifferentialEquations.jl
特にOrdinaryDiffEqLinear
)。
-
: 状態ベクトルu(t) -
: 独立変数t -
: 問題を定義する行列A(u,p,t) -
: パラメーターパック。p 、u 以外の依存変数を詰めるのに使うt
そのためにSciMLOperators.jlのMatrixOperator
を用いる[1]。
以下のコード例を示す際に共通の変数を導入する
u0 = [1.0; -1.0] # 初期状態。値やサイズは問題などに合わせて変わる
tspan = (1.0, 6.0) # 問題を解く独立変数の区間。こちらもユーザーの要件で変わる
自励的な場合
MatrixOperator
にターゲット行列を渡すだけで良い。
A = MatrixOperator([0.0 1.0; 1.0 0.0])
prob = ODEProblem(A, u0, tspan)
sol = solve(prob, LinearExponential())
自励的な場合は行列指数函数を計算すれば解けるのでソルバーはLinearExponential
非自励な場合
MatrixOperator
に渡す行列には時間や状態依存性を定義できない。そのためにMatrixOperator
のキーワード引数であるupdate_func!
を定義して渡す
function update_func!(A, u, p, t)
A[1, 1] = cos(t)
A[2, 1] = sin(t)
A[1, 2] = -sin(t)
A[2, 2] = cos(t)
end
A = MatrixOperator(ones(2, 2), update_func! = update_func!)
prob = ODEProblem(A, u0, tspan)
sol = solve(prob, MagnusGL6(), dt = 1 / 10)
- 状態
u
に依存しない場合、MagnusGL6
などのMagnus展開法を用いたソルバーが利用できる. -
dt
はt
の刻み幅
パラメーターパックp
を使う場合は
function update_func!(A, u, p, t)
A[1, 1] = p.a*cos(t)
A[2, 1] = p.a*sin(t)
A[1, 2] = -p.a*sin(t)
A[2, 2] = p.a*cos(t)
end
p = (; a = 1)# NamedTuple。この場合Structでも良い
という感じで定義して
prob = ODEProblem(A, u0, tspan, p)
ODEProblem
の第4引数に定義したp
を渡せば良い。
その他注意点
-
が複素数を含む場合(Schrödinger方程式など)、A(u, p, t) A
の時間非依存部分を指定するMatrixOperator
の第1引数と、ODEProblem
の第2引数の初期状態u0
の要素型を複素数型にしておかないと複素数型から浮動小数点数型の変換が発生しInexactError
で止まるので注意 -
MatrixOperator
の第1引数は 初期行列として使用される。A(u,p,t) update_func!
で触ってない要素はそのまま使用されるので注意。例えば
function update_func!(A, u, p, t)
A[2, 1] = sin(t)
A[1, 2] = -sin(t)
end
とした場合、対角要素MatrixOperator
の第1引数に渡されたものの要素が使われる。
- 公式ドキュメントではout-of-placeの
update_func
を使うように書いてあるが、これは正しくなく時間依存しない初期行列がソルバーにそのまま渡されるので使用してはいけない。(doc v7.15.0で確認)関連issue
-
ドキュメントでは明示的に
using SciMLOperators
してあるがDifferentialEquations.jlなどが再exportしているので必要なさそう(SciMLOperators←SciMLBase←DiffEqBase←OrdinaryDiffEq) ↩︎

(immutable) structのfieldのmutable structのfieldはmutable

get(collection, key, default)
collection
からkey
指定したアイテムを取得。なければdefault
が返ってくる。

Distributed.jl
-
julia -p n
あるいはUsing Distributed; addprocs(n)
するとDistributed.nprocs
はn+1
になる