#!/usr/bin/env python
# coding: utf-8
# # 『なにわ十六橋智恵の渡り』には「オイラー閉路」が存在する。('24.06.06)
# ## 「保古帖」(甲雑-58)巻19収録の「なにわ十六橋智恵の渡り」
#
# 昨日は、[『なには八ツ橋智恵の渡り』](https://hirax.github.io/wow/html/day_240605_graph_naniwa.html)を、単純な「ケーニヒスベルグの橋の問題」として解いてみた。
# つまり、「すべての橋を1度だけ渡り、同じ場所に戻ってくることができるか」という、ケーニヒスベルグの橋の問題として解いてみた。
#
# 「保古帖」(甲雑-58)巻19には、「なにわ十六橋智恵の渡り」という、同様の問題が収録されている。
# そこで、今日は、「なにわ十六橋智恵の渡り」を、やはり単純な※ケーニヒスベルグの橋の問題として解いてみようと思う。
#
# ※「単純な」という言葉の意味については、後述しようと思う。
#
# %
# ```{figure} ./images/day_240606_graphx_naniwa_16.jpeg
# ---
# height: 12cm
# ---
# 「なにわ十六橋智恵の渡り」
# ```
#
# ## 「なにわ十六橋智恵の渡り」は一筆書き可能
#
# 「なにわ十六橋智恵の渡り」は、少し見づらいのだけれど、題目通りに16の橋がある。
# 一見すると、14橋しかないように見えるが、島内部にある橋がひとつ、折り目に重なる橋がひとつあり、合計で16の橋がある。
# そして、橋で繋がれた島は、合計7つある。
# 島内部にある橋は、「ケーニヒスベルグの橋の問題」としては存在を無視して良い。
# したがって、「なにわ十六橋智恵の渡り」はこういう問題だ。
# 「7つの頂点間を結ぶ15の辺を、ちょうど1度だけ通るオイラー閉路が存在するか?」
#
# まずは、「なにわ十六橋智恵の渡り」を表現する、グラフ構造を作ってみよう。
# 下記では、同一頂点に戻る一辺を含む「7つの頂点間を結ぶ16の辺」を作っているが、「ケーニヒスベルグの橋の問題」としては、「7つの頂点間を結ぶ15の辺」と扱っても構わない。
# In[18]:
import numpy as np
import networkx as nx
# c.f. https://medium.com/@victorialandaberry/solving-the-konigsberg-bridge-problem-with-python-914f9f51bb8e
g = nx.MultiGraph() #create an empto Multigraph named G
#add nodes one by one
g.add_node("難波A")
g.add_node("難波B")
g.add_node("難波C")
g.add_node("難波D")
g.add_node("難波E")
g.add_node("難波F")
g.add_node("難波G")
#add edges
g.add_edge("難波A", "難波B")
g.add_edge("難波A", "難波B")
g.add_edge("難波A", "難波D")
g.add_edge("難波A", "難波D")
g.add_edge("難波B", "難波C")
g.add_edge("難波B", "難波F")
g.add_edge("難波B", "難波B")
g.add_edge("難波C", "難波G")
g.add_edge("難波D", "難波E")
g.add_edge("難波D", "難波F")
g.add_edge("難波D", "難波F")
g.add_edge("難波D", "難波F")
g.add_edge("難波E", "難波F")
g.add_edge("難波F", "難波G")
g.add_edge("難波F", "難波G")
g.add_edge("難波F", "難波G")
print("島の数", g.number_of_nodes())
print("橋の数", g.number_of_edges())
from IPython.display import display,SVG
def draw(graph):
svg = nx.nx_agraph.to_agraph(graph).draw(prog='dot',format='svg')
display(SVG(svg))
draw(g)
# %
# ```{figure} ./images/day_240606_graphx_naniwa_graph.png
# ---
# height: 9cm
# ---
# 「なにわ十六橋智恵の渡り」のグラフ構造
# ```
# そして、オイラー閉路が存在するかどうかを判定する、昨日書いたコードを実行してみる。
# すると、「一筆書き経路で元の場所に戻ることができます」という結果が得られる。
# つまり、すべての島=頂点に繋がる橋=辺は偶数なので、「なにわ十六橋智恵の渡り」には「オイラー閉路が存在する」というのが答えだ。
# In[19]:
def eulerpath(graph):
odd=0
a=list(graph.degree(graph.nodes()))
for i in a:
if (i[1] % 2) != 0:
odd+=1
if odd>0:
print("一筆書き経路で元の場所に戻ることはできません。")
else:
print("一筆書き経路で元の場所に戻ることができます。")
eulerpath(g)
# ## 一筆書き経路(オイラー閉路)を計算してみる。
#
# 一筆書き経路(オイラー閉路)が存在するとわかれば、その経路を計算するのは簡単だ。
# 島や橋の数が多ければ計算時間は掛かるけれど、今回の「なにわ十六橋智恵の渡り」くらいの計算量であれば、一瞬で経路例を作り出すことができる。
# In[20]:
for (u,v) in list(nx.eulerian_circuit(g)):
print(u,'から',v,'に渡る。')
# ## 「なにわ十六橋智恵の渡り」の舞台「中之島」あたりを眺めてみる
#
# 「ケーニヒスベルグの橋の問題」が、現実の町に存在する島や橋を題材にしたように、大阪を舞台とした「ケーニヒスベルグの橋の問題」も、実際の町を踏まえた観光計算問題だ。
# ちなみに、「なにわ十六橋智恵の渡り」の舞台は中之島あたりである。
# 東西南北の方向は異なるが、現在の地図を貼り付けてみると、下のような具合だ。
#
# %
# ```{figure} ./images/day_240606_graphx_naniwa_.png
# ---
# height: 9cm
# ---
# 「なにわ十六橋智恵の渡り」の舞台となった場所(現在)
# ```
#
# ## 和算の「橋渡り問題」はまだ続く
#
# 『浪華二十八橋智慧渡』や『なには八ツ橋智恵の渡り』あるいは『なにわ十六橋智恵の渡り』といった具合で、和算書物などに登場する「大阪、水の都での橋渡り問題」は多い。
# 古地図と和算の出題図を眺めながら、大阪の町を歩いてみるのも面白いかもしれない。
# In[ ]: