LoginSignup
9
5

More than 3 years have passed since last update.

JuliaでJuliaのコードをインプットとする

Last updated at Posted at 2020-12-05

Juliaで何らかの計算を行いたい場合、インプットをファイルとして与えたいことがありますよね。
例えば、

L = 3
g = true

のような。テキストデータとしてこのインプットを保存して読み込むという手もありますし、その他のファイルフォーマットを使うこともあるでしょう。

今回は、

input.jl
L = (3,2)
name = "dog"
namedict = Dict()
namedict["dt"] = 0.1
matrix = rand(Float64,2,2)
f(x) = 2x
beta = f(2.4)

をインプットファイルにして変数を読み込む方法について述べます。
これはJuliaのコードそのものですね。つまり、このようにインプットファイルで値を定義したり値を計算したりして、その結果をインプットファイルに入れる、という方法についてです。
インプットファイルに関数を入れられるので、

testinput.jl
x = 3
y = x+4
z = cos(x)*exp(z)

みたいなインプットファイルが可能になります。

コード

以下のコードがそれを実現します。

module Loadfromfile
    export loadfromfile

    function loadfromfile(filename)
        include(pwd()*"/"*filename)
        return L,name,beta,namedict,matrix
    end
end

非常に簡単なコードですね。このコードと

test.jl
module Testcode
    using ..Loadfromfile    
    function test(filename)
        variables = loadfromfile(filename)
        for v in variables
            display(v)
            println("\t")
        end
    end
end

using .Testcode
Testcode.test(ARGS[1])

を用いれば、

julia test.jl input.jl

を実行すると、

(3, 2)  
"dog"   
4.8 
Dict{Any,Any} with 1 entry:
  "dt" => 0.1   
2×2 Array{Float64,2}:
 0.426489   0.860886
 0.0233972  0.273282

となりますので、ちゃんと値を定義できていることがわかります。

コードの説明

以下に説明を行います。

ポイントはinclude文です。
include文、元々はModuleを複数ファイルに分割したりする時に使います。ですので、Moduleのすぐ下にincludeを置くことが多いですよね。
このようにfunctionの中に置くことも可能です。
しかし、注意点があります。includeで呼ばれたコードの変数のスコープはどうなっているのでしょうか?
以下のコードを実行してみましょう。

module Loadfromfile
    export loadfromfile

    function loadfromfile(filename)
        include(pwd()*"/"*filename)
    end
end

module Testcode
    using ..Loadfromfile

    function test2(filename)
        loadfromfile(filename)
        println(Loadfromfile.beta)
    end
end

using .Testcode
Testcode.test2(ARGS[1])

これを実行すると、

4.8

と出力されます。Loadfromfile.betaの値が出ています。
しかし、include文はfunction loadfromfile(filename)の中でよびましたので、何か挙動が違うようです。
例えば、

module Loadfromfile
    export loadfromfile

    function loadfromfile(filename)
        beta = 100
    end
end

module Testcode
    using ..Loadfromfile

    function test2(filename)
        loadfromfile(filename)
        println(Loadfromfile.beta)
    end
end

using .Testcode
Testcode.test2(ARGS[1])

を実行すると、

ERROR: LoadError: UndefVarError: beta not defined

となります。これは当然です。betaはfunction loadfromfile(filename)の中で定義していますので、module Loadfromfileの中には定義されていません。
一方、includeを使った場合はbetaを呼び出すことができています。
つまり、module内のどこでinclude文を呼んだとしても、module内の最上位変数(module内でどこでも使えるグローバル変数)として定義されているということです。
この挙動を知らなかったため大分試行錯誤することになりました。

実用的な例

実用的な例としては、何が返ってくるかわかるように初期値を指定する

module Loadfromfile
    export loadfromfile

    L = (5,3)
    name = "test"
    beta = 0.8
    namedict = Dict()
    matrix = zeros(Float64,3,3)

    function loadfromfile(filename)
        include(pwd()*"/"*filename)
        return L,name,beta,namedict,matrix
    end
end

のが良いかもしれません。
これの利点は

input2.jl
L = (3,2)
name = "dog"
namedict["dt"] = 0.1
matrix[1,2] = 4
function coscossinsin(x,y)
    cos(x)*cos(y) + sin(x)*sin(y)
end
beta =  coscossinsin(matrix[1,2],L[2])

のようにインプットを定義できる点です。インプットでは辞書型の変数や行列の型を定義するのではなく、値を入れる形にしています。
これにより、インプットファイルを記入する側は変数の定義に気を取られずに済みます。

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5