最長片道きっぷの経路を求める
[付録3-1] 2005年4月版(数式編)

「付録3」のあらまし

 この「付録3」は、 最長片道きっぷの経路を求める方法を記した「本編」に付随するもので、 「これまでに得られた数学的な知見をまとめる」 「無料で利用できるソフトウェアだけで最長経路を求める」というのが内容の2本柱です。

 2005年春、特に最長経路に変化があったわけではありません。しかし LOP を取り巻く状況は着実に変わりつつあります。
 無料で利用できる整数計画ソルバーの性能が格段に上がったうえ、 PC自体の性能も着実に上がっています。さらに LOP 研究者の性能も上が…ったかどうかは分かりませんが、 長いこと数式をにらんでいると新たな発見もあるもので、 制約式の面でも多少の進歩がありました。これらの進歩により、 商用のソルバーを利用できない環境でも、 JR全線を対象とした最長経路を計算することが現実的になってきました
 そこで、この「付録3」では、まず制約式の改善(あるいは、 これまで説明していなかった事項)についてまとめます。 次に、無料で利用できるソフトウェアだけで最長経路を求める方法について説明し、 興味のある人が自ら最長経路を計算できるような環境を提供します。

おことわり:この文書の前提条件

 この文書は、「本編」をすでに読み、 それなりに理解していることを前提にしています。
 必要なソフトウェアをインストールして、 出来合いのデータで最長経路の計算を追体験するだけなら、 制約式に関して理解していなくても何とかなります。 が、それでは単なる「体験」で終わってしまい、 自分の思いどおりに「計算」することはできません。
 もし、「○○という条件で最長経路を求めてみたい」といった目標があるのであれば、 少々取っつきにくい見かけではありますが、ぜひ、 制約式の理解に努めてほしいと思います。 整数計画法自体について深く理解することは難しいかもしれませんが (私も表面的にしか理解していません)、 こうした問題を解くためのツールだと割り切れば、 パズル感覚で取り組めるはずです。


目次


タイプL以外の孤立ループ禁止法

 まず最初に、 2000年当時にすでに知っていながら今まで文書として公開していなかった、 「タイプL以外の孤立ループ禁止法」について説明します。

タイプLの手法はなぜタイプPに使えないか

 どのタイプにも共通の問題として、 整数計画法を用いて最長経路を求めようとすると、 「本筋」のルート(タイプLなら一本道、タイプPなら6の字)のほかに、 本筋と接点を持たない「孤立したループ」が含まれる可能性があります(詳しくは本編の「[2-3] 整数計画法で(制約式編) - 定式化は完全か?」を参照)。
 本編では、タイプLについて、この孤立したループを禁止する制約式を紹介しましたが、 タイプP(実際に解く場合には Pe、B、B8)では同じ制約式は使えません。 なぜなら、タイプPの経路は、それ自体がループを1つ含んでいるからです。
 たとえば、タイプPの最長経路を求めるとき、本筋の経路のほかに、p、q、r という3本の枝から成る孤立ループが解に含まれていたとします。 しかし、ここで「p、q、r の3本を同時に使うことはない」という制約式を追加すると、 真の最長経路の芽を摘んでしまう恐れがあります。 タイプPの最長経路にはループがちょうど1つ含まれていますが、 その1つのループが「pqr」かもしれないのです。

図A3-1図A3-1 Aのような解が出てきても、 右下の孤立ループを単純に禁止することはできません。 真の最長経路がBのようになる可能性があるからです。

 ピンとこない人は、p が「肥前山口→早岐」、q が「早岐→諫早」、r が「諫早→肥前山口」だと思ってください。p、q、r の3本を同時に使うとループになります。だから、問題を解く過程で pqr が孤立ループとして現れる可能性もあります。しかし、そこで「pqr 同時使用不可」という制約式を入れてしまったら、 「あの」最長経路は絶対に出てこなくなるのです。

