第2回:▶︎ 複数のグラフを描く

第2回:▶︎ 複数のグラフを描く

■ リテラル

リテラル (literal) とは、 「文字の並び」の通りに解釈される量をいう。

11.1 はリテラルである。 それぞれ、整数 1, 小数1.1 という値として評価されるからである。

■ 文字列

「文字の並び」として表される量が、文字列である。 文字列のリテラルは、ダブルクォート " で囲まれた文字の並びである。

julia> "Hello world"
"Hello world"

文字列を連結するには、演算子 * を用いる。

julia> h="Hello"
"Hello"

julia> w="world"
"world"

julia> h*w
"Helloworld"

julia> h*" "*w
"Hello world"

数字を表す文字列を作るには、string関数を用いる。

julia> string(0)
"0"

julia> string(1)
"1"

julia> string(1.1)
"1.1"

■ for文

Repeated Evaluation: Loops

一つずつ要素を取り出すことができる量を、コレクションという。 ベクトルやRangeは、コレクションである。

for文を用いると、コレクションから要素を一つづつ取り出して、 end文が出現するまでの文を繰り返して、計算を行うことができる。 この繰り返される部分をブロック(block)という。 ブロックは、字下げ (indent) で表記される。 が、字下げは見やすさのためだけである。

繰り返しをループ(loop)ともいう。

Note

ブロックは、for文以外にも出現する (例えば、 ■ if文 )。 区別したいなら forブロックとも称する。

次の例では、変数 iに、ベクトルの各要素を入れて、end文までの計算を繰り返す。 コレクションの各要素が入る変数をループ変数 (loop variable)という。

julia> for i in [1,3,2]
         @show i   # 式 i の値を表示する
       end
i = 1
i = 3
i = 2

@show i は、式 i の値を表示するマクロである。

Range型を用いた for文の例を示す。

julia> for i in 1:5
         println( string(i) )
       end
1
2
3
4
5

string関数の結果を表示する。 println 関数は、印字してから、改行する命令である。

▶︎ グラフに凡例を加える

グラフの凡例(lengend)は、グラフに描かれた曲線を区別するための説明である。 PyPlotパッケージで書かれたグラフに凡例を追加するには、以下のようにする。

まず、plot関数に label=文字列 の形式で、 その曲線に付与する文字列を指定する。 全ての曲線を描いた後に、legend関数を付与する。

using PyPlot
xs=-1:0.1:1
plot(xs,-1*xs,  label="y=-x")
plot(xs,2*xs-1, label="y=2x-1")
legend()

比例関係 $y = ax$ ($a=1,2,3,4,5$)のグラフを描こう。

using PyPlot
xs=-1:0.1:1
plot(xs,   xs, label="y= x" )
plot(xs, 2*xs, label="y=2x" )
plot(xs, 3*xs, label="y=3x" )
plot(xs, 4*xs, label="y=4x" )
plot(xs, 5*xs, label="y=5x" )
end
legend()

上のプログラムを、for文を用いて繰り返しで書き直してみよう。

using PyPlot
xs=-1:0.1:1
for a in 1:5
  plot(xs, a*xs, label="y="*string(a)*"x" )
end
legend()

▶︎ 冪乗関数を描く

Base.:^ - Method

x^y は、冪(べき, power)ないし冪乗(べきじょう)$x^y$を表す。 $x$を底 (base)、$y$を冪指数 (exponent)という。

julia> 2^2
4

julia> 2^3
8

julia> 2^4
16

冪指数が負の整数のとき、冪の計算は失敗する (DomainError : 定義域外の例外)。 代わりに、負の小数を指定する。

julia> 2^-2 # DomainError
ERROR: DomainError:

julia> 2^-2.0
0.25

ベクトルや等差級数の各要素に対して 冪乗を計算するには 演算子 ^の前にピリオド. を加える。

julia> 2.^[2,3,4]
3-element Array{Int64,1}:
  4
  8
 16

julia> (2:4).^2
3-element Array{Int64,1}:
  4
  9
 16

julia> 2:4.^2    # `^`は `:` よりも優先度が高い
2:16

冪乗 $y=x^a, (a=2,3,4,5)$ のグラフを描こう。

plt[:axes]()[:set_aspect]("equal") は、 グラフの縦横比 (アスペクト比 aspect ratio) を等しくする命令である。

using PyPlot
xs=0:0.1:1
plot(xs, xs.^2 )
plot(xs, xs.^3 )
plot(xs, xs.^4 )
plot(xs, xs.^5 )
plt[:axes]()[:set_aspect]("equal")

for文を使って、繰り返しの処理をまとめる。

さらに、凡例を追加する。

using PyPlot
# 間隔を狭めた
xs=0:0.05:2
for a in 2:5
  plot(xs, xs.^a , label="y=x^"*string(a) )
end
legend()
# 描画範囲を設定
xlim(-0.05,2)
ylim(-0.05,2)
plt[:axes]()[:set_aspect]("equal")

plot命令は、全ての点を表示しようとする。 グラフの描画範囲を調整するには、関数 xlimylim を用いる。

関数 xlim(a,b) は、x軸の描画を a から b の範囲に限定する命令である。

関数 ylim(a,b) は、y軸の描画を a から b の範囲に限定する命令である。

▶︎ ローレンツ関数を描く

Lorentzian Function

