第1回:▼ 簡単なプロットを描く
■ 対話形式で使う
本文では,対話形式で,Julia を利用する.
Juliaをコマンドラインから利用している場合は, プロンプト julia>
が印字され,利用者の入力を待っている.
命令を打ち込み,ENTER
キーを押すと, その命令を計算(評価)した結果が印字される.
julia> 1
1
上の例では,1
という文字の並びから, 1
という数を内部で作成し, それを計算の結果として印字したのである.
計算機側から見ると, 利用者の入力を読み込み(Read), 入力された命令を評価し(Eval, Evaluate), その結果を印字する(Print)ことを,繰り返す(Loop). この4つの頭文字をとって, 対話型利用のことを REPL とも呼ぶ.
evaluate の訳として「評価する」をあてる. 「value を出すこと」すなわち,結果を得ることを意味する.
Jupyter notebookを用いる場合には, Code cellが表示されている. ここに命令を打ち込み,SHIFT
+ ENTER
キーを押すと, その命令を評価した結果が出力される.
REPLから抜け出るには関数 exit()
を用いる.
julia> exit()
■ 電卓として使う
数と数との加減乗除をしてみよう.
加算には +
, 減算には -
の文字を使う. 乗算には *
(アスタリスク asterisk と読む), 除算には /
(スラッシュ slash と読む)の文字を用いる.(なお %
は残余を表す→ ■ 残余 rem
と整商 div
)
julia> 1 + 2
3
julia> 3 * 4
12
数式と同じように,乗算と除算は,加算・減算に優先する. 計算の順序を変えるには,括弧 (
と )
との組を用いる
julia> 2 + 3 * 4
14
julia> (2 + 3) * 4
20
除算の結果は,小数となる.
julia> 2 / 2
1.0
julia> 1 / 3
0.3333333333333333
julia> 5 / 2
2.5
■ 変数に値を代入する
値には,名前(名札,ラベル)をつけることができる. この名前を変数(variable)といい,名前をつける操作を「値を変数に代入する(assign)」という. 変数には,色々な種類(「型」)の値を代入できる.
変数を評価すると,変数の値となる.
julia> # 変数 x に 値 2 を代入する x = 2 # 変数 x の値を用いる
2
julia> x + 1 # 変数 x に 別の値 3 を再代入する
3
julia> x = 3
3
#
はコメントである. #
から行末までの文字は,すべて無視される.
■ 変数名の規則
Allowed Variable Names (section)
変数の名前(変数名)は,以下のようにつける.
変数名の最初の文字は, 半角のアルファベット( a
から z
まで,A
から Z
まで), または,下線(アンダースコア _
)のいずれかでなければならない. 変数の2文字目以降は,さらに,半角の数字( 0
から 9
), または,半角の感嘆符 !
を含めることができる.
半角文字とは「かな漢字変換機能」を用いずに, キーボードから打ち込める文字と考えてよい.
変数名には,漢字やギリシャ文字などを使うことができるが, ここでは説明を省略する.
Stylistic Conventions (section)
今後出現する,定数,型,関数,マクロ,モジュール,パッケージの名前も,変数名の約束と同じである. ただし,慣習として,以下のように使い分ける.
- 変数名は小文字で始める.
- 型,モジュール,パッケージの名前は大文字で始める.
- 関数やマクロの名前は小文字で始める.下線(アンダースコア
_
)は用いない.
■ ベクトル
角括弧 [
と ]
との間に,半角文字のカンマ ,
で区切って 数を並べたものを,(数の)ベクトルという.
ベクトルは,縦に印字される(列ベクトル,column vector).
julia> [1, 3, 2]
3-element Vector{Int64}: 1 3 2
変数に,ベクトルを代入しよう.
julia> xs = [1, 2, 2, 1]
4-element Vector{Int64}: 1 2 2 1
julia> ys = [1, 1, 3, 1]
4-element Vector{Int64}: 1 1 3 1
本文の筆者は,(ベクトルなど)複数の値を内部に含むデータに対する変数の名前を「英語の複数形の名詞」とすることが多い(多くの場合,末尾を s
で終える).そのデータの各要素を表す変数の名前を単数形とする.(大文字は定数などを表す約束だから)大文字と小文字で,ベクトルなどとその要素を区別することは避けたほうがよい.
▼ 三角形を描く
「パッケージ」とは, 関連する関数,定数,変数などをまとめたものである.
Plots
パッケージは, プロットを描くためのパッケージの一つである.
命令 using <<パッケージ名>>
で,パッケージを読み込む.
Plots
パッケージは, プロットを描くための様々な関数を含んでいる.
関数 plot
はプロットを描く関数である.
単に plot()
として実行すると,新しいプロット枠を描く.
using Plots
#gr() #pythonplot()
plot()
データ系列(data series)を関数 plot
に渡して,プロットを描こう.
関数 plot(xs,ys)
の形で呼び出すと, ベクトル xs
, ys
から一つづつ数を取り出し. それらを各々 $x$ 座標,$y$ 座標とする点を順番に線で結ぶ.
# Plots パッケージの読み込み
using Plots
#gr() #pythonplot()
xs = [1, 2, 2, 1]
ys = [1, 1, 3, 1]
# 新しいプロットを作成する
plot(xs, ys)
▲ 練習
xs
や ys
の値を変えて,別の図形を表示してみよ.
xs
と ys
の要素の「数」が等しくない場合は,どうなるか? 試してみよ.
■ ベクトルをスカラーで乗除する
- ベクトル
v
- スカラー
c
演算 v * c
は, ベクトル r
にスカラー c
を乗じたベクトルである. すなわち, v * c
の各要素は,v
の各要素に c
を乗じた積である.
julia> xs * 2
4-element Vector{Int64}: 2 4 4 2
演算 c * v
も,同じ結果を与える.
julia> # 続けて 2 * xs
4-element Vector{Int64}: 2 4 4 2
v / c
は, ベクトル r
をスカラー c
で除したベクトルである. すなわち, v / c
の各要素は,v
の各要素を c
で除した商である.
julia> xs / 2
4-element Vector{Float64}: 0.5 1.0 1.0 0.5
先に描いた三角形を拡大してみよう.
関数 plot!(xs,ys)
の形で呼び出すと, 直近で描かれたプロットに対して, ベクトル xs
, ys
から一つづつ数を取り出し. それらを各々 $x$ 座標,$y$ 座標とする点を線で結ぶ.
すなわち,関数 plot(xs,ys)
と同じ動作であるが, 直近に描かれたプロットに追加する.
# Plots パッケージの読み込み
using Plots
#gr() #pythonplot()
xs = [1, 2, 2, 1]
ys = [1, 1, 3, 1]
# 新しいプロットを作成する
plot(xs, ys)
# それぞれ 2 倍する
xs2 = 2*xs
ys2 = 2*ys
# 直近のプロットにデータ系列を追加する
plot!(xs2, ys2)
Julia では,渡された引数の値を変える関数の名前の末尾に感嘆符 !
をつける習慣がある.
■ ベクトルをスカラーで加減する
- ベクトル
v
- スカラー
c
演算 v .+ c
は, ベクトル v
にスカラー c
を加えたベクトルである. すなわち, v .+ c
の各要素は, v
の各要素に c
を加えた和である.
同様に, 演算 v .- c
は, ベクトル v
からスカラー c
を減じたベクトルである. すなわち, v .- c
の各要素は, v
の各要素に c
を減じた差である.
演算子 +
や -
の前のピリオド .
は, 「各要素に対する演算 (element-wise operation)」を意味する. (以下の ■ ドット演算子 で説明する).
julia> xs .+ 2
4-element Vector{Int64}: 3 4 4 3
julia> xs .- 2
4-element Vector{Int64}: -1 0 0 -1
先に描いた三角形を平行移動してみよう.
# Plots パッケージの読み込み
using Plots
#gr() #pythonplot()
xs = [1, 2, 2, 1]
ys = [1, 1, 3, 1]
# 最初のプロット
plot(xs, ys)
# 続けて
# それぞれ1を加える
xs2 = xs .+ 1
ys2 = ys .+ 1
# データ系列を追加する
plot!(xs2, ys2)
関数 plot
と plot!
は, 既定では,すべてのデータが見えるように, 描画範囲を設定しようとする.(が,そのようにならないこともある).
同じ描画範囲に設定してプロットを比較したい場合は,以下を参照せよ.
ピリオドが付かない演算子 +
や -
を用いると,例外(exception, エラー)が発生するので注意しよう.
julia> xs + 2
ERROR: MethodError: no method matching +(::Array{Int64,1}, ::Int64)
■ 範囲
二つまたは三つの数字を半角文字のコロン( :
)で区切ったデータは, 有限の(=要素の数が定まった,finite)等差数列(arithmetic sequence)を 表す. このようなデータの種類を 範囲型
(range type
)という. 範囲型を持つデータを 範囲
(range
)と呼ぶ.
「型(type,かた)」とは「データの種類」である.詳しくは,後の節で述べる.→ ■ 型
二つの数をコロン( :
)で区切った量 a:b
は, a
から 1 づつ増やして b
を超えるまでの数からなる等差数列である. 三つの数をコロンで区切った量 a:c:b
は, a
から c
づつ増やして b
を超えるまでの数からなる等差数列である.
呼び方
a
: 初項(initial term, first term)b
: 末項(last term)c
: 等差(common difference)
一定間隔 c
を「等差(common difference)」と本文では呼ぶ. 数学では「公差」と呼ばれることもあるが,工学での「公差」は tolerance を意味することが多いので,区別した.
julia> 1:5
1:5
julia> xs = 0:0.1:1
0.0:0.1:1.0
範囲から各要素を取り出してベクトルに変換するには,collect
関数を用いる.
julia> collect(xs)
11-element Vector{Float64}: 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
等差 c
は,負の値でもよい. この場合,a:c:b
は,a
から c
づつ増やして b
を「下回る」までの数からなる有限の等差数列となる.
julia> xs = 10:-1:0
10:-1:0
julia> collect(xs)
11-element Vector{Int64}: 10 9 8 7 6 5 4 3 2 1 0
等差 c
が負で,$a < b$ だと,要素は0個になる.
julia> xs = 2:-1:5
2:-1:3
julia> collect(xs)
Int64[]
■ 範囲の各要素をスカラーで乗除する
- 範囲
r
- スカラー
c
演算 r * c
は,範囲 r
のスカラーc
倍である. すなわち, r
の各要素に c
を乗じた結果に相当する「範囲」を与える. 演算 r * v
も,同じ結果を与える.
julia> xs = 1:2:10 # 各要素を2倍する
1:2:9
julia> xs * 2
2:4:18
julia> 2 * xs
2:4:18
結果も範囲となる(賢い!).
範囲のスカラー倍は,初項,末項,等差を,すべてスカラー倍した範囲である(確かめよ).
演算 r / c
は,範囲 r
のスカラーc
商である. すなわち, r
の各要素を c
を除した結果に相当する「範囲」を与える.
julia> # 各要素を2で除す
1:2:9
julia> xs / 2
0.5:1.0:4.5
末項が数字で終わる場合には,範囲のスカラー乗除は,範囲全体を括弧で囲む必要がある.
julia> (2:2:4) * 2
4:4:8
julia> (2:2:4) / 2
1.0:1.0:2.0
注意:括弧をつけないと,解釈が異なる. 範囲の演算子 :
は,加減乗除の演算子よりも優先度が低いので, 2:2:4 * 2
は 2:2:(4 * 2)
と解釈される.
julia> 2:2:4 * 2
2:2:8
■ 範囲の各要素をスカラーで加減する
- 範囲
r
- スカラー
c
演算 r .+ c
は,範囲 r
にスカラー c
を加えた範囲である. すなわち, r .+ c
の各要素は, r
の各要素に c
を加えた和である.
同様に,演算 v .- c
は,v
の各要素から c
を減算した要素からなる範囲を与える.
演算子 +
や -
の前のピリオド .
は, 「各要素に対する演算 (element-wise operation)」を意味する. (この先の ■ ドット演算子 で再度説明する).
julia> xs = 1:2:10 # 各要素に1を加える
1:2:9
julia> xs .+ 1 # 各要素から1を減じる
2:2:10
julia> xs .- 1
0:2:8
範囲のスカラー和差は,等差を変えず,初項と末項にスカラーを加えた範囲である(確かめよ).
この場合, ピリオドが付かない演算子 +
や -
を用いると, 例外(exception, エラー)が発生する.
julia> xs + 1
ERROR: MethodError: no method matching +(::StepRange{Int64, Int64}, ::Int64)
末項が数字で終わる場合には,範囲のスカラー加減は,範囲全体を括弧で囲む必要がある. 範囲とスカラーの和でドットをつけないと,解釈が異なる. 範囲の演算子 :
は,加減乗除の演算子よりも優先度が低いので, 2:2:4 + 2
は 2:2:(4 + 2)
と解釈される.
julia> 2:2:4 + 2
2:2:6
ドットの付け忘れが怖いなら,範囲を括弧で囲むとよい.
julia> (2:2:4) .+ 2
4:2:6
■ コレクション
一つずつ要素を取り出すことができる量をコレクション(collection)という. ベクトルや範囲は,コレクションである.
ベクトルと範囲は,異なる種類(■ 型)の値であるが, スカラーの加減乗除が同じ形式で記載するよう,うまく設計されている. このような例は,Juliaの随所で観察される.
これから説明する例
今後説明する■ 行列も,コレクションの一つである.
■ ドット演算子
コレクションとスカラーとの間の加減で,.+
,.-
のように, 半角文字のピリオド(ドッド)で始まるドット演算子(dot operator)を用いた. ドット演算子は,「コレクションの各要素に対して演算する(element-wise operation)」という意味を持つ.
加減乗除のドット演算子を適用される値の 一方がコレクション,他方がスカラーの場合には, 「スカラーをコレクションと同じ寸法を持つベクトルに拡張して」から,要素どうしの演算を行う仕組みになっている. この仕組みを「ブロードキャスト(broadcast)」と呼ぶ.
▼ 式のプロットを描く
plot
またはplot!
関数に対して, 同じ寸法を持つ二つのベクトルまたは範囲 xs
,ys
を渡すと, xs
, ys
から一つづつ要素を取り出し, これらを $x, y$ 座標とする点どうしを結んで,図形が描かれるのであった.
式のプロットを描くには,$x$ 座標の値 xs
から計算した式の値を,$y$ 座標の値 ys
とすればよい.
二つの直線 $y=-x$ と $y=2x-1$ のプロットを描いてみよう.
# Plots パッケージの読み込み
using Plots
#gr() #pythonplot()
xs = -1:0.1:1
# 描画
plot()
ys1 = -1 * xs
plot!(xs, ys1)
ys2 = 2 * xs .- 1
plot!(xs, ys2)
▲ 練習
別の直線を描いてみよ.
★ 今回のまとめ
- 対話形式の使い方
- 数どうしの加減乗除
- Plots パッケージを用いた図形とプロットの描画
- ベクトルと等差数列
- コレクション
- コレクションの各要素をスカラー乗除する
- コレクションの各要素をスカラーで加減する
- ドット演算子
- 式のプロットを描く