孤立したループだけを除去するために

 この問題の解決法はいくつか考えられますが、今回紹介するのは、 以下で説明する「孤立したループだけを禁止する制約式」です。

 タイプPの経路の一部を形成するループと、単なるゴミの孤立ループ。 そのちがいは文字どおり「孤立しているか否か」です。 この「孤立している」という特徴を少し言いかえると、 「ループ上の駅から分岐する枝を1本も使っていない」ということができます。
 そこで、図 A3-2 のような「孤立したループ」が現れた場合、以下のような制約式 (A3-1) を加えることで、孤立したループだけを禁止します。 (参考までに、タイプLの場合に用いた、 「ループを禁止する制約式」を式 (A3-2) に示します。)

図A3-2図A3-2 孤立したループの例
ループ禁止制約式 for タイプP:
eab + ebc + eca − ea1 − ea2 − eb1 − ec1 ≦ 2 (A3-1)
ループ禁止制約式 for タイプL:
eab + ebc + eca ≦ 2 (A3-2)

 この「付録3」では、枝(=線路)を表す変数を「e123」、 頂点(=駅)を表す変数を「v456」と表記します。 それぞれ「edge(枝)」「vertex(頂点)」の頭文字です。
 以前は枝変数が「line」の頭文字をとって「l123」、 頂点変数が「station」の頭文字をとって「s456」だったのですが、 「l」が数字の「1」とまぎらわしいうえ、 筆者が「edge」「vertex」という言葉に慣れ、 制約式生成ツールなどもすべて「e」「v」で作ってしまったので、 今後はこの表記で統一したいと思います。 「付録2」以前の文書もそのうち書き換えたいと思いますが、 当面は「l→e」「s→v」と読み替えてください。

 タイプL用のループ除去制約式 (A3-2) に、マイナスのついている4変数を追加したのが式 (A3-1) です。eab、ebc、eca の3本をすべて使っても、ea1 や eb1 といった「ループ上から分岐する枝」を同時に使っていれば、 左辺は2以下になります(本物のタイプPはこれに該当します)。 逆に言うと、左辺が3以上になるのは「eab、ebc、eca の3本をすべて使い、なおかつ ea1、ea2、eb1、 ec1 の4本をどれも使わない場合」、つまり、A-B-C というループが他の経路から孤立している場合に限られます。
 上の例ではマイナスのついた枝変数は4つでしたが、 これが何個になるかは場合によります。 禁止したい孤立ループ上から分岐する枝をもれなく列挙し、 それらに対応する枝変数全部にマイナスをつけて制約式に加えないと、 解の厳密さを損ねます
 この制約式はタイプP一族(Pe、B、B8)のどれにでも適用できます。 タイプLでこの制約式を使っても(メリットはありませんが)問題ありません。

日=B≠8=P

 細かい話ですが、「日」形の外周をたどるような孤立ループが出てきた場合、 これを禁止するための制約式に「日」の真ん中を横切る枝を加えるかどうか、 という問題があります。たとえば図 A3-3 のような状況で、 「−eab」を制約式に加えるかどうか、ということです。

図A3-3図A3-3 「日」形の真ん中を横切る枝の取り扱いについて。 図の右側の経路はまっとうなタイプBの経路なので、 タイプBでは eab を考慮する必要があります。

 結論からいえば、タイプBでは「真ん中の枝」を加えることが必須です。「[2-3] 整数計画法で(制約式編) - タイプ Pn の定式化」に書いたとおり、 タイプBには「□_□」という一般的な形(ループ2つを1本線で結んだ形)のほか、 「日」形のものも含まれるので、孤立したループを禁止したい一方で、 それに枝を1本加えた「日」形は禁止してはいけないのです。
 いっぽう、タイプ Pe やタイプ B8 では「日」形の「真ん中の枝」を加える必要はありません。 その理由はタイプBの逆、すなわち「日」形の経路がタイプ Pe やタイプ B8 とは呼べない(ので、「日」形を禁止する制約式を加えてもかまわない)からです。
 ただ、「真ん中の枝」を制約式に加えることは、 加えない場合と比較すると制約を弱める方向にはたらくので、 「真ん中の枝」を加えた制約式をタイプ Pe やタイプ B8 に適用しても、厳密さを損ねることはありません(が、 計算時間が長くなるなどのデメリットはあるかもしれません)。


