gnuplot によるグラフ作成 - 弘前大学 Home Sweet Home

葛西 真寿 弘前大学大学院理工学研究科

はじめに

この Notebook では,gnuplot_kernel (A Jupyter/IPython kernel for Gnuplot) を使って,関数およびデータのプロットプログラムである gnuplot の使用例を紹介する。

セクションの構成は,テキスト「wxMaxima による数式処理とグラフ作成」の「第2章 wxMaxima によるグラフ作成」や,「Sympy による数式処理とグラフ作成」の 「2 Sympy や Matplotlib によるグラフ作成」に準じているので,Jupyter Notebook の活用例としてだけでなく,wxMaxima や SymPy,Matplotlib などのグラフ作成方法を比較するのに役立つかもしれない。

演算子・定数・関数

gnuplot では以下のような(FORTRAN と同じような... と言っても,もはや通じない)演算記号を使うことができる。

足し算 +,引き算 -,かけ算 *,割り算 /,べき乗 **

print コマンドを使えば,以下のように簡易電卓として使うこともできる。

In [1]:
print 12**2
Out[1]:
144

数の表現方法も(FORTRAN と同様であり... と言っても通じない),整数と実数がある。

In [2]:
print 1/3
Out[2]:
0
In [3]:
print 1./3
Out[3]:
0.333333333333333

非常に大きい数や,とても小さい数を表すには...

(例: $M = 5.972 \times 10^{24}, q = 1.0.6 \times 10^{-10}$)

In [4]:
M = 5.972e24
q = 1.6e-19

gnuplot には定数として円周率 pi がはじめから組み込まれている。

In [5]:
print pi
Out[5]:
3.14159265358979

また、組み込み関数としてよく使われるものをあげると,

sqrt(x)= $\sqrt{x}$ abs(x)= |$x$|
exp(x)= $e^x$ log(x)= $\log_e x$ log10(x) = $\log_{10} x$
sin(x) cos(x) tan(x)
sinh(x) cosh(x) tanh(x)
asin(x)=$\arcsin x$ acos(x)=$\arccos x$ atan(x)=$\arctan x$

gnuplot には,このほか,ユーザが自分で定数や関数を定義できる機能もある。定数については,上で定義した Mq の例がすでにあるので...

In [6]:
print M
Out[6]:
5.972e+24

関数を定義する例をあげる。組み込み関数 sin(x) に入れる x の値は radian 単位である。

In [7]:
print sin(30)
Out[7]:
-0.988031624092862

$\displaystyle \sin \frac{\pi}{6} = ...$

In [8]:
print sin(pi/6)
Out[8]:
0.5

以下のような関数 degsin(x) を定義してやると...

In [9]:
degsin(x) = sin(x*pi/180)
In [10]:
x = 30
print degsin(x)
Out[10]:
0.5

ユーザが定義した定数や関数は,gnuplot を終了すると忘れ去られてしまう。次回もまた使いたいときは,

save "defs.gpt"

などとして現在の定義をファイルに保存し,次に gnuplot を使うときに,

load "degs.gpt"

として読み込んでやればよい。

なお,このページのように Jupyter notebook を使えばユーザが定義した定数や関数,そして描画したグラフもすべて notebook に保存されるので,とても便利。

練習問題: 重力加速度の大きさ

gnuplot を電卓として用い,重力加速度の大きさ $g$ を求める。 地球の質量を$M$、半径を$R$、万有引力定数を$G$とすると、

$$\displaystyle \ g = \frac{GM}{R^2} $$

である。

$M = 5.972 \times 10^{24} \mbox{kg}$, $R = 6.378 \times 10^6 \mbox{m}$, $G = 6.672 \times 10^{-11} \mbox{N} \mbox{ m}^2/\mbox{kg}^2$ のとき、$g$はいくらか?

gnuplot によるグラフ作成

まず,ターミナルを開いて,シェルのプロンプトで gnuplot と入力し,Enter キーを押すと以下のようになる。


$ gnuplot

        G N U P L O T
        Version 5.4 patchlevel 0    last modified 2020-07-13 

        Copyright (C) 1986-1993, 1998, 2004, 2007-2020
        Thomas Williams, Colin Kelley and many others

        gnuplot home:     http://www.gnuplot.info
        faq, bugs, etc:   type "help FAQ"
        immediate help:   type "help"  (plot window: hit 'h')

Terminal type is now 'qt'
gnuplot>   


以下では,Jupyter kernel for gnuplot を使っているので gnuplot のプロンプト gnuplot> は表示されない。

2次元グラフ plot の例

2次元グラフ $y = f(x)$ を $a \le x \le b$ の範囲で描く表記例は,plot [a:b] f(x) です。

例として,$y = \sin x$ のグラフを $-2\pi \le x \le 2 \pi$ の範囲で描きます。基本的な定数の一つである円周率 $\pi$ は gnuplot では pi と書きます。

In [11]:
reset
# 念の為`set` コマンドで定義できるグラフに関する
# 全てのオプションをデフォルトの値に戻します。

plot [-2*pi:2*pi] sin(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1 -6 -4 -2 0 2 4 6 sin(x) sin(x)

いくつかオプションを指定して描く例です。

以下では,座表軸を表示し,線の色(lc)を設定し,凡例(title)を表示させ,x軸とy軸にラベルを表示させて $y = \cos x$ を描いています。

In [12]:
set zeroaxis
set xlabel 'x'
set ylabel 'y'
plot [-2*pi:2*pi] cos(x) title '余弦関数' lc 2
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1 -6 -4 -2 0 2 4 6 y x 余弦関数 余弦関数

$x$ の範囲と $y$ の表示範囲を両方指定してプロットする例。

In [13]:
plot [-pi:pi] [-2:2] tan(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 -3 -2 -1 0 1 2 3 y x tan(x) tan(x)

3次元グラフ splot の例

3次元グラフ $z = g(x, y)$ を描く一般的な表記例は splot [a:b] [c:d] g(x, y) です。

例として,$z = x \sin y$ のグラフを $-3 \le x 3, -4 \le y \le 4$ の範囲で描きます。

In [14]:
# 上記で設定したオプションをデフォルトに戻す
reset

splot [-3:3] [-4:4] x*sin(y) notitle
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -3 -2 -1 0 1 2 3 -4 -3 -2 -1 0 1 2 3 4 -3 -2 -1 0 1 2 3 gnuplot_plot_1

デフォルトでは,splot は透明な曲面を描きます。曲面の重なった部分を非表示にしたい場合は,set hidden3d です。(解除するには,unset hidden3d です。)

曲面を滑らかにするには,isosamples の数値を増やします。

In [15]:
set hidden3d
In [16]:
show isosamples
Out[16]:
	iso sampling rate is 10, 10

In [17]:
set isosamples 50, 50
replot
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 gnuplot_plot_1 gnuplot_plot_2 -3 -2 -1 0 1 2 3 -4 -3 -2 -1 0 1 2 3 4 -3 -2 -1 0 1 2 3

数値データのグラフ作成例

配列の定義と利用

gnuplot では,数値データの配列をつくってグラフを描くことができます。

以下のように array で1次元配列を定義し,値を入れます。配列の番号は 1 からはじまります。

In [18]:
array X[6] = [0, 1, 2, 3, 4, 5]
array Y[6] = [0, 1**2, 2**2, 3**2, 4**2, 5**2]

do for ループ

以下のように,do for を使ったループで配列に値を入れることもできます。

In [19]:
array X[6]
array Y[6]
do for [i=1:6]{
    X[i]=i-1
    Y[i]=(i-1)**2
    }

do for [i=1:6]{print X[i], Y[i]}
Out[19]:
0 0
1 1
2 4
3 9
4 16
5 25

配列 X[i] を $x$,配列 Y[i] を $y$ の値として $(x, y)$ の点をプロットする例です。

In [20]:
reset
plot Y using (X[$1]):2
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 5 10 15 20 25 0 1 2 3 4 5 Y using (X[$1]):2 Y using (X[$1]):2

いくつかオプションを指定してプロットする例。ここでは,w lp (with linespoints の省略形) で各点を線でつないで描きます。

In [21]:
plot Y using (X[$1]):2 w lp pt 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 5 10 15 20 25 0 1 2 3 4 5 Y using (X[$1]):2 Y using (X[$1]):2

丸点の大きさが,svg にしたせいか大きめです。pointsize (ps)0.6 にしてみます。

In [22]:
set pointsize 0.6
replot
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 5 10 15 20 25 0 1 2 3 4 5 Y using (X[$1]):2 Y using (X[$1]):2

複数のグラフを重ねて表示

gnuplot で複数のグラフを重ねて表示する例を示します。

$y = x^2 - 1$ と $y = 4 x - 5$ の2つのグラフを重ねて描きます。$x$ の範囲は $-5 \le x \le 5$ です。

In [23]:
reset

plot [-5:5] x**2 - 1, 4*x - 5
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -25 -20 -15 -10 -5 0 5 10 15 20 25 -4 -2 0 2 4 x**2 - 1 x**2 - 1 4*x - 5 4*x - 5

いくつかオプションを設定して描く例です。

以下の例では,set zeroaxis で x 軸と y 軸を表示させ, set grid; set xtics 1; set ytics 1 で x, y それぞれ 1 ごとに格子線を表示させ, 横軸 (x 軸),縦軸 (y 軸)の表示範囲をそれぞれ $-1 \le x \le 4$, $-2 \le y \le 6$ に制限して,$x^2 - 1$ グラフの線を lw (linewidth) 2 で少し太めにして表示します。

$x=2, y=3$ あたりで両線が接している様子が見えてきます。

In [24]:
set zeroaxis
set grid
set xtics 1
set ytics 1
set key left top

plot [-1:4] [-2:6] x**2 - 1 title "x^2 - 1" lw 2, 4*x - 5 title "4 x - 5"
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -2 -1 0 1 2 3 4 5 6 -1 0 1 2 3 4 x2 - 1 x2 - 1 4 x - 5 4 x - 5

数値データを読み込む

gnuplot あらかじめ作成された数値データファイルを読み込んでグラフを描くこともできます。

以下のような内容のファイル test.dat がカレント・ディレクトリにあるとします。

# x   y
  0   0
  1   1
  2   4
  3   9
  4   16
  5   25

このデータをプロットするには,以下のようにファイル名を指定して plot します。 pt (pointtype) 7 で点種を,lc (linecolor) 7 で色を設定しています。

In [25]:
reset
set pointsize 0.6
plot 'test.dat' pt 7 lc 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 5 10 15 20 25 0 1 2 3 4 5 'test.dat' 'test.dat'

数値データと理論曲線を重ねて表示

前節の数値データファイル test.dat と理論曲線 $y = x^2$ の2つのグラフを重ねて表示してみます。

また,グラフの線と重ならないように,set key left top で凡例の表示位置を左上にします。

In [26]:
set key left top
plot 'test.dat' pt 7 lc 7, x**2 title "x^2"
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 5 10 15 20 25 0 1 2 3 4 5 'test.dat' 'test.dat' x2 x2

媒介変数表示の2次元グラフ

半径1の円の方程式は $x^2 + y^2 = 1$ です。

この円を描くには,$y = \pm\sqrt{1-x^2}$ として $y = f(x)$ の形にするよりも,以下のような媒介変数表示にしたほうが簡単でしょう。

$$ x = \cos t, \quad y = \sin t, \quad(0 \le x \le 2\pi)$$

このような媒介変数表示の2次元グラフを gnuplot で描くには以下のようにします。

最初に set parametric とします。

In [27]:
reset

set parametric
plot [0:2*pi] cos(t), sin(t) title "半径 1 の円"
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1 -1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1 半径 1 の円 半径 1 の円
Out[27]:
	dummy variable is t for curves, u/v for surfaces

これは媒介変数表示の円のグラフですが,横につぶれて楕円のように見えます。せっかくですから,グラフの縦横の比を$1:1$にして円らしく見えるようにします。

In [28]:
set xrange [-1.2:1.2]
set yrange [-1.2:1.2]
set zeroaxis
set key samplen 1 
set size square 
replot
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 -1 -0.5 0 0.5 1 半径 1 の円 半径 1 の円

非媒介変数モードに戻るには,unset parametric と入力します。

なお,set parametric としたときの媒介変数は,デフォルトでは t であるが,どうしてもそれ以外の文字,例えば phi を使いたのであれば以下のようにする。

In [29]:
set xrange [-1.2:1.2]
set yrange [-1.2:1.2]
set parametric
set size square 
plot [phi=0:2*pi] cos(phi), sin(phi) notitle
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 -1 -0.5 0 0.5 1 gnuplot_plot_1

(練習) 楕円のグラフ(楕円中心を原点として)

同様にして,楕円のグラフを描くこともできます。原点を中心とし,長半径 $a$,短半径 $b$ の楕円の式は

$$ \frac{x^2}{a^2} + \frac{y^2}{b^2} = 1 $$

です。媒介変数表示では,

$$ x = a \cos t, \quad y = b \sin t \quad (0 \le t \le 2\pi)$$

と書けます。$a, b$ に適当な値を入れて楕円のグラフを描きなさい。

海王星と冥王星の軌道

太陽からの万有引力を受けて運動する惑星(惑星だけでなく,準惑星や小天体も含みます)は,太陽を焦点とした楕円軌道を描きます。焦点を原点とし,長半径 $a$,離心率 $e$ の楕円の方程式は,極座標 $r, \phi$ を使って以下のように表すことができます。

$$ r = \frac{a(1-e^2)}{1 + e\cos \phi}$$

さて,かつては第9惑星,現在では準惑星の一つである冥王星も楕円軌道を描きます。冥王星の軌道長半径 $a_P = 39.767 \,\mbox{au}$,離心率 $e_P = 0.254$ を使って冥王星の軌道を描きます。

まず,極座標表示の楕円の式を関数として定義します。

In [30]:
r(a, e, phi) = a*(1-e**2)/(1 + e*cos(phi))

極座標表示の2次元グラフ

極座標表示で描く場合は,set polar とします。(解除は unset polar です。)

In [31]:
reset

set zeroaxis
set xrange [-50:50]
set yrange [-50:50]
set polar
set size square

aP = 39.767
eP = 0.254
plot [phi=0:2*pi] r(aP, eP, phi) title '冥王星'
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -40 -20 0 20 40 -40 -20 0 20 40 0 10 20 30 40 50 冥王星 冥王星
Out[31]:
	dummy variable is t for curves

では,この冥王星の軌道と,その内側をまわる海王星の軌道を重ねて描いてみましょう。

海王星の軌道長半径は $a_N=30.1104\,\mbox{au}$,離心率は $e_N=0.0090$ と小さいので簡単のために $e_N = 0$ として扱います。実際の2つの天体の軌道は同じ平面上にありませんが,太陽からの距離のみをみるために,ここでは同一平面上に描きます。

以下の例では,凡例の位置を set key outside で図の外に設定しています。

In [32]:
set key outside  
set grid
aN = 30.1104
eN = 0
replot r(aN, eN, phi) title '海王星'
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -40 -20 0 20 40 -40 -20 0 20 40 0 10 20 30 40 50 冥王星 冥王星 海王星 海王星

月別気温のグラフと関数フィット

以下のような内容のファイル aomori.dat がカレント・ディレクトリにあるとします。

# 青森の月別気温  「理科年表 2019」(丸善)より。
#    月別   日最高   日最低
#    平年   気温の   気温の
# 月 気温  月 別 平 年 値   
 1  -1.2     1.6    -3.9
 2  -0.7     2.3    -3.7
 3   2.4     6.3     1.3        
 4   8.3    13.5     3.7
 5  13.3    18.4     8.9
 6  17.2    21.7    13.5
 7  21.1    25.4    18.0
 8  23.3    27.7    19.8
 9  19.3    24.0    15.1
10  13.1    18.0     8.6
11   6.8    10.9     3.0
12   1.5     4.6    -1.4

1列目の「月」を x,2列目の「月別平年気温」を y としてプロットする例。

In [33]:
reset
set pointsize 0.6
set grid
plot [1:12] "aomori.dat" using 1:2 pt 7 title '平年気温'
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -5 0 5 10 15 20 25 2 4 6 8 10 12 平年気温 平年気温

グラフをみると,月別平年気温は12ヶ月周期の正弦関数または余弦関数のように見えます。では,以下のように関数フィットをしてみましょう。

以下のような関数でフィットしてみます。

$$f(x) = a - b \cos\left(\frac{2\pi (x-c)}{12}\right)$$
In [34]:
a = 1
b = 1
c = 1
In [35]:
f(x) = a - b*cos( 2*pi*(x-c)/12 )
fit f(x) "aomori.dat" using 1:2 via a, b, c
Out[35]:
iter      chisq       delta/lim  lambda   a             b             c            
   0 1.7624375829e+03   0.00e+00  7.39e-01    1.000000e+00   1.000000e+00   1.000000e+00
   * 2.1142340687e+03   1.66e+04  7.39e+00    9.959250e+00   1.053066e+01   5.291637e+00
   1 1.2896418676e+03  -3.67e+04  7.39e-01    2.688467e+00   2.029918e+00   1.167118e+00
   2 4.0989083093e+02  -2.15e+05  7.39e-02    1.003269e+01   1.081626e+01   2.895648e+00
   3 6.3223045451e+01  -5.48e+05  7.39e-03    1.036651e+01   8.731077e+00   1.499286e+00
   4 7.3169349600e+00  -7.64e+05  7.39e-04    1.036667e+01   1.178309e+01   1.487360e+00
   5 7.3147551296e+00  -2.98e+01  7.39e-05    1.036667e+01   1.178326e+01   1.490449e+00
   6 7.3147551292e+00  -5.25e-06  7.39e-06    1.036667e+01   1.178326e+01   1.490449e+00
iter      chisq       delta/lim  lambda   a             b             c            

After 6 iterations the fit converged.
final sum of squares of residuals : 7.31476
rel. change during last iteration : -5.24694e-11

degrees of freedom    (FIT_NDF)                        : 9
rms of residuals      (FIT_STDFIT) = sqrt(WSSR/ndf)    : 0.901527
variance of residuals (reduced chisquare) = WSSR/ndf   : 0.812751

Final set of parameters            Asymptotic Standard Error
=======================            ==========================
a               = 10.3667          +/- 0.2602       (2.51%)
b               = 11.7833          +/- 0.368        (3.123%)
c               = 1.49045          +/- 0.05965      (4.002%)

correlation matrix of the fit parameters:
                a      b      c      
a               1.000 
b              -0.000  1.000 
c              -0.000  0.000  1.000 
In [36]:
print a, b, c
Out[36]:
10.3666666666667 11.7832643434252 1.49044916541745

最小二乗法によって求めた $a, b, c$ の値をもった $f(x)$ のグラフを重ねて描きます。

In [37]:
set key Right at 5, 24
replot f(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -5 0 5 10 15 20 25 2 4 6 8 10 12 平年気温 平年気温 f(x) f(x)

日最高気温,日最低気温の月別平年値も合わせてプロットしてみてください。

stats コマンドによる統計情報

ちなみに,関数フィットした際の定数 $a$ は月別平年気温の年平均値に相当します。平均値を求めるだけなら,最小二乗法などやらなくても以下のようにして求めることができます。

* COLUMN: 
  Mean:              10.3667
In [38]:
stats "aomori.dat" using 2
Out[38]:
* FILE: 
  Records:           12
  Out of range:       0
  Invalid:            0
  Header records:     0
  Blank:              0
  Data Blocks:        1

* COLUMN: 
  Mean:              10.3667
  Std Dev:            8.3685
  Sample StdDev:      8.7406
  Skewness:           0.0452
  Kurtosis:           1.5839
  Avg Dev:            7.5167
  Sum:              124.4000
  Sum Sq.:         2130.0000

  Mean Err.:          2.4158
  Std Dev Err.:       1.7082
  Skewness Err.:      0.7071
  Kurtosis Err.:      1.4142

  Minimum:           -1.2000 [ 0]
  Maximum:           23.3000 [ 7]
  Quartile:           1.9500 
  Median:            10.7000 
  Quartile:          18.2500 

gnuplot を使ってもう少し...

gnuplot を使って,さらにいくつか問題に取り組んでみます。

波動

x 方向に進む波

$\sin(x - v t)$ は$x$の正の方向に速度$v$で進む正弦型の波動をあらわす。 波が進む様子を描いてみよう。

簡単のために,$v = 1$ とする。時刻 $t=0$ では,この波は $\sin x$。少し時間がたった後,たとえば $t = 0.5$ では,$\sin (x - 0.5)$,さらに,$\sin (x - 1.0)$,,$\sin (x - 1.5)$ など...

In [39]:
reset
set key outside
set key samplen 1 
set samples 500
set zeroaxis
set xrange [-10:10]
set yrange [-1.1:1.1]
plot sin(x) lw 2 lt 7 title "sin(x)    "
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 -10 -5 0 5 10 sin(x) sin(x)

set key outside で凡例をグラフ外に表示させると,グラフの横サイズが狭くなります。Jupyter Notebook 内でグラフサイズを変更する例です。

In [40]:
%gnuplot inline svg size 640, 384 font "NotoSansMonoCJKjp-Regular.otf,14"
replot
# gnuplot 内では以下のように。
# gnuplot> set term qt size 640, 384
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 -10 -5 0 5 10 sin(x) sin(x)
In [41]:
plot sin(x) title "sin(x)    " dt 3, \
     sin(x-0.5) lw 2 lc 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 -10 -5 0 5 10 sin(x) sin(x) sin(x-0.5) sin(x-0.5)
In [42]:
plot sin(x) title "sin(x)    " dt 3, \
     sin(x-0.5) dt 3, \
     sin(x-1.0) lw 2 lc 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 -10 -5 0 5 10 sin(x) sin(x) sin(x-0.5) sin(x-0.5) sin(x-1.0) sin(x-1.0)
In [43]:
plot sin(x) title "sin(x)    " dt 3, \
     sin(x-0.5) dt 3, \
     sin(x-1.0) dt 3, \
     sin(x-1.5) lw 2 lc 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 -10 -5 0 5 10 sin(x) sin(x) sin(x-0.5) sin(x-0.5) sin(x-1.0) sin(x-1.0) sin(x-1.5) sin(x-1.5)

while ループと GIF アニメ

Jupyter Notebook 環境では,簡単にアニメーションを作ることはできないが,以下のようにすれば見れそう。


set xrange [-10:10]
set yrange [-1.1:1.1]
i = 0
imax = 20
while(i < imax){
    plot sin(x - 0.628*i) notitle
    pause 0.5
    i = i + 1
}

参考:以下のようにすれば,GIF アニメを作れる。


set terminal gif animate delay 10 optimize size 512,384
set output "hadou.gif"

set samples 512
set zeroaxis
set xlabel ' >>> +x '
set xrange [-10:10]
set yrange [-1.1:1.1]
i = 0
imax = 20
while(i < imax){
    plot sin(x-0.314*i) notitle
    i = i + 1
}
unset output

うなり

振動数が少しだけ異なる2つの波を重ね合わせると「うなり」が起こることを示せ。

In [44]:
%gnuplot inline svg size 512, 384 font "NotoSansMonoCJKjp-Regular.otf,14"
reset
In [45]:
set key below
set samples 500
set zeroaxis
set yrange [-2.1:2.1]
plot [-100:100] sin(x + 0.05*x) + sin(x - 0.05*x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 -100 -50 0 50 100 sin(x + 0.05*x) + sin(x - 0.05*x) sin(x + 0.05*x) + sin(x - 0.05*x)

$\sin(a+b) + \sin(a-b) = 2 \sin a \cos b$ ですから,うなりとなる波形を描いてみます。

In [46]:
replot  2*abs(cos(0.05*x)) lw 2 lc 7 notitle
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 -100 -50 0 50 100 sin(x + 0.05*x) + sin(x - 0.05*x) sin(x + 0.05*x) + sin(x - 0.05*x) gnuplot_plot_2

つまり,$\omega_1 = a+b, \omega_2 = a-b$ の波を重ねると, 振動数の差の半分 $\displaystyle b = \frac{\omega_1 - \omega_2}{2}$ の コサイン波 $2 \cos b t$ が生じるように思えるが...

正確には,その絶対値 $2 | \cos b t|$ なので,振動数は実質その2倍,つまり うなりの振動数は $2 b = \omega_1 - \omega_2$ となり,

振動数のわずかに異なる2つの波を重ねると,それらの振動数の差の振動数をもつうなりが発生する

ということになる,という理解でどうでしょう。

定常波

波長・振幅が等しい正弦波が直線上を逆向きに同じ速さで進んでいると,重ね合わせによってどのような波が生じるか。

$$ \sin (x- v t) + \sin(x + v t)$$
In [47]:
reset 
set zeroaxis
set samples 500
set yrange [-2.1:2.1]
plot sin(x - 0) + sin(x + 0) notitle lw 2 lt 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 -10 -5 0 5 10 gnuplot_plot_1
In [48]:
plot sin(x - 0) + sin(x + 0) notitle dt 3, \
     sin(x - 0.5) + sin(x + 0.5) notitle lw 2 lt 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 -10 -5 0 5 10 gnuplot_plot_1 gnuplot_plot_2
In [49]:
plot sin(x - 0) + sin(x + 0) notitle dt 3, \
     sin(x - 0.5) + sin(x + 0.5) notitle dt 3, \
     sin(x - 1.0) + sin(x + 1.0) notitle lw 2 lt 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 -10 -5 0 5 10 gnuplot_plot_1 gnuplot_plot_2 gnuplot_plot_3
In [50]:
plot sin(x - 0) + sin(x + 0) notitle dt 3, \
     sin(x - 0.5) + sin(x + 0.5) notitle dt 3, \
     sin(x - 1.0) + sin(x + 1.0) notitle dt 3, \
     sin(x - 1.5) + sin(x + 1.5) notitle lw 2 lt 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 -10 -5 0 5 10 gnuplot_plot_1 gnuplot_plot_2 gnuplot_plot_3 gnuplot_plot_4

以下のような GIF アニメを作ってみてください。

一様重力場中の質点の運動

水平な地上で,水平となす角 $\theta$ で斜め上方に初速度の大きさ $v_0$ でボールを投げ出す。 $v_0$ を一定としたとき,水平到達距離を最大にする $\theta$ は? またそのときの水平到達距離は?

無次元化

$t = 0$ で $x(0) = 0, y(0) = 0$ とすると,

$$ x = v_0 t \cos \theta , \quad y = v_0 t \sin\theta - \frac{1}{2} g t^2$$

となるが,$g$ や $v_0$ に実際の次元のついた量を入れるのではなく,まずはこの式を,この系に特徴的な量で無次元化することを考える。

今,$\displaystyle \theta=\frac{\pi}{2}$ として垂直に投げ上げると,鉛直方向の $y$ は

$$ y = v_0 t - \frac{1}{2} g t^2 = \frac{v_0^2}{2 g} - \frac{1}{2} g \left( t - \frac{v_0}{g}\right)^2 $$

となることから,特徴的な量として,$y$ が最大値をとる時刻 $\displaystyle t_m \equiv \frac{v_0}{g}$ と,その時の $y$ の最大値 $\displaystyle y_m \equiv \frac{v_0^2}{2g}$ を使って,以下のような無次元量をつくる。

$$ \bar{x} \equiv \frac{x}{y_m}, \quad \bar{y} \equiv \frac{y}{y_m}, \quad \bar{t} \equiv \frac{t}{t_m}$$

これらの無次元量を使って軌道をあらわすと,

$$ \bar{x} = 2 \bar{t} \cos\theta, \quad \bar{y} = 2 \bar{t} \sin\theta - \bar{t}^2 $$

以後は簡単のために $\bar{\ }$(バー)を省略する。

$\theta$ の値を変えて,$t$ を媒介変数としたグラフをいくつか描いてみる。

In [51]:
reset

x(theta,t) = 2*t*cos(theta)
y(theta,t) = 2*t*sin(theta) - t**2
In [52]:
set parametric
set zeroaxis
plot [0:2] x(pi/4, t), y(pi/4, t) title "θ=π/4"
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1.2 -1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0 0.5 1 1.5 2 2.5 3 θ=π/4 θ=π/4
Out[52]:
	dummy variable is t for curves, u/v for surfaces

媒介変数 $t$ の範囲を適当に [0:2] とした図が上図であるが,$y$ の値がマイナスの領域まで描いてしまって,このボールが地面にめり込んでしまっている!!

以後は $\bar{\ }$ をとる約束だったので, $\displaystyle y = 2 t \sin\theta - t^2 = 0 $ から $t$ の範囲は $\theta$ によって異なり,$0 \le t \le 2 \sin\theta$ であることがわかるので, 以下のようにして,地面にめりこまないように,$y$ がふたたび $0$ になる時刻までのプロットにする。

In [53]:
th1=pi/4
plot [t=0:2] x(th1, t*sin(th1)), y(th1, t*sin(th1)) title 'θ=π/4'
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0 0.5 1 1.5 2 θ=π/4 θ=π/4
In [54]:
th2=pi/6
replot x(th2, t*sin(th2)), y(th2, t*sin(th2)) title 'θ=π/6'
th3=pi/3
replot x(th3, t*sin(th3)), y(th3, t*sin(th3)) title 'θ=π/3'
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0 0.5 1 1.5 2 θ=π/4 θ=π/4 θ=π/6 θ=π/6
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0 0.5 1 1.5 2 θ=π/4 θ=π/4 θ=π/6 θ=π/6 θ=π/3 θ=π/3

さて,肝心の水平到達距離を最大にする $\theta$ だが,地上から投げ上げたボールが再び地上に戻ってくるまでの時間は,(無次元化された時間で) $t = 2\sin\theta$ ということが,上述の議論でわかっているので,これを $x = 2 t \cos\theta$ に代入して,

$$ x = 4 \sin\theta \cos\theta = 2 \sin 2\theta$$

これから,ただちに $x$ は $\theta=\pi/4$ のとき最大値 $2$ をとることがわかる。

あたらめて無次元化するまえの $x$ についてみると,最大到達距離は

$$x_{\max} = \bar{x}_{\max} \, y_m = \frac{v_0^2}{g}$$

ケプラーの第3法則

以下のような内容のファイル planets.dat がカレント・ディレクトリにあるとします。

# 惑星と一部の準惑星「理科年表2019」(丸善)より。
# 
#     軌道長半径  離心率   平均周期
#     a(天文単位)     e      T (年)
水星     0.3841  0.2056    0.24085
金星     0.7233  0.0068    0.61520
地球     1.0000  0.0167    1.00002
火星     1.5237  0.0934    1.88085
木星     5.2026  0.0485   11.8620
土星     9.5549  0.0554   29.4572
天王星  19.2184  0.0463   84.0205
海王星  30.1104  0.0090  164.7701
# Ceres  2.767   0.076     4.60
冥王星  39.767   0.254   248 
# Eris  67.668   0.156   561

2列目の軌道長半径を x に,4列目の平均周期を y にしてプロットしてみます。

In [55]:
reset
In [56]:
set grid
set xlabel "軌道長半径 a"
set ylabel "公転周期 T"
plot "planets.dat" using 2:4 pt 7 lc 7 ps 0.7 notitle
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 50 100 150 200 250 0 5 10 15 20 25 30 35 40 公転周期 T 軌道長半径 a gnuplot_plot_1

対数グラフ

直線で近似できるような単純な比例関係ではなさそうです。

以下のように,set logscale xy として両対数グラフにしてみます。

In [57]:
set logscale xy
replot
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0.1 1 10 100 1000 1 10 公転周期 T 軌道長半径 a gnuplot_plot_1

両対数グラフにすると,データは直線に乗っているようにみえます。ということは, $\displaystyle T = K a^p$ のような関係になっていることが予想されます。

また,$a = 1$ のとき $T=1$ であることから,$K$ の値はほぼ $1$。

さらに,$a=10$ のあたりで $T$ の値は $10$ と $100$ の間であることから,$1 < p < 2$ であることが予想されます。

In [58]:
f(x) = K*x**p
fit f(x) "planets.dat" using 2:4 via K, p
print K, p
Out[58]:
iter      chisq       delta/lim  lambda   K             p            
   0 6.6134138173e+04   0.00e+00  4.64e+01    1.000000e+00   1.000000e+00
   * 2.1191662436e+07   9.97e+04  4.64e+02    1.289586e+00   2.199178e+00
   1 4.0057677906e+04  -6.51e+04  4.64e+01    1.054161e+00   1.190785e+00
   * 1.2058224131e+05   6.68e+04  4.64e+02    1.144339e+00   1.670822e+00
   2 4.8663711530e+03  -7.23e+05  4.64e+01    1.109225e+00   1.396774e+00
   3 1.1720575605e+02  -4.05e+06  4.64e+00    1.113010e+00   1.477055e+00
   4 9.3883640709e-01  -1.24e+07  4.64e-01    1.039488e+00   1.486259e+00
   5 6.2273611805e-01  -5.08e+04  4.64e-02    1.036398e+00   1.487599e+00
   6 6.2271346074e-01  -3.64e+00  4.64e-03    1.036419e+00   1.487598e+00
   7 6.2271346073e-01  -1.72e-06  4.64e-04    1.036419e+00   1.487598e+00
iter      chisq       delta/lim  lambda   K             p            

After 7 iterations the fit converged.
final sum of squares of residuals : 0.622713
rel. change during last iteration : -1.7208e-11

degrees of freedom    (FIT_NDF)                        : 7
rms of residuals      (FIT_STDFIT) = sqrt(WSSR/ndf)    : 0.29826
variance of residuals (reduced chisquare) = WSSR/ndf   : 0.0889591

Final set of parameters            Asymptotic Standard Error
=======================            ==========================
K               = 1.03642          +/- 0.01388      (1.34%)
p               = 1.4876           +/- 0.003769     (0.2533%)

correlation matrix of the fit parameters:
                K      p      
K               1.000 
p              -0.997  1.000 
1.03641859501968 1.48759778359842
In [59]:
replot f(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0.1 1 10 100 1000 1 10 公転周期 T 軌道長半径 a gnuplot_plot_1 f(x) f(x)

$\displaystyle T = 1.04 \ a^{1.49}$ のような関係が得られました。

実際のケプラーの第3法則は,$T \propto a^{1.5}$ すなわち,$\displaystyle T^2 \propto a^3$ です。

データファイルから配列へ代入

In [60]:
# データの行数の取得。stats コマンドは数値データしか扱えない。
stats "planets.dat" using 2 nooutput  # 1 桁目は数値ではないので,2桁目で。
N = STATS_records   # データの行数

# 配列の宣言
array a[N]    # 軌道長半径
array T[N]    # 周期

# データファイルから配列へ代入
stats "planets.dat" using (a[$0+1] = $2, 0) nooutput
stats "planets.dat" using (T[$0+1] = $4, 0) nooutput

# 惑星名。stats は文字データは読めないらしいので,手動で代入。
array P[9] = ["水星","金星","地球","火星","木星","土星",\
              "天王星","海王星","冥王星"]

# 配列の内容の表示
do for [i=1:N]{
     print P[i], "   ", a[i], "   ", T[i]
     }
Out[60]:
水星   0.3841   0.24085
金星   0.7233   0.6152
地球   1.0   1.00002
火星   1.5237   1.88085
木星   5.2026   11.862
土星   9.5549   29.4572
天王星   19.2184   84.0205
海王星   30.1104   164.7701
冥王星   39.767   248.0

簡単のために,惑星(および冥王星)を離心率 $e=0$ の円軌道として,1年の間にどれだけ公転運動するかを描いてみます。

半径 $a_i$,公転周期 $T_i$ の天体の $t=0$ での初期位置を $x$ 軸上として,時刻 $t$ における位置は

$$x = a_i \cos \frac{2\pi t}{T_i}, \quad y = a_i \sin \frac{2\pi t}{T_i}$$

ですから...

In [61]:
reset

set parametric
set zeroaxis
set key left top
set key samplen 1

plot [t=0:T[3]] a[3]*cos(2*pi*t/T[3]), a[3]*sin(2*pi*t/T[3]) title P[3]
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1 -1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1 地球 地球
Out[61]:
	dummy variable is t for curves, u/v for surfaces
In [62]:
replot a[4]*cos(2*pi*t/T[4]), a[4]*sin(2*pi*t/T[4]) title P[4]
replot a[5]*cos(2*pi*t/T[5]), a[5]*sin(2*pi*t/T[5]) title P[5]
replot a[6]*cos(2*pi*t/T[6]), a[6]*sin(2*pi*t/T[6]) title P[6]
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 1.5 2 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 地球 地球 火星 火星
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 1.5 2 2.5 3 -2 -1 0 1 2 3 4 5 6 地球 地球 火星 火星 木星 木星
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1 -0.5 0 0.5 1 1.5 2 2.5 3 -2 0 2 4 6 8 10 地球 地球 火星 火星 木星 木星 土星 土星

地球の公転軌道が円にみえるように xrange, yrange, ratio を調整して描きます。

In [63]:
set xrange [-2:10]
set yrange [-2:4]
set size ratio 0.5
replot
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -2 -1 0 1 2 3 4 -2 0 2 4 6 8 10 地球 地球 火星 火星 木星 木星 土星 土星
  1. 残りの天体の軌道も描いてみましょう。
  2. GIF アニメにしてみましょう。
  3. 一番内側の水星がちょうど一周する時間に,残りの天体はどこまで運動するかがわかるように描いてみましょう。

人口問題

マルサスの人口モデル

人口変化のしかたを明らかにし,将来の変化を予測するモデルを定式化するこ とは実社会において非常に重要な問題である。ここでは,まずマルサスの 「人口論」に書かれたアイデアを紹介する。

時刻 $t$ におけるある国の総人口を $N(t)$ とする。短い時間間隔 $dt$ における 出生数と死亡数は,ともにその時点での総人口と時間間隔に比例するから,

$$\mbox{出生数} = \alpha N dt, \quad \mbox{死亡数} = \beta N dt $$

したがって,時間間隔$dt$での人口の増加$dN$は

$$dN = \alpha N dt - \beta N dt = \gamma N dt, \quad\mbox{ただし}\ \gamma \equiv \alpha - \beta $$

これは微分方程式

$$\frac{dN}{dt} = \gamma N $$

であり,次のように解ける。

$$N(t) = N_0 \,e^{\gamma (t - t_0)} $$

ここで,$N_0 = N(t_0)$ は $t_0$ 年の人口である。また,$\gamma$ は,$t_0$ 年と $t_1$ 年の人口を使って以下のように求めることができる。

$$ \gamma = \frac{1}{t_1 - t_0} \ln\left(\frac{N(t_1)}{N_0} \right)$$

以下のような内容のファイル usa.dat がカレント・ディレクトリにあるとします。

# usa.dat
#
# 年 米国の人口(単位: 百万人)
1790      3.9
1800      5.3
1810      7.2
1820      9.6
1830     12.9
1840     17.1
1850     23.2
1860     31.4
1870     38.6
1880     50.2
1890     62.9
1900     76.0
1910     92.0
1920    106.5
1930    123.2

この数値データをプロットします。

In [64]:
# 前の設定が残っていると困るので,元に戻しておきます。
reset
In [65]:
set grid
set key left top
set key samplen 1

set xlabel '年'
set ylabel '人口(単位:百万人)'
plot "usa.dat" title "米国の人口" pt 7 ps 0.6
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 20 40 60 80 100 120 140 1780 1800 1820 1840 1860 1880 1900 1920 1940 人口(単位:百万人) 米国の人口 米国の人口

人口データから,$t_0, N_0, \gamma$ の値を求め,マルサスモデル $N(t) = N_0 \,e^{\gamma (t - t_0)}$ を重ねて描きます。

In [66]:
t0 = 1790
N0 = 3.9
gamma = 1./(1800-1790) * log(5.3/3.9)

Nm(t) = N0*exp(gamma*(t-t0))
replot Nm(x) title "マルサスモデル"
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 50 100 150 200 250 300 1780 1800 1820 1840 1860 1880 1900 1920 1940 人口(単位:百万人) 米国の人口 米国の人口 マルサスモデル マルサスモデル

上の結果から,何がわかりますか?

ヴェアフルストによる修正モデル

マルサス・モデルは,$\gamma > 0$ の場合には人口の際限ない増加を予測する。 しかし,実際には食糧資源の供給不足,人口の過密,その他の環境的要因によ り,このような無制限な増加は続かない。

ヴェアフルストは,人口過密の要因を考慮にいれて,次のような修正を提案し た。人口は継続し続ける限り増加するが,上限 (それを$N_{\max}$としよう) があるとする。そして,人口変化は,次の各々に比例すると仮定する:

  1. 現在の人口 $N$
  2. 未使用の人口資源に対する割合 $(1 - N/N_{\rm max})$

したがって微分方程式は

$$ \frac{dN}{dt} = \gamma N \left(1 - \frac{N}{N_{\rm max}}\right) $$

となり,(変数分離法によってこの式は解けて)解は

$$ N(t) = N_0 \frac{N_{\rm max}}{N_0 + (N_{\rm max}-N_0)\,e^{-\gamma (t-t_0)}} $$

パラメータ $N_{\max}$ をどのように選ぶと,米国の人口変化をよく再現するか,調べてみます。

In [67]:
t0 = 1790
N0 = 3.9
gamma = 1./(1800-1790) * log(5.3/3.9)

Nv(t) = N0*Nmax/(N0 + (Nmax - N0)*exp(-gamma*(t-t0)))
fit Nv(x) "usa.dat" using 1:2 via Nmax
replot Nv(x) title "ヴェアフルストモデル" lc 7
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 50 100 150 200 250 300 1780 1800 1820 1840 1860 1880 1900 1920 1940 人口(単位:百万人) 米国の人口 米国の人口 マルサスモデル マルサスモデル ヴェアフルストモデル ヴェアフルストモデル
Out[67]:
iter      chisq       delta/lim  lambda   Nmax         
   0 4.9508263697e+04   0.00e+00  1.06e+00    1.000000e+00
   1 2.2011632447e+04  -1.25e+05  1.06e-01    3.747798e+01
   2 2.6058115269e+03  -7.45e+05  1.06e-02    1.294357e+02
   3 8.8265950844e+01  -2.85e+06  1.06e-03    1.981613e+02
   4 1.3341184836e+01  -5.62e+05  1.06e-04    2.152396e+02
   5 1.3248691294e+01  -6.98e+02  1.06e-05    2.158899e+02
   6 1.3248690564e+01  -5.51e-03  1.06e-06    2.158875e+02
iter      chisq       delta/lim  lambda   Nmax         

After 6 iterations the fit converged.
final sum of squares of residuals : 13.2487
rel. change during last iteration : -5.51383e-08

degrees of freedom    (FIT_NDF)                        : 14
rms of residuals      (FIT_STDFIT) = sqrt(WSSR/ndf)    : 0.972798
variance of residuals (reduced chisquare) = WSSR/ndf   : 0.946335

Final set of parameters            Asymptotic Standard Error
=======================            ==========================
Nmax            = 215.888          +/- 2.083        (0.965%)
In [68]:
# 凡例の位置を微調整して描きます。
set key default
set key at 1880,290
replot
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0 50 100 150 200 250 300 1780 1800 1820 1840 1860 1880 1900 1920 1940 人口(単位:百万人) 米国の人口 米国の人口 マルサスモデル マルサスモデル ヴェアフルストモデル ヴェアフルストモデル

フーリエ級数展開

周期$2L$の周期関数$f(x)$のフーリエ級数展開は

$$ f(x) = \frac{a_0}{2} + \sum_{n=1}^{\infty}\left( a_n \cos\frac{n\pi x}{L} + b_n \sin \frac{n\pi x}{L}\right) $$

ここで,

$$ a_n = \frac{1}{L} \int_{-L}^{L} f(x)\cos\frac{n\pi x}{L}\, dx, \quad b_n = \frac{1}{L} \int_{-L}^{L} f(x)\sin\frac{n\pi x}{L}\, dx. $$

矩形波のフーリエ級数展開

以下のように $\pi \le x < \pi$ で定義された矩形が,この領域外では周期 $2\pi$ の矩形波となっている例。

$$ f(x) = \left\{ \begin{array}{rl} -1 & \mbox{$(-\pi \le x < 0)$} \\ 1 & \mbox{$(0 \le x < \pi)$} \end{array} \right. $$

gnuplot でこの周期的矩形波をどうやって表すかが,腕の見せどころ。

私としては,以下を提案する。

$$ f(x) = \mbox{sgn}(\sin x) $$

ここで,$\mbox{sgn}(x)$ は,$x>0$ のとき $+1$,$x<0$ のとき $-1$ を返す関数。

In [69]:
reset
f(x) = sgn(sin(x))
plot [-2*pi:2*pi] [-1.5:1.5] f(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1.5 -1 -0.5 0 0.5 1 1.5 -6 -4 -2 0 2 4 6 f(x) f(x)
In [70]:
# 少し体裁を整える。
set samples 500
set grid
set xtics pi
set format x '%4.1P π'
replot
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1.5 -1 -0.5 0 0.5 1 1.5 -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π f(x) f(x)
In [71]:
f1(x) = 4./pi*sin(x)
f3(x) = 4./(pi*3)*sin(3*x)
f5(x) = 4./(pi*5)*sin(5*x)
f7(x) = 4./(pi*7)*sin(7*x)

plot [-2*pi:2*pi] [-1.5:2] f(x), \
    f1(x) lc 7 lw 3
    
plot [-2*pi:2*pi] [-1.5:2] f(x), \
    f1(x) notitle dt 3, \
    f1(x) + f3(x) lc 7 lw 3

plot [-2*pi:2*pi] [-1.5:2] f(x), \
    f1(x) notitle dt 3, \
    f1(x) + f3(x) notitle dt 3, \
    f1(x) + f3(x) + f5(x) lc 7 lw 3

plot [-2*pi:2*pi] [-1.5:2] f(x), \
    f1(x) notitle dt 3, \
    f1(x) + f3(x) notitle dt 3, \
    f1(x) + f3(x) + f5(x) notitle dt 3, \
    f1(x) + f3(x) + f5(x) + f7(x) lc 7 lw 3
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1.5 -1 -0.5 0 0.5 1 1.5 2 -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π f(x) f(x) f1(x) f1(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1.5 -1 -0.5 0 0.5 1 1.5 2 -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π f(x) f(x) gnuplot_plot_2 f1(x) + f3(x) f1(x) + f3(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1.5 -1 -0.5 0 0.5 1 1.5 2 -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π f(x) f(x) gnuplot_plot_2 gnuplot_plot_3 f1(x) + f3(x) + f5(x) f1(x) + f3(x) + f5(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 -1.5 -1 -0.5 0 0.5 1 1.5 2 -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π f(x) f(x) gnuplot_plot_2 gnuplot_plot_3 gnuplot_plot_4 f1(x) + f3(x) + f5(x) + f7(x) f1(x) + f3(x) + f5(x) + f7(x)

三角波のフーリエ級数展開

以下のように $\pi \le x < \pi$ で定義された三角形が,この領域外では周期 $2\pi$ の三角波となっている例。

$$ f(x) =\left\{ \begin{array}{rl} \pi + x, &\mbox{$(-\pi \le x < 0)$} \\ \pi - x, &\mbox{$(0 \le x < \pi)$} \end{array} \right. $$

gnuplot でこの周期的三角波をどうやって表すかが,腕の見せどころ。

私としては,以下を提案する。

f(x) = abs(x - 2*pi*floor(x/(2*pi)) - pi)

$$ f(x) = \left| x - 2\pi\,\mbox{floor}\left(\frac{x}{2\pi}\right) - \pi\right| $$
In [72]:
reset

set samples 500
set grid
set xtics pi
set format x '%4.1P π'
set ytics 0.5*pi
set format y '%4.1P π'
set yrange [-0.2:4]

f(x) = abs(x - 2*pi*floor(x/(2*pi)) - pi)
plot [-3*pi:3*pi] f(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0.0 π 0.5 π 1.0 π -3.0 π -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π 3.0 π f(x) f(x)
In [73]:
a0 = pi/2
f1(x) = 4./pi*cos(x)
f3(x) = 4./(9*pi)*cos(3*x)
f5(x) = 4./(25*pi)*cos(5*x)
f7(x) = 4./(49*pi)*cos(7*x)

plot [-3*pi:3*pi] f(x), a0 + f1(x) lc 7 lw 2
plot [-3*pi:3*pi] f(x), a0 + f1(x) + f3(x) lc 7 lw 2
plot [-3*pi:3*pi] f(x), a0 + f1(x) + f3(x) + f5(x) lc 7 lw 2
plot [-3*pi:3*pi] f(x), a0 + f1(x) + f3(x) + f5(x) + f7(x) lc 7 lw 2
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0.0 π 0.5 π 1.0 π -3.0 π -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π 3.0 π f(x) f(x) a0 + f1(x) a0 + f1(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0.0 π 0.5 π 1.0 π -3.0 π -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π 3.0 π f(x) f(x) a0 + f1(x) + f3(x) a0 + f1(x) + f3(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0.0 π 0.5 π 1.0 π -3.0 π -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π 3.0 π f(x) f(x) a0 + f1(x) + f3(x) + f5(x) a0 + f1(x) + f3(x) + f5(x)
Gnuplot Produced by GNUPLOT 5.4 patchlevel 0 0.0 π 0.5 π 1.0 π -3.0 π -2.0 π -1.0 π 0.0 π 1.0 π 2.0 π 3.0 π f(x) f(x) a0 + f1(x) + f3(x) + f5(x) + f7(x) a0 + f1(x) + f3(x) + f5(x) + f7(x)