(その1/3) https://qiita.com/mrrclb48z/items/26b3d7ad1bdd88672a3e
(その2/3) https://qiita.com/mrrclb48z/items/356e664fce56d960d7a3
・会話→sympyのソースコード
・ChatGPT先生へお願いしました。Gemini先生だと覚えているカモ。
・私は何が何だかわからなくなってきました。
(本日の)ChatGPT先生へ。
以下の会話をsympyのソースコードに変換して、計算結果をmarkdown の背景黒で。
# 幾何構造と代数変換による厳密座標計算プログラムの解説
太郎:「ねえ花子さん、このPythonコード、何をしているプログラムか読み解いてみない?」
花子:「いいわね。コメントによると、ver1.1の幾何構造とver1.2の代数変換を組み合わせて、図形の正確な座標を計算しているみたいよ。」
太郎:「そうだね。最初のほうでは、Pythonの数式処理ライブラリである sympy をインポートして、t と DB を正の代数変数として定義しているんだ。」
花子:「t は tan(theta) を表していて、DB はそのまま線分DBの長さを表しているわね。既知の長さとして CD = 2, DA = 3 が設定されているわ。」
太郎:「そのあと、2つの方程式 eq1 と eq2 を立てているね。eq1 は tan(2*theta) = DB / DA から導かれる式で、コードでは 2*t / (1 - t**2) = DB / 3 と表現されているよ。」
花子:「eq2 は tan(theta) = CD / DB だから、t = 2 / DB になっているわね。この2つは三角関数の性質を使った連立方程式よ。」
太郎:「なるほど! solve関数を使って、この連立方程式から t と DB の厳密解を求めて、db_val に DB の値を取り出しているわけだ。」
花子:「そして、SymPyの Point クラスを使って、それぞれの点の座標を定義しているわ。Cは原点 (0, 0)、Dは (CD, 0) だから (2, 0)、Aは (CD + DA, 0) で (5, 0) になるね。」
太郎:「Bの座標は (CD, db_val) になっているから、x座標が2で、y座標がさっき求めた db_val になるんだね。」
花子:「その下のループでは、定義した点 A, B, C, D の名前と座標の引数を出力しているわ。」
太郎:「最後の自作部分では、B.distance(C) を使って点Bと点Cの間の距離を計算して、出力しているね。コメントアウトされた値を見ると、最終的に 2*sqrt(5) になることが確かめられる仕組みだ。」
花子:「幾何学的な条件を数式としてコンピュータに正確に解かせて、座標をバッチリ求められるスマートなコードね!」
実行結果
```python
from sympy import *
from sympy.geometry import Point
# ============================================================
# 幾何構造と代数変換による厳密座標計算
# ============================================================
# 代数変数
# t = tan(theta)
# DB = 線分DBの長さ
t, DB = symbols('t DB', positive=True)
# 既知の長さ
CD = 2
DA = 3
# ------------------------------------------------------------
# 連立方程式
# ------------------------------------------------------------
# tan(2θ) = DB / DA
# tan(2θ) = 2*t / (1 - t**2)
eq1 = Eq(
2*t / (1 - t**2),
DB / DA
)
# tan(θ) = CD / DB
eq2 = Eq(
t,
CD / DB
)
# ------------------------------------------------------------
# t と DB を厳密に求める
# ------------------------------------------------------------
sol = solve([eq1, eq2], [t, DB], dict=True)[0]
t_val = simplify(sol[t])
db_val = simplify(sol[DB])
# ------------------------------------------------------------
# 各点の座標
# ------------------------------------------------------------
# C = (0, 0)
C = Point(0, 0)
# D = (CD, 0)
D = Point(CD, 0)
# A = (CD + DA, 0)
A = Point(CD + DA, 0)
# B = (CD, DB)
B = Point(CD, db_val)
# ------------------------------------------------------------
# 座標を表示
# ------------------------------------------------------------
for name, point in [
("A", A),
("B", B),
("C", C),
("D", D)
]:
print(f"{name} = {point}")
# ------------------------------------------------------------
# BC の長さ
# ------------------------------------------------------------
BC = simplify(B.distance(C))
print("t =", t_val)
print("DB =", db_val)
print("BC =", BC)
計算結果
A = Point2D(5, 0)
B = Point2D(2, 4)
C = Point2D(0, 0)
D = Point2D(2, 0)
t = 1/2
DB = 4
BC = 2*sqrt(5)
したがって
tan(θ) = 1/2
DB = 4
A = (5, 0)
B = (2, 4)
C = (0, 0)
D = (2, 0)
BC = 2√5
特に B.distance(C) もSymPyが厳密計算するので、
BC = √(2² + 4²)
= √20
= 2√5
となり、会話中の「最終的に 2*sqrt(5)」という確認まで一致します。