Maxima を使って,関数のグラフを描くことができます。また,数値データもグラフにすることができます。
Maxima の2次元グラフ作成は plot2d()
でもできますが,ここでは,draw2d()
について説明します。
draw2d()
でプロットできるオブジェクトは以下のとおりです。
- 陽関数 $y = f(x)$:
explicit(f(x), x, xmin, xmax)
- 陰関数 $f(x, y) = 0$:
implicit(f(x, y) = 0, x, xmin, xmax, y, ymin, ymax)
- 媒介変数表示 $x(t), y(t)$:
parametric(x(t), y(t), t, tmin, tmax)
- 曲座標表示 $r(\phi)$:
polar(r(phi), phi, 0, 2*pi)
- 点,$x$ 座標 $y$ 座標の数値データ:
points([[x1, y1], [x2, y2], ... ])
またはpoints([[x1, x1, ...], [y1, y2, ...]])
- ベクトル,始点 $x_0, y_0$ からベクトル成分 $v_x, v_y$:
vector([x0, y0], [vx, vy])
また,2本の陽関数で挟まれた領域を塗りつぶすこともできます。
陽関数のグラフ
例として,$y = \sin x$ のグラフを $−2\pi \leq x \leq 2\pi$ の範囲で描きます。基本的な定数の一つである円周率 $\pi$ は Maxima では %pi
と書きます。
draw2d(explicit(sin(x), x, -2*%pi, 2*%pi))$
いくつかオプションを設定する例。
/* オプションの設定例 */
draw2d(
/* フォント設定 */
font = "Arial", font_size = 16,
/* 表示範囲。描画範囲と別に指定可能。 */
xrange = [-10, 10], yrange = [-1.1, 1.1],
/* x 軸 y 軸の表示 */
xaxis = true, yaxis = true,
/* グリッド */
grid=true,
/* 凡例 */
key = "正弦関数",
/* 色 */
color = red,
/* 線の太さ */
line_width = 2,
explicit(sin(x), x, -2*%pi, 2*%pi)
)$
color
color
は線や点などの色を指定します。デフォルトは blue
。利用可能な色の名前は:
white black gray0 grey0
gray10 grey10 gray20 grey20
gray30 grey30 gray40 grey40
gray50 grey50 gray60 grey60
gray70 grey70 gray80 grey80
gray90 grey90 gray100 grey100
gray grey light_gray light_grey
dark_gray dark_grey red light_red
dark_red yellow light_yellow dark_yellow
green light_green dark_green spring_green
forest_green sea_green blue light_blue
dark_blue midnight_blue navy medium_blue
royalblue skyblue cyan light_cyan
dark_cyan magenta light_magenta dark_magenta
turquoise light_turquoise dark_turquoise pink
light_pink dark_pink coral light_coral
orange_red salmon light_salmon dark_salmon
aquamarine khaki dark_khaki goldenrod
light_goldenrod dark_goldenrod gold beige
brown orange dark_orange violet
dark_violet plum purple
色はまた "#rrggbb"
のような16進コードでも指定でき,面倒な場合は以下のような数値(0~17)でも指定可能です。
draw2d(
xlabel = "", ylabel = "", line_width = 4,
xrange = [-10, 10], yrange = [-18, 1],
makelist([color = i,
key = concat("color = ", i),
explicit(-i, x, -10, 0)],
i, 0, 17)
)$
system("cp ~/.maxplot.svg ./maxdraw03.svg")$
陰関数のグラフ
例として,$x^2 + y^2 = 1$ のグラフを描きます。$y$ について解いて陽関数の形にしたり,以下で述べるような媒介変数表示にしなくても,陰関数のまま,グラフに描くことができます。
/* ip_grid を設定しないと線がガタガタになる場合も。 */
draw2d(
/* 滑らかにするために ip_grid を多めに */
ip_grid = [200, 200],
implicit(x**2 + y**2 = 1, x, -1.2, 1.2, y, -1.2, 1.2)
)$
縦横比・サイズの設定
縦横の比 proportional_axes = xy
を設定して円らしく見えるようにします。size
も変更します。弘大 JupyterHub ではグラフを svg でインライン表示させているので, user_preamble
で size 600, 600
などと設定します。
/* オプションの設定例 */
draw2d(
/* 滑らかにするために ip_grid を多めに */
ip_grid = [200, 200],
/* 縦横比 */
proportional_axes = xy,
/* x 軸 y 軸の表示 */
xaxis = true, yaxis = true,
/* サイズの設定 */
user_preamble = "set term svg font \",14\" size 600,600;",
line_width = 2,
implicit(x**2 + y**2 = 1, x, -1.2, 1.2, y, -1.2, 1.2)
)$
媒介変数表示のグラフ
半径 $1$ の円の方程式は $x^2 +y^2 = 1$ です。この円を以下のような媒介変数表示にして描きます。
$$ x=\cos t, \quad y=\sin t \quad (0 \leq t \leq 2\pi) $$
/* オプションの設定例 */
draw2d(
/* 滑らかにするために nticks を多めに */
nticks = 200,
/* 縦横比。*/
proportional_axes = xy,
/* 表示範囲 */
xrange = [-1.5, 1.5], yrange = [-1.1, 1.1],
/* x 軸 y 軸の表示 */
xaxis = true, yaxis = true,
parametric(cos(t), sin(t), t, 0, 2*%pi)
)$
点・数値データのグラフ
以下の例では,最初(左側)の数値を $x$ 座標の値,次(右側)の数値を $y$ 座標の値として 6 個の点 からなるリスト data
の各点をつないだ折れ線グラフを描きます。
data: makelist([i, i^2], i, 0, 5);
draw2d(points(data))$
以下のように,$x$ 座標のみの数値データ,$y$ 座標のみの数値データをプロットしてもよいです。
X: makelist(i, i, 0, 5);
Y: makelist(i**2, i, 0, 5);
オプションを設定して,各点を線でつないで draw する例。
ここでは,points_joined = true
を設定して線でつないで描きます。オプションには, point_type
,point_size
, color
などを設定できます。
/* オプションの設定例 */
draw2d(
/* 表示範囲 */
xrange = [-0.2, 5.2], yrange = [0, 28],
/* 点を塗りつぶした丸に */
point_type = 7,
/* 点の大きさ,色 */
point_size = 1, color = purple,
/* 線でつなぐ */
points_joined = true,
/* x 座標のみのリスト, y 座標のみのリスト */
points(X, Y)
)$
point_type
point_type
には以下の種類があります。
none (-1)
dot (0)
plus (1)
multiply (2)
asterisk (3)
square (4)
filled_square (5)
circle (6)
filled_circle (7)
up_triangle (8)
filled_up_triangle (9)
down_triangle (10)
filled_down_triangle (11)
diamant (12)
filled_diamant (13)
ベクトルを描く
原点を始点とし,$v_x = 0.5, v_y = 1$ のベクトルを描きます。
/* head オプションを指定しないと変なベクトルになるかも */
draw2d(
/* ベクトルの矢の設定 */
head_length = 0.1, head_angle = 20,
vector([0, 0], [0.5, 1])
)$
/* オプションの設定例 */
draw2d(
/* 表示範囲 */
xrange = [-2, 2], yrange = [-2, 2],
/* 縦横比。*/
proportional_axes = xy,
/* x 軸 y 軸,グリッドの表示 */
xaxis = true, yaxis = true, grid = true,
/* ベクトルの矢の設定 */
head_length = 0.2, head_angle = 20,
/* 線の太さ */
line_width = 2,
vector([0, 0], [0.5, 1])
)$
複数のベクトルやベクトル場などを描く例。
x(t):= t$
y(t):= t-0.25*t**2$
vx(t):= 0.5$
vy(t):= 0.5-0.25*t$
vecV:
makelist(
vector([x(t), y(t)], [vx(t), vy(t)]), t, 0, 4)$
for v in vecV do(print(v))$
/* 以下のように vecV は 5本のベクトルのリストになっている */
draw2d(
xrange = [-0.5, 4.5], yrange = [-0.5, 2],
proportional_axes=xy,
xaxis = true, yaxis = true, grid = true,
/* y 軸の目盛を 1 ごとに */
ytics = 1,
head_length = 0.1, head_angle = 20,
line_width = 2,
vecV
)$
さらには以下のようなベクトル場のグラフも描くことができます。参考までに。
複数のグラフを重ねて表示
複数のグラフを重ねて表示する例を示します。
$y = x^2 – 1$ と $y = 4 x – 5$ の 2つの陽関数のグラフを重ねて描きます。
draw2d(
explicit(x**2 - 1, x, -5, 5),
explicit(4*x - 5, x, -5, 5)
)$
plot2d()
の場合と違い,自動で色を変えてはくれません。いくつかオプションを設定して描く例です。それぞれの関数を explicit()
で描く直前に,それぞれのオプションを指定します。
/* オプションの設定例 */
draw2d(
/* 表示範囲 */
xrange = [-5, 5], yrange = [-5, 10],
xaxis = true, yaxis = true,
/* 凡例の位置 */
user_preamble = "set key bottom",
color = 1,
line_width = 3,
key = "x^2 - 1",
explicit(x**2 - 1, x, -5, 5),
color = 2,
line_width = 1,
key = "4 x - 5",
explicit(4*x - 5, x, 1, 3)
/* x の範囲も別個に設定可能 */
)$
数値データファイルを読み込む
Maxima では,あらかじめ作成された数値データファイルを読み込んでグラフを描くこともできます。
/* 読み込むデータファイルを作成しておく */
tmp: makelist([i, i^2], i, 0, 5)$
write_data(tmp, "data.txt")$
データファイルを読み込む Maxima の関数は,read_nested_list
を使います。
dat: read_nested_list("data.txt");
リスト dat
に読み込んだ数値データをグラフにします。
/* オプションの設定例 */
draw2d(
/* 表示範囲 */
xrange = [0, 6], yrange = [0, 28],
user_preamble = "set key top left",
point_type = 7,
point_size = 1,
key = "データ",
points(dat)
)$
数値データと理論曲線を重ねて表示
前節の数値データファイル test.dat
と理論曲線 $y = x^2$ の 2 つのグラフを重ねて表示してみます。
draw2d(
user_preamble = "set key top left",
/* 数値データを点で */
point_type = 7,
point_size = 1,
color = 1,
key = "データ",
points(dat),
/* 曲線を陽関数で */
color = 2,
key = "理論曲線 y = x^2",
explicit(x**2, x, 0, 5)
)$
海王星と冥王星の軌道
焦点を原点とした楕円のグラフ
太陽からの万有引力を受けて運動する惑星は,太陽(二体問題では質量中心)を焦点の一つとした楕円運動を描いて運動します。
焦点の一つを原点とし,長半径 $a$,離心率 $e$ の楕円の方程式は,極座標 $r$,$\varphi$ を使って以下のように表すことができます。
$$ r= \frac{a (1−e^2)}{ 1 + e\cos\varphi}$$
さて,かつては第9惑星,現在では準惑星の一つである冥王星も楕円軌道を描きます。冥王星の軌道長半径 $𝑎_P=39.445 \mbox{au}$,離心率 $𝑒_P=0.250$
を使って冥王星の軌道を描きます。
まず,極座標表示の楕円の式を関数として定義します。
r(a, e, phi):= a*(1-e^2)/(1+e*cos(phi));
x(a, e, phi):= r(a, e, phi)*cos(phi);
y(a, e, phi):= r(a, e, phi)*sin(phi);
媒介変数表示でプロット
冥王星の軌道長半径と離心率を入れて,媒介変数表示でプロットしてみます。
aP: 39.445$
eP: 0.250$
draw2d(
/* 滑らかにするためにサンプリングを多めに */
nticks = 200,
/* 縦横比。*/
proportional_axes = xy,
/* 表示範囲 */
xrange = [-50, 50], yrange = [-50, 50],
/* x 軸 y 軸の表示 */
xaxis = true, yaxis = true,
key = "冥王星",
parametric(x(aP, eP, phi), y(aP, eP, phi), phi, 0, 2*%pi)
)$
では,この冥王星の軌道と,その内側をまわる海王星の軌道を重ねて描いてみましょう。
海王星の軌道長半径は $a_N=30.181 \mbox{au}$,離心率は $e_N=0.0097$ と小さいので簡単のために $e_N=0$ として扱います。
実際の2つの天体の軌道は同じ平面上にありませんが,太陽からの距離のみをみるために,ここでは同一平面上に描きます。
aN: 30.181$
eN: 0$
draw2d(
/* 滑らかにするためにサンプリングを多めに */
nticks = 200,
/* 縦横比。*/
proportional_axes = xy,
/* 表示範囲 */
xrange = [-50, 50], yrange = [-50, 50],
/* x 軸 y 軸の表示 */
xaxis = true, yaxis = true,
key = "冥王星",
color = blue,
parametric(x(aP, eP, phi), y(aP, eP, phi), phi, 0, 2*%pi),
key = "海王星",
color = red,
parametric(x(aN, eN, phi), y(aN, eN, phi), phi, 0, 2*%pi)
)$
参考:極座標表示でプロット
極座標表示でプロットする例。
draw2d(
nticks = 200,
proportional_axes = xy,
xrange = [-60, 60], yrange = [-40, 40],
xaxis = true, yaxis = true,
color = 1, key = "冥王星",
polar(r(aP, eP, phi), phi, 0, 2*%pi),
color = 2, key = "海王星",
polar(r(aN, eN, phi), phi, 0, 2*%pi)
)$
月別平年気温の関数フィット
弘前市の月別平年気温のデータを使ってリスト HiroT
を作ります。
HiroT: [
[1, -1.5],
[2, -1.0],
[3, 2.3],
[4, 8.6],
[5, 14.3],
[6, 18.3],
[7, 22.3],
[8, 23.5],
[9, 19.4],
[10, 12.9],
[11, 6.5],
[12, 0.8]
];
このデータをグラフに描いてみます。
draw2d(
point_type = 7, point_size = 1,
points(HiroT)
)$
グラフを見ると,月別平年気温は 12 ヶ月周期の三角関数でフィットできるようにみえます。
では,以下のように関数フィットをしてみましょう。
まず,最小二乗法のパッケージ lsquares
をロードします.これは lsquares_estimates
を 初めて使う際,最初に 1 回だけ行えばよいです。
load(lsquares)$
次に,以下のような関数を定義して,最小二乗法でパラメータ a, b, c
を求めます。
$$f(x) = a + b \sin\left(\frac{2\pi}{12}\right)+ c \cos\left(\frac{2\pi}{12}\right)$$
f(x):= a + b*sin(%pi*x/6)+ c*cos(%pi*x/6);
最小二乗法を行う関数 lsquares_estimates
には数値データを行列として入れてやる必要があります。
このために apply('matrix, HiroT)
でリスト HiroT
を行列に変換しています。
/* 以後の少数表示は 5 桁くらいで... */
fpprintprec: 5$
/* 元に戻すには fpprintprec: 0$ */
lsquares_estimates(
apply('matrix, HiroT), [x, y], y=f(x), [a, b, c]
)$
float(%);
最小二乗法によって求めた a, b, c
の値を f(x)
に代入して fit
とし,数値データと合わせて,この関数のグラフも描きます。
fit: ev(f(x), %);
draw2d(
xrange = [0.8, 12.2], yrange = [-5, 28],
xaxis = true, yaxis = true,
user_preamble = "set xtics 1",
xlabel = "月",
ylabel = "°C",
title = "弘前市の月別平年気温",
color = 1, key = "月別平年気温",
point_type = 7, point_size = 0.6,
points(HiroT),
color = 2, key = "関数フィット",
explicit(fit, x, 1, 12)
)$
領域の塗りつぶし
$y = f(x)$ と $y = g(x)$ ($f(x) \geq g(x)$)で囲まれた領域を塗りつぶす例。
f(x):= 0.6*x + 0.4*cos(x)$
g(x):= 0$
draw2d(
xrange = [-0, 2.5], yrange = [-0.2,1.5],
xaxis = true,
/* 塗りつぶす色の指定。*/
fill_color = yellow,
/* 上の線。*/
filled_func = f(x),
/* 下の線と範囲の指定。*/
explicit(g(x), x, 0.5, 2),
/* 塗り潰し終了 */
filled_func = false,
/* あらためて y = f(x) を描く */
color = blue,
line_width = 2,
explicit(f(x), x, 0.25, 2.25)
)$