fork 変数の改良

 タイプ Pe・B・B8 では、「ある1駅に接続する枝を同時に3本使ってもよい、 しかしそれは全国で1回だけ」という制約を表現するために、新たな変数 fi を定義します(「f」は「fork」の意)。この「fork 変数」の定義を見直し、制約式の本数の削減を図りました。

 もともとの fi の定義については、「[2-3] 整数計画法で(制約式編) - タイプ Pe の定式化」に書いたとおりで、 3分岐の駅に対しては fork 変数を1つ、4分岐の駅に対しては(43=)4個、 5分岐なら(53=)10個…と、 多くの枝が出ている駅では多数の変数を定義しなければなりませんでした。 そのぶん制約式の数も増えます。
 このときは fork 変数 fi を0-1変数と定義していて、 そのために「枝数が増えると fork 変数の個数も増える」ということになったのですが、 あらためて考えてみると、fork 変数が2以上の値をとっても、 制約式を書くうえで問題はありません。
 そこで、fork 変数の定義を以下のように見直しました。式 (A3-3) は、駅 s から5本の枝 e1〜e5 が出ている場合の例です。

fs ≧ e1 + e2 + e3 + e4 + e5 − 2 (A3-3)
fs ≧ 0, fs は整数 (A3-4)

 新しい定義では、ある駅からどれだけ多くの枝が出ていようと、その駅に対する fork 変数は1つです。右辺は「出ている枝変数の合計−2」となります。 この駅 s から出ている枝を2本使うだけなら fs は0以上(の任意の整数)、同様に3本使うなら1以上、 4本使うなら2以上となります。より詳細に書くと表 A3-1 のとおりです。

表 A3-1 使用する枝の本数と fs のとりうる値の関係
駅 s から出る枝を
何本使うか
式 (A3-3) による
fs の下限
式 (A3-4) による
fs の下限
fs の下限
0本
(駅 s を通らない)
−2 0 0
1本
(駅 s は終端駅)
終端駅には fork 変数を定義しない
分岐駅では「1本だけ使用」はあり得ない
2本
(駅 s を1度通過)
0 0 0
3本
(駅 s はタイプ Pe の終点
or タイプBの起終点)
1 0 1
4本
(駅 s はタイプ B8 の起終点)
2 0 2

 式 (A3-3) と式 (A3-4) では fork 変数の下限を決めただけで、上限は決めていないので、 別に上限を決める必要があります。
 たとえばタイプ Pe であれば、以前と同じように「すべての(全駅の)fork 変数の総和は1以下」という制約式([2-3] の式 (14))を別に入れてやります。これで fork 変数の値が必要以上に大きくなる(たとえば、まったく通らない駅の fork 変数の値が1や2になる)ことは防げますし、 「3本同時使用」の駅がいくつも出てくるようなことを抑えられます。

タイプ別、fork 変数の総和

 式 (14) はタイプ Pe の場合なので fork 変数の総和は1となっていますが、 総和を変えることで他のタイプにも対応できます。
 まずタイプBなら、スタートとゴールの2駅が「3本同時使用」となるので、 fork 変数の総和はどうしても2以上になります。 そこで、fork 変数の総和を2以下に制限する制約式(式 (14) の右辺を2にしたもの)を入れてやります。
 タイプ B8 も同様で、表 A3-1 によると「4本同時使用」の場合には fork 変数が2以上となるので、fork 変数の総和を2以下として、 「4本同時使用」を全国1カ所に抑えます。 これは結果的にタイプBと同一の制約式になります。