以下の曲線を、 ローレンツ関数 (Lorentzian function)という。

\[y = \frac{\frac{\gamma}{2}}{(x-x_0)^2+\left(\frac{\gamma}{2}\right)^2}\]
\[\gamma > 0\]

パラメータを $x_0 = 0, \gamma = 2$ のように選ぶと、 以下のように簡単な形となる。

\[y = \frac{1}{x^2+1}\]

まず、この曲線を描いてみる。 各要素に対して除算を行うため、/の前にも、ピリオド.を付与する。

julia> xs=-3:0.5:3
-3.0:0.5:3.0

julia> 1 ./ (xs.^2+1)
13-element Array{Float64,1}:
 0.1
 0.137931
 0.2
 0.307692
 0.5
 0.8
 1.0
 0.8
 0.5
 0.307692
 0.2
 0.137931
 0.1

上のグラフを描こう。

using PyPlot
xs=-3:0.1:3
plot(xs, 1 ./ (xs.^2+1) )

以下のように、パラメータ $\gamma$ を導入する。

\[y = \frac{\frac{\gamma}{2}}{x^2+\left(\frac{\gamma}{2}\right)^2}\]

三つのパラメータ $\gamma=0.5,1,2$ について、この曲線を描く。

using PyPlot
xs=-3:0.05:3
gamma=0.5
plot(xs, (gamma/2) ./ (xs.^2+(gamma/2)^2), label=gamma )
gamma=1.0
plot(xs, (gamma/2) ./ (xs.^2+(gamma/2)^2), label=gamma )
gamma=2.0
plot(xs, (gamma/2) ./ (xs.^2+(gamma/2)^2), label=gamma )
legend()
plt[:axes]()[:set_aspect]("equal")

gammaの値が変わっても、それぞれの曲線を描く命令は変わらない。 for文を用いて、gammaの値を変えてみよう。(結果のグラフは同じである)

using PyPlot
xs=-3:0.05:3
for gamma in [0.5,1.0,2.0]
  plot(xs, (gamma/2) ./ (xs.^2+(gamma/2)^2), label=gamma )
end
legend()
plt[:axes]()[:set_aspect]("equal")

ローレンツ関数には、次の性質がある。

2つ目の性質を観察するため、最大値に対する比を描いてみる。

PyPlotパッケージに用意された関数 axhline() は、 水平線(horizontal line)を描く。 引数 color="k" は、黒色(black)で描くことを指定し、lw=0.5は線幅(linewidth)を指定する。

using PyPlot
xs=-3:0.05:3
for gamma in [0.5,1.0,2.0]
  plot(xs,
    (gamma/2) ./ (xs.^2+(gamma/2)^2) / (2/gamma),
    label=gamma )
end
legend()
axhline(1/2, color="k", lw=0.5)

Note

plot関数の文は、複数の行に渡って記述しているが、行が更に続くことを示す記法は、特に用意されていない。構文が行末で終わらなければ、次の行まで読みに行くことになっている。

パラメータ $\gamma$は、半値全幅 (Full Width of Half Maximum, FWHM)と呼ばれる。 $\gamma$を非常に小さくすると、 Diracのデルタ関数 (Dirac delta function)の近似(の一つ)となる。

■ 更新演算子

Updating operators

変数に四則演算などを行って、元の変数に再代入する場合には、 更新演算子を用いるとよい。 演算子の直後に = の文字が入る。

julia> x=1
1

julia> # 再代入
       x=x+1
2

julia> # 更新演算子
       x+=1
3

演算子 +, -, *, /, ^ に対して、 更新演算子 +=, -=, *=, /=, ^= が用意されている。

以下の例は、変数 gamma を 2 で繰り返し割り算する。

julia> gamma=2
2

julia> for i=1:5
         gamma /= 2
         @show gamma
       end
gamma = 1.0
gamma = 0.5
gamma = 0.25
gamma = 0.125
gamma = 0.0625

更新演算子 /= を利用して、ローレンツ関数のパラメータ gamma を変えてみる。

using PyPlot
xs=-3:0.05:3
gamma=2
for i in 1:5
  plot(xs,
    (gamma/2) ./ (xs.^2+(gamma/2)^2) / (2/gamma),
    label=gamma )
  gamma /= 2
end
legend()
axhline(1/2, color="k", lw=0.5)

更新演算子は、ベクトルのスカラー倍や、定数の加減にも適用できる。

julia> xs = [1,2,2,1]
4-element Array{Int64,1}:
 1
 2
 2
 1

julia> xs +=1
4-element Array{Int64,1}:
 2
 3
 3
 2

julia> xs +=1
4-element Array{Int64,1}:
 3
 4
 4
 3

julia> xs *=1
4-element Array{Int64,1}:
 3
 4
 4
 3

前節の三角形を描く例題で、更新演算子 +=を用いて、図形を繰り返し並行移動してみよう。

using PyPlot
xs = [1,2,2,1]
ys = [1,1,3,1]
for i=1:5
  plot(xs,ys)
  xs += 0.5
  ys += 0.5
end
plt[:axes]()[:set_aspect]("equal")

◀︎ 練習

ローレンツ関数において、パラメータ $x_0$ を変えたグラフを作成せよ。 for文を使う方法、更新演算子を使う方法の、二つで描いてみよ。

★ 今回のまとめ