裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

算額(その382)

2023年08月11日 | Julia

算額(その382)

東京都渋谷区 金王八幡宮(金王八幡神社) 嘉永3年(1850)
https://www.naruto-u.ac.jp/journal/info-edu/j05006.pdf

二十八宿のうち15宿の名前をつけた円がある。角と亢の円周の和が16寸,心,尾,箕の円周の和が30寸,虚,危,室,壁,奎 の周の和が63寸であるとき,角の円周を求めよ。


答は 7 寸 7 分 6 厘 3 毛 3 糸 2 忽 1 微と残りは微少数(7.763321...)である。

include("julia-source.txt");

using Plots

function draw()
   pyplot(size=(500, 500), grid=false, aspectratio=1, label="", fontfamily="IPAMincho")
   f(n) = -69//10960*n^2 + 1079//2192*n + 997//137
   names = ["角", "亢", "氐", "房", "心", "尾", "箕", "斗", "牛", "女", "虚", "危", "室", "壁", "奎"]
   plot()
   for (i, name) in enumerate(names)
       point(i, 1, name, :blue, :center, mark=false)
       circle(i, 0, f(i)/30)
   end
   plot!(showaxis=false)
end;

金王八幡宮といえば,冲方丁の「天地明察」にも出てくる。その中に,この問題を参考にしたと思われる算額問題がある。これについては,末尾に記す。

15宿の名前を順番に書いておく。角が一番小さく,奎が一番大きい。
角,亢,氐,房,心,尾,箕,斗,牛,女,虚,危,室,壁,奎

天文(学)に,しかも昔の天文(学)に興味がなければ,読み方も分かりづらいので,この算額の題意を,現代数学風に書き下す。

数列 a[n], n = 1, 2, ..., 15 がある。
a[i] < a[i+1], i = 1, 2, ..., 14 である。
a[1] + a[2] = 16
a[5] + a[6] + a[7] = 30
a[11] + a[12] + a[13] + a[14] + a[15] = 63
がわかっているとき,a[1] を求めよ。

等差数列ではなさそうだが,次に簡単な形式の数列といえば a[n] = p×n^2 + q×n + r であろうか。

第1の条件 a[1] + a[2] = 16 は
(p×1^2 + q×1 + r) + (p×2^2 + q×2 + r)
= 5p + 3q + 2r
のようになる。
2, 3 番目の条件における p, q, r の係数を求める。

using SymPy

function coef(s, e)
   coef2 = coef1 = coef0 = 0
   for n in s:e
       coef2 += n^2
       coef1 += n
       coef0 += 1
   end
   return (coef2, coef1, coef0)
end

coef(1, 2) |> println
coef(5, 7) |> println
coef(11, 15) |> println

   (5, 3, 2)
   (110, 18, 3)
   (855, 65, 5)

以下の3元連立方程式を解けばよい。

@syms p, q, r
eq1 = 5p + 3q + 2r - 16
eq2 = 110p + 18q + 3r - 30
eq3 = 855p + 65q + 5r - 63
res = solve([eq1, eq2, eq3], (p, q, r))

   Dict{Any, Any} with 3 entries:
     p => -69/10960
     q => 1079/2192
     r => 997/137

分数形式を小数点付きで表す。

res[p].evalf(), res[q].evalf(), res[r].evalf()

   (-0.00629562043795620, 0.492244525547445, 7.27737226277372)

a[1] は 1^2p + 1q + r なので,7.76332116788321 が答えである。

(res[p] + res[q] + res[r]).evalf() |> println

   7.76332116788321

行列演算で行うならば,以下のようにする。

A = Sym[5 3 2; 110 18 3; 855 65 5]
b = [16, 30, 63];

pqr = A \ [16.0, 30, 63]
pqr |> println

   Sym[-0.00629562043795620, 0.492244525547445, 7.27737226277372]

pqr' * [1;1;1] |> println

   7.76332116788321

演算子 \ は Julia 特有のものなので,一般言語的には以下のようにする。

inv(A) * b |> println

   Sym[-69/10960, 1079/2192, 997/137]

---------------------------------

さて,冲方丁の天地明察に出てくる問題である。
冲方 丁. 天地明察(特別合本版) (Japanese Edition) (p.237). Kindle 版. 

『今、図の如く、大小の十四宿の星の名を持つ円が並んでいる。角星と亢星の周の長さを足すと九寸である。また房星と心星と尾星の周の長さを足すと十八寸である。さらに女星、虚星、危星、室星、壁星の五つの星の周の長さを足すと四十五寸である。角星の周の長さは何寸であるか問う』

変更点は以下の通り。