「fork 一本化」の効果

 以上のように fork 変数の定義を変えたところ、解答時間が短くなりました。 問題にもよるので一概に何%短縮とはいえませんが、 たとえば「JR西日本の最長経路」を求めようとしたとき、タイプ Pe の解答時間(ループ除去制約式の追加をして解き直す過程の計算時間の総和)は、 もともと15分ほどかかっていたものが3分で解けるようになりました。 これは効果が顕著に出た例ですが、 「かえって遅くなった」という事例は多くないと考えています。


タイプB8をまじめに解く

 タイプB8は、JR全線を対象とした最長経路を求めるとき、 解き始めてすぐに「最長になる望みがない」と判明したため、 最後までまじめに解いたことがありませんでした。より正確に言うと、 ループ除去を繰り返して「ちゃんとしたタイプB8の最長経路」が出てくるまで解き直す、 という作業を怠っていました。
 しかし、たとえば「本州だけの最長片道きっぷ」を考えたときには、 タイプB8が最長にならないとも限りませんし、 そうでないにしても、タイプB8の中で最長のものはどういう経路なのか、 興味もあります。
 そこで、あらためてタイプB8について考えてみることにしました。

「3本同時使用」を認めないために

 タイプB8は、全国で1カ所だけ「ある駅から出る枝を4本使う」ことがあり、 あとはすべての駅が「0本 or 2本使用」です。 つまり「ある駅から出る枝をちょうど3本だけ使う」ということはありません。 このことを制約式として表現する必要があります。

 まず、枝がちょうど3本出ている駅では、 「4本同時使用」があり得ないので、 「使う枝は2本以下」という制約式を入れればOKです。たとえば駅 s から3本の枝 e1〜e3 が出ている場合、 以下のような制約式 (A3-5) を入れます。

e1 + e2 + e3 ≦ 2 (A3-5)

 次に、4本以上の枝が出ている駅に関しては、 「3本同時使用だけは不可」という制約式を入れます。たとえば駅 s から4本の枝 e1〜e4 が出ている場合、 以下のような制約式 (A3-6)〜(A3-9) を入れます。

e1 + e2 + e3 − e4 ≦ 2 (A3-6)
e1 + e2 − e3 + e4 ≦ 2 (A3-7)
e1 − e2 + e3 + e4 ≦ 2 (A3-8)
−e1 + e2 + e3 + e4 ≦ 2 (A3-9)

 発想は「タイプPのループ除去」、 あるいは「枝を1本だけ使うのは不可」(詳細は「[2-3] 整数計画法で(制約式編) - タイプ Lee の定式化」参照)というのと同じです。 4本のうちちょうど3本だけを使うと、(A3-6)〜(A3-9) のどれかは左辺が3になり、「≦2」を満たさなくなります。いっぽう e1〜e4 の4本すべてを使えば、すべての式で左辺が2となり、制約を満たします。
 5分岐以上の駅に対しては、すべての枝を列挙して、 そのうち3つに+、残りに−の符号をつけます。 そしてすべての符号の組合せ(n分岐で n3通り)を網羅すれば、 同様に「3本同時使用」だけを禁止する制約式を書くことができます。

 以上のような制約式を入れて問題を解いてみると、 たしかにタイプB8のルート(+0個以上の孤立ループ)が出てきます。 そして多くの場合、総距離はかなり短くなります。 もともと、3分岐にくらべると4分岐以上の駅はそれほど多くないため(たとえば本州では、 3分岐の駅が約150あるのに対し4分岐は約40駅、5分岐以上は約10駅しかない)、 「必ず4分岐以上の駅がスタート・ゴールになる」というタイプB8の特徴を満たすことは意外に厳しいようです。



(c) SWA / KASAI TakayaSWA へメールを送る
最終更新: 2005年 4月 9日
簡易包装にご協力ください。