算額(その8)
円の内部に大きさの異なる 5 種類の円がある。それぞれは互いに接している。
円の半径を求めよ。
山形県新庄市神明町 総鎮守天満宮 文政元年7月(現在は戸沢神社にあり)
http://www.wasan.jp/yamagata/tozawa.html
なお,算額には上半分の図が描かれているが,ここでは下半分も描くことにする。
外側の円の半径を 2 とする。内側の一番大きい円の半径は r1 で,以下 r2, r3, r4, r5 とする。
それぞれの円の中心座標を (0, 1), (x2, r2), (x3, y3), (x4, y4), (x5, y5) とする。
互いに接することから以下の 11 本の方程式を立てる。
using SymPy
@syms r2::positive, r3::positive, r4::positive, r5::positive
@syms x2::positive, x3::positive, x4::positive, x5::positive
@syms y3::positive, y4::positive, y5::positive
eq1 = x3^2 + (y3 - 1)^2 - (1 + r3)^2;
eq2 = x5^2 + (y5 - 1)^2 - (1 + r5)^2;
eq3 = x2^2 + (1 - r2)^2 - (1 + r2)^2;
eq4 = x2^2 + r2^2 - (2 - r2)^2;
eq5 = x4^2 + y4^2 - (2 - r4)^2;
eq6 = x3^2 + y3^2 - (2 - r3)^2;
eq7 = (x4 - x5)^2 + (y4 - y5)^2 - (r4 + r5)^2;
eq8 = (x4 - x3)^2 + (y3 - y4)^2 - (r3 + r4)^2;
eq9 = (x2 - x4)^2 + (y4 - r2)^2 - (r2 + r4)^2;
eq10 = (x2 - x5)^2 + (y5 - r2)^2 - (r2 + r5)^2;
eq11 = (x3 - x5)^2 + (y3 - y5)^2 - (r3 + r5)^2;
未知数が 11 個で,方程式が 11 本なので,理論的には解けるが,SymPy の solve では時間ばかりかかって一向に解が求まらない。
eq9 と eq11 を図と見比べると,x2 = x4, x3 = x5 であることがわかる。未知数の個数は変わらないが式の数を増やす。
eq12 = x2 - x4;
eq13 = x3 - x5;
solve([eq1, eq2, eq3, eq4, eq5, eq6, eq7, eq8, eq9, eq10, eq11, eq12, eq13], (r2, r3, r4, r5, x2, x3, x4, x5, y3, y4, y5))
解が求まった。
1-element Vector{NTuple{11, Sym}}:
(1/2, 1/5, 1/6, 2/15, sqrt(2), 4*sqrt(2)/5, sqrt(2), 4*sqrt(2)/5, 7/5, 7/6, 16/15)
using Plots
function circle(ox, oy, r, color=:red)
θ = 0:0.01:2pi
x = r.*cos.(θ)
y = r.*sin.(θ)
plot!(ox .+ x, oy .+ y, color=color)
end;
function point(x, y, string="", position=:left, vertical=:center)
scatter!([x], [y])
annotate!(x, y, text(string, 10, position))
end;
function circle2(x, y, r, color)
circle( x, y, r, color)
circle( x, -y, r, color)
circle(-x, y, r, color)
circle(-x, -y, r, color)
end
function draw(more=false)
pyplot(size=(500, 500), aspectratio=1, label="", fontfamily="IPAMincho")
(r2, r3, r4, r5, x2, x3, x4, x5, y3, y4, y5) = (1/2, 1/5, 1/6, 2/15, sqrt(2), 4*sqrt(2)/5, sqrt(2), 4*sqrt(2)/5, 7/5, 7/6, 16/15)
plot()
circle(0, 0, 2)
circle(0, 1, 1, :blue)
circle(0, -1, 1, :blue)
circle2(x2, r2, r2, :green)
circle2(x3, y3, r3, :magenta)
circle2(x4, y4, r4, :brown)
circle2(x5, y5, r5, :black)
end;
draw()
savefig("fig.png")
なお,数値的に解を求めることもできる。
この場合は,方程式は 11 本でよい。
# import Pkg; Pkg.add("NLsolve")
using NLsolve
function nls(func, params...; ini = [0.0])
if typeof(ini) <: Number
r = nlsolve((vout,vin)->vout[1]=func(vin[1],params...), [ini])
v = r.zero[1]
else
r = nlsolve((vout,vin)->vout .= func(vin,params...), ini)
v = r.zero
end
return v, r.f_converged
end;
function h(u)
r2, r3, r4, r5, x2, x3, x4, x5, y3, y4, y5 = u
return [
x3^2 + (y3 - 1)^2 - (1 + r3)^2,
x5^2 + (y5 - 1)^2 - (1 + r5)^2,
x2^2 + (1 - r2)^2 - (1 + r2)^2,
x2^2 + r2^2 - (2 - r2)^2,
x4^2 + y4^2 - (2 - r4)^2,
x3^2 + y3^2 - (2 - r3)^2,
(x4 - x5)^2 + (y4 - y5)^2 - (r4 + r5)^2,
(x4 - x3)^2 + (y3 - y4)^2 - (r3 + r4)^2,
(x2 - x4)^2 + (y4 - r2)^2 - (r2 + r4)^2,
(x2 - x5)^2 + (y5 - r2)^2 - (r2 + r5)^2,
(x3 - x5)^2 + (y3 - y5)^2 - (r3 + r5)^2
]
end;
iniv = [0.525, 0.225, 0.175, 0.125, 1.45, 1.175, 1.45, 1.025, 1.45, 1.2, 1.1] # 初期値
nls(h, ini=iniv)
([0.4999999999999999, 0.19999999995440246, 0.16666666671681116, 0.13333333457600596, 1.4142135623730967, 1.1313708498182247, 1.414213562263483, 1.1313708505474644, 1.4000000001367925, 1.166666666725507, 1.0666666672577463], true)