- 15宿から14宿に縮小された
- 条件数は変わらず3個であるが,係数行列と定数ベクトルは異なる
- 2 番目の条件式で,金王八幡宮のものは「心,尾,箕の円周の和」であるが天地明察のものでは「房星と心星と尾星の周の長さを足す」となっている
- p*n^2+q*n+r だが,(結果的に)p = 0 である。つまり,簡単な階差数列である

coef(1, 2) |> println
coef(4, 6) |> println
coef(10, 14) |> println


   (5, 3, 2)
   (77, 15, 3)
   (730, 60, 5)

以下の3元連立方程式を解けばよい。

@syms p, q, r
eq1 = 5p + 3q + 2r - 9
eq2 = 77p + 15q + 3r - 18
eq3 = 730p + 60q + 5r - 45

$730 p + 60 q + 5 r - 45$

res = solve([eq1, eq2, eq3])

   Dict{Any, Any} with 3 entries:
     p => 0
     q => 3/7
     r => 27/7

分数形式を小数点付きで表す。なお,p = 0 なので,一般項は
a[n] = 27//7 + 3/7*n
つまり,階差数列である。これを村瀬は「……招差術か」と言っている。

res[p].evalf(), res[q].evalf(), res[r].evalf()

   (0, 0.428571428571429, 3.85714285714286)

a[1] は 1^2p + 1q + r なので,7.76332116788321 が答えである。

res[r] + res[q]

   30/7

1^2*res[p] + 1*res[q] + 1*res[r] |> println

   30/7

因縁の "30/7" が出てきた。

一般項 a(n) を求める関数を定義しておこう。

func_a(n) = (3n + 27)//7;

for i in 1:14
   println("func_a($i) = $(func_a(i))")
end

   func_a(1) = 30//7
   func_a(2) = 33//7
   func_a(3) = 36//7
   func_a(4) = 39//7
   func_a(5) = 6//1
   func_a(6) = 45//7
   func_a(7) = 48//7
   func_a(8) = 51//7
   func_a(9) = 54//7
   func_a(10) = 57//7
   func_a(11) = 60//7
   func_a(12) = 9//1
   func_a(13) = 66//7
   func_a(14) = 69//7

func_a(1) + func_a(2)

   9//1

func_a(4) + func_a(5) + func_a(6)

   18//1

func_a(10) + func_a(11) + func_a(12) + func_a(13) + func_a(14)

   45//1

角星の周の長さは 30/7

func_a(1) |> println

   30//7

行列演算で行うならば,以下のようにする。

A = Sym[5 3 2; 77 15 3; 730 60 5]
b = [9, 18, 45];

A, b

   (Sym[5 3 2; 77 15 3; 730 60 5], [9, 18, 45])

pqr = A \ [9, 18, 45]
pqr |> println

   Sym[0, 3/7, 27/7]

pqr' * [1;1;1] |> println

   30/7

演算子 \ は Julia 特有のものなので,一般言語的には以下のようにする。

inv(A) * b |> println

   Sym[0, 3/7, 27/7]

---

なお,この数列の問題は,初版本(単行本)では解答不能ではないものの,なぜこのような答えになる問題を出したのかという状態であった。

236ページ
『今、図の如く、大小の十五宿の星の名を持つ円が並んでいる。角星と亢星の周の長さを足すと十寸である。また心星と尾星と箕星の周の長さを足すと二十七寸五分である。さらに虚星、危星、室星、壁星、奎星の五つの星の周の長さを足すと四十寸である。角星の周の長さは何寸であるか問う』

角星 + 亢星 = 10寸
心星 + 尾星 + 箕星 = 27寸5分
虚星 + 危星 + 室星 + 壁星 + 奎星 = 40寸

using SymPy

A = Sym[5 3 2; 110 18 3; 855 65 5]
b = [10, 27.5, 40];
pqr = A\b
pqr |> println

   Sym[-0.0942062043795621, 1.64119525547445, 2.77372262773723]

g(n) = -0.0942062043795621*n^2 + 1.64119525547445*n + 2.77372262773723

using SymPy
solve(diff(g))

   8.71065375302662

g(7), g(8), g(9), g(10)

   (9.645985401459837, 9.874087591240855, 9.91377737226275, 9.765054744525518)

9 番目が最大でそれ以降では減少する。そういう意味では,この問題は「無術」なのであろう。

角星の周の長さは 4.32071167883212 ということになる。

pqr' * [1;1;1]

   4.32071167883212

しかし,この数値も特段の意味を持つものではないようだ。

ということで,改訂版(電子版)では著者の意図したように問題(の数値)が変更された

 

 


コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 算額(その381) | トップ | 算額(その383) »
最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。

Julia」カテゴリの最新記事