以下、添付図面を参照して、本発明にかかる情報処理装置の実施形態を詳細に説明する。
まず、以下に説明する各実施形態で用いる記号、用語等について説明する。決定性有限状態オートマトン(以下、DFAと表記する)は5つ組(5-tuple)、DFA=(Q,Σ,E,q0,F)で表される。ここで、Qは状態の集合、Σは入力記号の集合、Eは遷移の集合、q0は初期状態である。Fは終了状態の集合であり、F⊆Qを満たす。遷移e∈Eに関してp(e)は遷移元の状態(以下、遷移元状態という)を表し、n(e)は遷移先の状態(以下、遷移先状態という)を表し、label(e)はその遷移に割り当てられている入力記号を表す。
なお、遷移に割り当てられているものは全て入力記号であると見なすことで、入力記号とともに出力記号が付随している有限状態トランスデューサや、重みが付随している重み付き有限状態オートマトン等の有限状態オートマトンから派生したモデルを用いる場合においても、以下に説明する実施形態の手法を適用することができる。
プログラム等で集合を表現するときは、集合の要素を格納でき、集合内に重複した要素が発生しなければどのように表現してもよく、例えば、配列、リンクリスト、二分木、ハッシュテーブル等が挙げられる。空集合はφ又は{}で表す。集合Xのサイズは|X|と表す。例えば状態の集合Qに含まれる状態数は|Q|で表される。
入力記号の集合Σのクリーネ閉包(Kleene closure)をΣ*で表す。つまり、Σ*は集合Σに含まれる入力記号で構成される入力記号列全てと空入力記号列(空文字列,空列とも呼ばれる)とを含む集合ということである。
ある状態qに入力記号σ∈Σを入力したときの遷移先状態をδ(q,σ)と表す。同様に、入力記号列w∈Σ*を入力したときの遷移先の状態をδ(q,w)と表す。また、状態の集合に関しても同様の記法を用いる。状態の集合sに入力記号σ∈Σを入力したときの遷移先状態の集合をδ(s,σ)と表す。さらに、入力記号列w∈Σ*を入力したときの遷移先状態の集合をδ(s,w)と表す。
状態q∈Qから出て行く遷移に割り当てられている入力記号の集合をΣqとする。同様に、状態の集合sから出て行く遷移に割り当てられている入力記号の集合をΣsとする。
後述する経路番号や状態x等に値や集合等を関連付けるためのテーブルをDとするとき、このテーブルDに関連付けられた値や集合を得るときはD[x]と記載する。例えばD[x]←rは、テーブルD中のxに値rを関連付ける処理を表している。また、D[x]=yであるとき、これに対応するテーブルDの要素は(x,y)のように表すこととする。また、テーブルDに含まれる全ての要素について処理する擬似コードを記載する場合には、foreach文を用いて、foreach(x,y)∈Dのように表す。
後述する各擬似コード内の変数については特に説明のない限り局所変数であるとする。つまり、その擬似コードの範囲内で処理されているときのみ有効な変数であるとする。なお、再帰呼び出しする場合は、個々の呼び出し毎に変数が作成され、異なる呼び出しの間で変数の内容が共有されることはない。一方、全ての擬似コードの間で共有される変数、つまりグローバルな変数については個々に説明する。なおDFAを構成する状態の集合Q、入力記号の集合Σ、遷移の集合E、初期状態q0、終了状態の集合Fは、グローバル変数であるとする。
ある状態qに対して、δ(q,w)=qが成り立つようなw∈Σ*\{ε}が存在する場合、状態qは循環経路上にあるという。また、このようなwによって通過することになる経路のことを循環経路と呼ぶ。なお、w∈Σ*\{ε}は、空入力記号列εを含まない入力記号列全てから構成される集合を意味する。
wiをwの先頭からi番目までの記号で構成される記号列とする。例えば、w=abcならw1=a,w2=ab,w3=abcとなる。状態q∈Qから入力記号列w∈Σ*\{ε}の入力によって通過する経路上にある状態をQwとすると、Qw={q,δ(q,w1),δ(q,w2),・・・,δ(q,w)}のように定義できる。状態δ(q,w)から入力記号σ∈Σによって遷移した先の状態δ(q,wσ)がQwに含まれるとき、状態δ(q,wσ)を循環経路の開始状態と呼ぶ。qをどの状態とするかで循環経路の開始状態は変化する。例えば、後述する図3では、ステップN103で選ばれる集合gに含まれる状態が、ここでのqに対応する。
ある状態pから終了状態へと導く入力記号列全体の言語をL(q)={w∈Σ*|δ(q,w)∈F}と定義するとき、2つの状態p、qが区別可能であるとは、L(p)≠L(q)であることをいう。同様に、区別不可能であるとはL(p)=L(q)であることをいう。3個以上の状態数の場合に拡張すると、状態の集合sに含まれる状態が互いに区別不可能であるとは、全ての入力記号列w∈Σ*に対してδ(s,w)⊆F又はδ(s,w)⊆Q\Fが成り立つことをいう。また、循環経路を考慮する場合、他の状態が区別不可能であれば区別不可能になる状態も考えられる。このような状態を区別不可能候補と呼ぶこととする。
依存関係とは、区別不可能候補である状態を依存元状態とし、依存元状態が区別不可能な状態となるか否かを判断するための状態を依存先状態とするとき、依存元状態と依存先状態との関係を表す情報である。具体的には、循環経路の開始状態である状態のうちの何れかが依存先状態となる。
状態の集合をsとするとき、sに含まれる状態が互いに区別可能であるとは、全てのp∈s,q∈s,p≠qに対して、pとqとが区別可能であることをいう。同様にsに含まれる状態が互いに区別不可能であるとは、pとqとが区別不可能であることをいう。
状態の終了性(finality)とは、状態q∈Qが終了状態の集合Fに含まれているか否かを表している。q∈Fであれば状態の終了性は真であり、¬(q∈F)であれば状態の終了性は偽である。終了性と出て行く遷移の入力記号の集合が同じ状態を分類したもの、言い換えると、それらが同じ状態を夫々集合とし、その集合を要素とする集合をGとする。したがって、集合Gは状態の集合の集合となる。集合ηも状態の集合を要素とする集合とし、集合ηを要素とする集合を集合Hとする。
また、後述する実施形態では、循環経路の判定のためにスタック(スタックS)を利用するが、スタックの実装方法は特に問わないものとする。例えば、配列やリンクリストで構成することとしてもよい。ただし、スタックに記録している要素の内容と、そのスタック内での格納位置を調べることが可能であるものとする。
[第1の実施形態]
図1は、第1の実施形態に係る情報処理装置のハードウェア構成の一例を示したブロック図である。同図に示したように、情報処理装置100は、CPU(Central Processing Unit)1、操作部2、表示部3、ROM(Read Only Memory)4、RAM(Random Access Memory)5、記憶部6等を備え、各部はバス7により接続されている。
CPU1は、RAM5の所定領域を作業領域として、ROM4又は記憶部6に予め記憶された各種制御プログラムとの協働により各種処理を実行し、情報処理装置を構成する各部の動作を統括的に制御する。また、CPU1は、ROM4又は記憶部6に予め記憶された所定のプログラムとの協働により、後述する各機能部の機能を実現させる。
操作部2は、マウスやキーボード等の入力デバイスであって、ユーザから操作入力された情報を指示信号として受け付け、その指示信号をCPU1に出力する。
表示部3は、LCD(Liquid Crystal Display)等の表示装置により構成され、CPU1からの表示信号に基づいて、各種情報を表示する。
ROM4は、情報処理装置の制御にかかるプログラムや各種設定情報等を書き換え不可能に記憶する。RAM5は、SDRAM等の揮発性の記憶媒体であって、CPU1の作業エリアとして機能し、具体的には、後述する状態数削減処理時において生成される各種変数やパラメータの値等を一時記憶するバッファの役割を果たす。
記憶部6は、磁気的又は光学的に記録可能な記憶媒体を有し、情報処理装置の制御にかかるプログラムや各種設定情報等を書き換え可能に記憶する。また、記憶部6は後述する状態数削減処理を実行する各機能部を実現するためのプログラムや、状態数削減処理の対象となるDFA等、各種の情報を予め記憶する。
図2は、図1に示した情報処理装置の機能的構成を示したブロック図である。同図に示したように、情報処理装置は、CPU1とROM4又は記憶部6に予め記憶された所定のプログラムとの協働により実現される機能部として、状態数削減処理部10を備えている。
状態数削減処理部10は、状態分類部11と、探索部12とを有し、これら機能部との協働により後述する状態数削減処理を実行し、処理対象となるDFAを構成する状態数を漸進的に削減する。
状態分類部11は、処理の対象となるDFAに含まれる各状態を、その状態の終了性(finality)と、出て行く遷移(outgoing transition)に付随する入力記号の種別とが同じ状態毎に分類する。ここで、各分類は状態の集合として表すことができる。また、分類全体は分類から構成されるので、分類の集合、つまり、状態の集合を要素とする集合で表すことができる。そこで、以下では、状態分類部11が分類した状態の集合をgと表記し、このgを要素とする分類全体の集合をGと表記する。なお、状態分類部11は、分類に含まれる状態数が1の場合には、その分類を集合Gに含めないものとする。即ち、全てのg∈Gに対して、|g|>1であるものとする。
また、状態分類部11は、集合Gが空集合φであるか否かを判定し、空集合φと判定した場合、処理対象のDFAを構成する状態の数が最小と判断する。一方、集合Gが空集合φでないと判定した場合、集合Gの要素となる集合gの一つを選択し、探索部12に引き渡す。なお、要素の選択順序は特に問わず、例えばgのサイズが小さいものから選んでもよいし、大きいものから選んでもよい。
探索部12は、図2に示したように、状態併合部121と、遷移先集合生成部122と、区別不可能集合生成部123と、区別不可能候補集合生成部124とを有している。探索部12は、これら各機能部との協働により、集合gに含まれる状態のうち、区別不可能な状態同士を一つの状態に併合し、この併合した集合gを集合Gから除去する。なお、探索部12の動作の詳細については後述する。
以下、本実施形態の状態数削減処理部10により実行される状態数削減処理について説明する。図3は、状態数削減処理の概要を示したフローチャートである。なお、図中ステップN110で示す各ステップ(ステップN111〜N119)が、探索部12により実行される処理内容を表している。
まず、状態分類部11は、処理対象となったDFAについて、当該DFAを構成する各状態を、その状態の終了性と、出て行く遷移に付随する入力記号の種別とについて分類する(ステップN101)。
次いで、状態分類部11は、ステップN101で分類した集合gを要素とする集合Gが、空集合φか否かを判定する(ステップN102)。ここで、集合Gが空集合φでないと判定した場合(ステップN102;No)、状態分類部11は集合Gに含まれる集合gを一つ選択し、探索部12に処理を渡す(ステップN103)。
探索部12では、ステップN103で選択された集合gに含まれる各状態について、出て行く遷移に付随する入力記号の集合Σgを生成する(ステップN111)。
続いて、探索部12は、ステップN112〜N115のループ処理(ループ1)を実行する。まず、ステップN112では、集合Σgに含まれる各入力記号について、ステップN113、N114の処理が完了したか否かを判定する。次いで、探索部12は、集合Σgから一の入力記号を選択すると、この入力記号により遷移する集合gに含まれる状態の遷移先状態の集合gnを導出する(ステップN113)。
そして、探索部12は、集合gnと集合Gの各要素g′(g′∈G)との積集合(gn∩g′)を求め、このサイズが2以上である場合のみ(|gn∩g′|>1)、この積集合を集合gと見なして、ステップN111〜N119までの処理を再帰的に行う(ステップN114)。
ステップN112〜N115のループ処理が完了すると、再帰処理によって遷移先状態のうち互いに区別可能な状態は一つにまとめられている。探索部12は、これを前提として集合gに含まれる各状態のうちで、互いに区別不可能な状態の集合を夫々一つの状態に併合する(ステップN116)。なお、ステップN114の再帰処理中に生成された後述する依存関係の情報があり、さらに併合すべき状態があれば、それらについても一の状態に併合する。
続いて、探索部12は、集合gが循環経路にあるか否かを判定し、循環経路にある場合には、この集合gの依存先となる状態集合についての情報を記録する(ステップN117)。なお、集合gが循環経路にあると判定した場合であっても、現時点では区別不可能と決められないものに関しては、その集合gを依存元とし、この循環経路の開始状態を依存先とした依存関係の情報を記録する。この場合、依存先の状態集合が区別不可能であると判定したときに、一つの状態に併合する。ここで、循環経路の開始状態とは、前記定義により、その循環経路上の状態のうち最初に処理する状態を意味する。
また、探索部12は、集合gに含まれている状態が何れも循環経路上になければ、この集合gに一致する集合Gの要素を集合Gから除去する(ステップN118)。さらに、探索部12は、区別不可能と判定し、一つの状態に併合する過程で削除した状態を集合Gから除去し(ステップN119)、ステップN102の処理に再び戻る。
ステップN102において、集合Gが空集合であると判定した場合(ステップN102;Yes)、状態分類部11は処理対象のDFAの状態数が最小化されていると判断し、本処理を終了する。
ステップN110が実行される度に、区別不可能な状態がまとめられることで状態が削減される。そのため、本処理が完了する前に処理が中断されても、この途中の時点でのDFAを得ることができる。なお、上記処理では再帰的な処理が発生するが、局所変数、つまりステップN110の処理が呼び出される度に、この処理により生成される変数をスタックに記録する一般的な方法により、繰り返し処理へと変換できることは言うまでもない。
以下、上述した状態数削減処理を実現する具体的な手法の一例について説明する。図4は、上述した状態数削減処理のメインプログラムとなる“simin”の擬似コードの一例を示した図である。なお、括弧内の“A”は、引数となる処理対象のDFAを意味している。
まず、状態数削減処理部10は、状態と経路番号との2つ組の集合を記憶しておくためのスタックSを空にするとともに、状態の依存関係を記憶しておくためのテーブルDを空集合にする(ステップN201)。なお、スタックSとテーブルDはグローバル変数とする。つまり、後述する各擬似コードから、同じスタックSと、テーブルDとが参照できるものとする。
次いで、状態数削減処理部10は、状態分類部11を用いて、終了性と出て行く遷移の入力記号とで、処理対象のDFAを構成する各状態を分類し、その結果を集合Gに代入する(ステップN202)。具体的には、ある状態から出て行く全ての遷移に付随する入力記号から構成される集合と、その状態の終了性とが同じ条件のものを一つの集合gに集約し、それらの集合をGとする。遷移や終了性のパターンが複数あると、この集合gが複数個生成されるが、要素が1つの集合gはGに含めない。形式的に表すと、∀g∈G,|g|>1である。これらの処理を行うのが、ステップN202に記述したサブプログラム“create_class”である。なお、“create_class”については後述する。
ステップN202で得られる集合Gの内容は、全てのg∈Gに関して任意の状態q1,q2∈gを考えたとき、{label(e)|e∈E, p(e)=q1}={label(e)|e∈E,p(e)=q2}、且つ、q1,q2∈F∨¬(q1,q2∈F)を満たすものとなっている。このステップN202が、図3に示したステップN101の処理に対応している。
以下、図5を参照して、ステップN202のサブプログラム“create_class”について説明する。ここで、図5は“create_class”の擬似コードの一例を示した図である。
まず、状態分類部11は、状態の集合gを要素とする集合Gを空集合φで初期化するとともに、状態の終了性と集合Σqとの2つ組に状態の集合gを関連付けて記憶するためのテーブルCを空集合φで初期化する(ステップN211)。
続いて、状態分類部11は、ステップN212のforeach文に従い、処理対象のDFAを構成する状態の集合Qに含まれる各状態qについて、ステップN213、N214の処理を実行する。ステップN213において、状態分類部11は、状態qから出て行く遷移の入力記号の集合を生成し集合Σqに代入する。また、ステップN214において、状態分類部11は、状態qの終了性と集合Σqとの2つ組をテーブルCに登録し、この2つ組みの条件に関連付けた集合gに当該条件に該当する状態qを追加する。なお、ステップN214の“q∈F”は、状態qが終了状態であれば真となり,そうでなければ偽となる演算を意味している。
続く、ステップN215は、状態分類部11がテーブルCに登録した各要素に対して、ステップN216、N217の処理を実行することを表している。ここで、状態分類部11は、状態の終了性と集合Σqとの2つ組に関連付けられている状態の集合gのみをステップN216、N217で使用する。ステップN216において、状態分類部11は、集合gのサイズが2以上(|g|>1)であるか否かを判定し、2以上であればステップN217で集合Gに集合gを追加する。
なお、ステップN216において、集合gのサイズが1以下(|g|≦1)と判定した場合、テーブルCに登録されている次の要素についてステップN215を実行する。また、全ての要素についてステップN216、N217の処理が完了した場合には、ステップN218の処理に移行する。
次いで、状態分類部11は、上述した処理で得られた集合Gを、“create_class”の処理結果としてメインプログラム“simin”に返し(ステップN218)、“create_class”の処理を終了する。
図4に戻り、状態数削減処理部10は、集合Gが空集合φになるまでステップN204、N205の処理を繰り返し実行する(ステップN203)。このステップN203が、図3に示したステップN102の処理に対応する。ステップN204において、状態数削減処理部10は、集合Gから任意の要素(集合g)を一つ選択する。なお、要素の選択順序は特に問わず、例えばgのサイズが小さいものから選んでもよいし、大きいものから選んでもよい。
続くステップN205において、状態数削減処理部10は、探索部12を用いることで、集合gに含まれる状態と、これら各状態からの遷移先状態とのうち、区別不可能な状態を一つの状態に併合する。上記したステップN204、N205の処理が、それぞれ図3に示したステップN103、N110の処理に対応している。
また、サブプログラム“search_equiv”の引数の生成に係るサブプログラム“add_path_index”では、集合gの要素に1から順に番号を付与した集合を生成する処理が行われる。この番号を経路番号(path index)と呼ぶこととし、経路番号が割り振られた状態の集合をγで表す。ここで、集合γの要素は(状態,経路番号)で構成される2つ組であるとする。集合gに含まれる状態の夫々に固有の番号を関連付けられればよいので、実際のプログラムとして実装する場合には、集合gに含まれる状態を要素とする配列やリンクリストなどを用いることとしてもよい。なお、ステップN205の処理を行うサブプログラム“search_equiv”については後述する。
ステップN204、N205を実行する度に状態を併合する処理が完結するため、集合Gが空集合φになる前に処理を中断しても、その中断した時点でのDFAが得られる。また、後述するサブプログラム“search_equiv”やそこから呼び出されるサブプログラムは、一部を除き、処理の途中で中断することも可能である。これらの点において漸進的な処理になっていることが分かる。なお、中断するとその時点でのDFAを得ることができない箇所については後述する。
以下、図6−1及び図6−2を参照して、ステップN205のサブプログラム“search_equiv”について説明する。ここで、図6−1及び図6−2は“search_equiv”の擬似コードの一例を示した図である。なお、“search_equiv”は、図3に示したステップN110(ステップN111〜N119)の処理に対応する。
まず、探索部12は、引数として渡された集合γの各要素から経路番号を取り除いた状態の集合を集合gに代入する(ステップN221)。なお、配列やリンクリストのような各要素に順序がある記憶方法で集合γが構成されており、さらに順序を無視して集合演算を行えるように構成されている場合には、ステップN221のような経路番号を取り除く処理は必要なく、そのまま集合gとして使用してもよい。
次いで、探索部12は、集合gに含まれる各状態から出て行く遷移に付随する入力記号の集合を作成し、それをΣgとする(ステップN222)。なお、集合gに含まれている状態に関しては全て同じ集合Σgとなるので、ステップN222のように集合gに含まれる状態全てについて出て行く遷移の入力記号を調べなくてもよく、集合gに含まれる状態のうち一つのみについて取り扱えば十分である。このステップN222の処理が、図3に示したステップN111の処理に対応する。
続いて、探索部12は、後の処理で使用する集合Ψscを空集合φとした後(ステップN223)、集合Σgが空集合φであるか否かを判定する(ステップN224)。ここで、集合Σgが空集合φであれば、ステップN225の処理を実行する。集合Σgが空集合φということは遷移先が存在していないということであるため、集合gに含まれる状態は互いに区別不可能である。つまり一つの状態に併合することができるので、探索部12は、状態併合部121を用いてサブプログラム“merge_states”を実行することで、集合gに含まれる状態を一つの状態に併合する(ステップN225)。また、遷移先がある場合には|Σg|>0となるので、探索部12は、ステップN226に移行し、ステップN227からステップN267までの処理を行うこととなる。なお、サブプログラム“merge_states”については後述する。
ステップN227において、探索部12は、集合Hを空集合φにするとともに、集合Yscを空集合φとする(ステップN227)。続いて、探索部12は、現在の集合γの値をスタックSに格納する(ステップN228)。そして、探索部12は、ステップN229のforeach文に従い、集合Σgの要素σ毎にステップN230〜N254までの処理を行う。なお、ステップN229〜N254までの処理が、図3に示したステップN112〜N115の処理に対応している。
ステップN230において、探索部12は、このループ内で使用する集合Ψsc,集合Ψnsc,集合ηを空集合φとする(ステップN230)。次いで、探索部12は、遷移先集合生成部122を用いてサブプログラム“next_gamma”を実行することで、集合γに含まれる各状態からの入力記号σによる遷移先状態の集合を経路番号とともに集合γnに記録する(ステップN231)。なお、サブプログラム“next_gamma”については後述する。
|γ|=|γn|の場合には経路番号は遷移元に対応する番号でなければならない。一方、状態が同じで経路番号が異なる2つ組が存在する場合には、|γ|>|γn|となるので、集合γnに含まれる経路番号が互いに異なっていればどのような経路番号を割り当ててもよい。例えば、状態が同じで経路番号だけが異なる2つ組に関して、その中で最も小さい経路番号を割り当てるようにしてもよい。
|γ|>|γn|の場合に、経路番号を割り当て直してもよい理由は次の通りである。循環経路を発見するために経路番号を用いている。循環経路と判定されるにはスタックSに集合γnが存在する必要がある。もし|γ|>|γn|であるなら、全てのγs∈Sに対して、|γs|>|γn|が成立する。これは、|γ|>|γn|のとき集合γnがスタックSに存在しないことを意味する。したがって、集合γnの経路番号は集合γの経路番号とは無関係に定めることができる。
探索部12は、スタックSに集合γnが記憶されているか否かを判定し(ステップN232)、スタックSに集合γnが記憶されていない場合、ステップN233〜N248までの処理を実行する。
スタックSに集合γnが記憶されていない場合、探索部12は、ステップN233のforeach文に従い、集合Gに含まれる状態の集合g′の全てについて、ステップN234〜N237までの処理を行う。ステップN234では、集合γnの要素のうち、集合g′に含まれる状態のみを選択し、集合γniに代入する(ステップN234)。言い換えると、集合γnに含まれる2つ組(状態,経路番号)に記録されている状態から構成される状態の集合と、集合g′との積集合を、経路番号を維持したまま求め、それを集合γniとするということである。なお、本擬似コードでは経路番号を常に維持するようにしているが、|γ|>|γni|の場合は経路番号を維持する必要はないため、この場合には新たに経路番号を振りなおしてもよい。
集合γや集合γn,集合γniを先頭のインデックスが固定の配列とし、配列のインデックスを経路番号に、その要素を状態とすることで、記憶域を無駄に使用せずに集合γなどを表現することができる。要素数が減れば経路番号は振りなおせるので、常に集合γや集合γn,集合γniのサイズ分だけ配列のサイズを用意すればよい。
ところで、本擬似コードでは、ステップN233において集合Gに含まれる全ての要素についてステップN234の処理を行うこととしたが、多くの場合集合g′に関して集合γnとの積集合の演算を行うとγni=φとなることから、次に述べるように、一部の要素についてのみステップN234の処理を行うこととし、さらに効率よく動作させるようにしてもよい。その動作とは、サブプログラム“create_class”で集合Gを求める際に、各状態が集合Gのどの要素に含まれているのかを対応付けるテーブルを生成しておくというものである。これにより、集合Gの要素のうち、集合γnに含まれる状態を含む集合Gの要素についてのみステップN233〜N237を処理することが効率よくできるようになり、その結果、集合γniのサイズは1以上のものしか生成されないようになる。
続くステップN235において、探索部12は、集合γniのサイズが1より大きいか否かを判定し、集合γniのサイズが1より小さい場合には、ステップN233に再び戻る。また、ステップN235において、集合γniのサイズが1より大きい場合には、続くステップN236にて“search_equiv”を再帰的に呼び出す。この結果、集合Gが更新される。なお、集合GはステップN233の判定処理で使用しているが、その時点までに処理した要素について再度処理しなおす必要はない。また、集合Ψnsctには、集合γniに含まれる状態に後述する区別不可能候補が存在したときに、その依存関係が記録される。探索部12は、集合Ψnsctの要素を集合Ψnscに追加する(ステップN237)。
続いて、探索部12は、入力記号σを伴う集合gの遷移先となる状態の集合gnを取得する(ステップN238)。この理由は、サブプログラム“search_equiv”の再帰呼び出しによって、処理対象のDFAの状態数|Q|が減少しているかもしれないためである。ただし、|γn|より|gn|が大きくなることはない。
また、探索部12は、ステップN239のforeach文に従い、遷移先が同じ状態を一つの状態に併合するため、集合gnに含まれる状態全てについて、ステップN240〜N243までの処理を実行する。
ステップN240において、探索部12は、集合gに含まれる状態のうち、入力記号σによる遷移先が同じ状態の集合を集合gsに代入する。なお、ステップN236の再帰呼び出しで集合gに含まれている状態がなくなっている可能性があるが、そのような状態はp(e)に現われることはないので問題はない。
次いで、探索部12は、集合gsのサイズが1よりも大きいか否かを判定し(ステップN241)、1以下の場合にはステップN244の処理に移行する。また、ステップN241において、集合gsのサイズが1よりも大きいと判定した場合、探索部12は集合gsに含まれる状態は入力記号σによって同じ状態へと遷移するということになるため、集合gsに含まれる状態は入力記号σに関しては区別不可能である。したがって、探索部12は、入力記号毎の区別不可能な状態の集合を記憶するための集合ηに集合gsを要素として追加する(ステップN242)。
さらに、探索部12は、集合gsを区別不可能候補としても記録しておくため、依存先状態を自分自身とした2つ組(q,q)の集合と、この集合を記録したスタックSでの格納位置、つまりスタックSのサイズ|S|とを集合Ψscに追加する(ステップN243)。なお、スタックSの格納位置を表すインデックスは1から始まるものとする。
また、探索部12は、ステップN244のforeach文に従い、集合Ψnscの各要素に関して、ステップN245〜N248の処理を実行する。このとき、集合gの遷移先状態が区別不可能候補である場合、依存関係の情報が集合ψnscに記録されているので、探索部12は、その依存先の状態を現在処理中の集合gに含まれる状態の依存先とし、集合gに含まれる区別不可能候補である状態の依存関係を集合ψscに代入する(ステップN245)。
続いて、探索部12は、依存先が格納されたスタックSの格納位置xlevelが、現在参照中のスタックSの|S|と等しいか否かを判定する(ステップN246)。ここで、一致しない場合には、ステップN248の処理に直ちに移行する。なお、xlevelはψscの依存先状態のスタックS上での格納位置を表す。
一方、ステップN246において一致したと判定した場合、探索部12は、集合ψscに含まれる2つ組(依存元状態,依存先状態)の依存元状態から入力記号σによる遷移を含む循環経路が入力記号σに関しては区別不可能であることが分かるので、集合ψscに含まれる依存元状態を集合ηに追加する(ステップN247)。なお、xlevel>|S|のケースは発生しない。
続くステップN248では、探索部12が、集合ψscとその依存先状態が格納されたスタックSの格納位置xlevelとの2つ組を、区別不可能候補として集合Ψscに追加する(ステップN248)。
ステップN249〜N253は、ステップN232の判定時において、スタックSに集合γnが記憶されている場合、つまり循環経路が発見された場合に実行される処理である。ステップN250において、探索部12は、依存関係を表す2つ組(依存元状態,依存先状態)の集合ψscを生成する。ここで、依存元状態とは、集合gに含まれる状態を意味し、依存先状態とは、依存元状態から入力記号σによって到達できる状態を意味する。
続くステップN251では、探索部12が、集合ψscとその依存先状態の集合が記録されているスタックSでの格納位置level(S,γn)との2つ組を集合Ψscに追加する。続いて、探索部12は、γ=γnか否か、即ち、自己遷移か否かを判定する(ステップN252)。ここで、自己遷移と判定した場合には、集合gに含まれる状態は区別不可能であるので、集合ηに集合gを追加する(ステップN253)。なお、ステップN232での条件の評価と同時に、位置level(S,γn)を取得しておいてもよい。
前述したように、スタックSのインデックスは1から始まるものとしているので、集合γnがスタックSの一番底に格納されている場合、level(S,γn)=1となる。以上の処理により、集合gに含まれる状態のうち、どの状態が互いに区別不可能な状態なのか、どの状態が区別不可能候補なのかが入力記号σに関して判明するので、ステップN254ではステップN230〜N253で得られた集合Ψscと集合ηとを夫々集合Yscと集合Hに追加する。
続くステップN255とN256とが、図3に示したステップN116に対応する。集合Σgに含まれる入力記号全てについて処理が終わるとステップN255以降の処理が行われる。ステップN255以降の処理では、ステップN254までに各入力記号について求めた集合ηを使って、集合gに含まれる状態の区別不可能性を判定し、互いに区別不可能な状態を一つの状態に併合する。さらにステップN254までに各入力記号について求めた集合Ψscを使って、集合gの状態のうち区別不可能候補となる状態を特定する。
ステップN255では、探索部12が、互いに区別不可能な状態の集合を要素にもつ集合を取得する。ここで集合ηは、集合Hに含まれる要素のうち何れか一つを選択すればよく、例えば、集合Hのうちで一番サイズの小さい要素を選ぶなどしてもよい。
具体的に、探索部12は、集合ηに含まれる状態の集合gs毎に、第1引数を集合gs、第2引数を集合Hから集合ηを除いた集合(H\{η})として、区別不可能集合生成部123を用いて、サブプログラム“search_sharable_state”を実行し、この実行により得られる戻り値の和集合をGshareとする。なお、サブプログラム“search_sharable_state”については後述する。
ステップN256では、探索部12が、状態併合部121を用いてサブプログラム“merge_states”を実行することで、ステップN255で検出した互いに区別不可能な状態を、一つの状態に併合する。同時に、区別不可能な状態に依存している状態もひとつにまとめられる。また、探索部12は、ステップN256において併合により不要となり削除された状態を集合geraseに代入する。なお、サブプログラム“merge_states”は、ステップN231と同様であり、詳細については後述する。
続くステップN257〜N266の処理が、図3に示したステップN117の処理に対応する。ステップN257では、探索部12が、集合gに含まれる区別不可能候補の依存関係を記録している集合Yscから、ステップN256での状態の併合処理により削除した状態に関する情報を除去する。
続くステップN258では、探索部12が区別不可能候補集合生成部124を用いて、集合Ψの要素(ψ,xlevel)毎にサブプログラム“search_sharable_state_candidate”を実行することで、区別不可能候補を見つける。ここで集合Ψは、集合Yscに含まれる要素のうち何れか一つを選択すればよく、例えば、集合Yscに含まれる要素のうちで一番サイズの小さい要素を選ぶなどしてもよい。
サブプログラム“search_sharable_state_candidate”の第1引数はψ、第2引数はxlevel、第3引数は集合Yscから集合Ψを取り除いた集合となる。“search_sharable_state_candidate”は実行する度にその結果が戻り値として返ってくるので、探索部12は、それらの和集合をΨscとする。なお、サブプログラム“search_sharable_state_candidate”については後述する。
続いて、探索部12は、xlevelが|S|以上の要素を集合Ψscから取り除く(ステップN259)。ここで、集合Ψscから取り除く理由は、自分自身や処理済みの状態へと依存することはないためである。
探索部12は、ステップN260のforeach文に従い、集合Ψscに含まれる各要素(ψsc,xlevel)について、ステップN261の処理を行う。ステップN261では、探索部12が、区別不可能候補の依存関係をグローバル変数であるテーブルDに記録する。
続いて、探索部12は、ステップN262のforeach文に従い、集合Ψscに含まれる各要素(ψscとxlevel)について、ステップN263の処理を行う。また、探索部12は、ステップN263のforeach文に従い、D[|S|]の各要素dについて、ステップN264とN265の処理を行う。
ステップN264では、探索部12が、ψscに含まれる各要素(qs,qd)に対して、qsを依存先の状態とするようなdの要素を見つけ、それに対応している依存元の状態q′sの依存先の状態をqdへと変更した2つ組(q′s,qd)の集合を生成し、それら全ての集合の和集合をdpとする。続くステップN265では、探索部12が、D[xlevel]にdpを追加する。これら、ステップN262〜N265の処理で、集合gに含まれる区別不可能候補に依存している状態の依存先状態の付け替えが行われる。
次いで、探索部12は、スタックSでの|S|の格納位置に対応する依存関係を削除し(ステップN266)、スタックSから今処理していた状態の集合γを取り除く(ステップN267)。
次に、探索部12は、集合Ψscが空集合φか否かを判定する(ステップN268)。空集合φでないと判定した場合には、ステップN270の処理に直ちに移行する。一方、空集合φであれば、集合gに含まれている状態は区別不可能候補となることはない。互いに区別不可能な状態があれば、ステップN256の処理によってそれらは既に一つにまとめられている。また、区別可能なら再度調べる必要はない。そこで、探索部12は、集合Gの要素のうち集合gと一致する要素を集合Gから取り除く(ステップN269)。なお、ステップN268、N269の処理が、図3に示したステップN118の処理に対応している。
また、集合geraseに含まれる状態は既に削除済みであるので処理される必要はない。そこで、探索部12は、ステップN270において、集合Gの要素である状態の集合から集合geraseに含まれる状態を削除したものを集合G′とする(ステップN270)。ここで、集合G′の要素である状態の集合のサイズが1以下となるものは集合G′には含めないものとする。なお、ステップN270の処理が、図3に示したステップN119の処理に対応している。
最後に、更新した集合G′と区別不可能候補の依存関係が記録された集合Ψscとで構成される2つ組を戻り値としてメインプログラム“simin”に返し(ステップN271)、“search_equiv”の処理を終了する。
次に、図7を参照して、上述したステップN231のサブプログラム“next_gamma”について説明する。図7は、サブプログラム“next_gamma”の擬似コードの一例を示した図である。
まず、遷移先集合生成部122は、遷移先状態と経路番号との2つ組(qn,i)を記憶するための集合γnを空集合φとして初期化する(ステップN281)。
続いて、遷移先集合生成部122は、ステップN282のforeach文に従い、集合γに含まれる各要素についてステップN283を実行する。なお、ここで処理の対象となる集合γの各要素を(q,i)とすると、遷移元状態がqであり、遷移に付随する入力記号がσである遷移の遷移先状態qnに関して、状態qnが集合γnに含まれていなければ、(qn,i)の2つ組を集合γnに追加する(ステップN283)。
集合γに含まれる全ての要素についてステップN283の処理が終了すると、遷移先集合生成部122は、その結果得られた集合γnをこのサブプログラム“next_gamma”の戻り値として探索部12に返す(ステップN284)。
なお、図7で説明した疑似プログラムでは、遷移先状態が同じで経路番号が異なる2つ組がある場合に、最初にステップN283で処理された経路番号が残るようにしている。しかしながら、経路番号が異なるだけの2つ組が存在する場合には、|γ|>|γn|となるので、他の集合γnに含まれる2つ組の経路番号と重複さえしなければ、どのような経路番号を付与してもよい。
次に、図8を参照して、上述したステップN255のサブプログラム“search_sharable_state”について説明する。図8は、サブプログラム“search_sharable_state”の擬似コードの一例を示した図である。
まず、区別不可能集合生成部123は、集合Hが空集合φか否かを判定する(ステップN291)。ここで、集合Hが空集合φである場合、全ての入力記号に関して積集合演算を終えたということを意味しているので、ステップN292の処理に移行する。また、集合Hが空集合φでない場合には、ステップN293の処理に移行する。
ステップN292では、探索部12から引数として与えられた集合gstartに含まれる状態を互いに区別不可能として確定することになるので、区別不可能集合生成部123は、集合gstartを集合Gsに追加するために、集合gstartのみを要素した集合を戻り値として返し(ステップN292)、“search_sharable_state”を終了する。
一方、ステップN293では、区別不可能集合生成部123が、状態の集合を要素とする集合を集合Hから一つ選択し、それを集合ηとする(ステップN293)。引数として渡された集合Hに含まれている限り、どの入力記号に対応するものを選択してもよい。例えば、集合Hの要素のうちでサイズが最も小さいものを選択することとしてもよい。
次いで、区別不可能集合生成部123は、区別不可能な状態の集合を記録するために使用する集合Gsを空集合φとして初期化すると(ステップN294)、ステップN295のforeach文に従い、集合ηに含まれる状態の集合g′の全てについてステップN296〜N298の処理を繰り返し実行する。
ステップN296では、区別不可能集合生成部123が、引数で渡された状態の集合gstartと集合g′との積集合をgisとする。次いで、区別不可能集合生成部123は、集合gisのサイズが2以上か否かを判定し(ステップN297)、集合gisのサイズが2以上の場合には、ステップN298の処理を実行する。なお、集合gisのサイズが1以下の場合には、区別不可能な状態が集合gisに存在せず、ステップN298の処理に寄与しないためステップN299の処理に直ちに移行する。
ステップN298では、区別不可能集合生成部123が積集合演算で求めた集合gisと、集合Hから今処理している集合ηを除いたもの(H\{η})とを引数として、再帰的に“search_sharable_state”を実行し、この再帰呼び出しの結果得られる区別不可能な状態の集合を集合Gsに追加する。
そして、区別不可能集合生成部123は、全ての集合g′について処理を終えると、得られた集合Gsを戻り値として返し(ステップN299)、“search_sharable_state”を終了する。
なお、探索部12では、上述したようにステップN255において、集合Hから一つ選択した集合ηに含まれる状態の集合の全てに対して“search_sharable_state”を実行し、その結果(戻り値)の和集合をとったものを区別不可能な状態の集合を要素とする集合Gshareとする。
次に、図9を参照して、上述したステップN225及びN256のサブプログラム“merge_states”について説明する。図9は、サブプログラム“merge_states”の擬似コードの一例を示した図である。
互いに区別不可能な状態を一つに併合するには、その中から代表とする状態を1つ選択し、入ってくる遷移(incoming transition)をその代表状態へ遷移するように変更する。さらに代表状態以外の状態から出て行く遷移(outgoing transition)を除去すればよい。言い換えると、2つの状態が互いに区別不可能な状態であるとし、代表状態つまり併合後に残留対象となる状態をr、残りの状態つまり削除対象の状態をqe、遷移(遷移元状態、遷移先状態、入力記号)の集合Eで表すとき、入ってくる遷移については
E←{(qs,r,σ)∈E|(qs,qd,σ)∈E,qd=qe}∪{(qs,qd,σ)∈E|qd≠qe}のような操作をすればよく、出て行く遷移については、
E←{(qs,qd,a)∈E|qs≠qe}のような操作をすればよい。
そして、最後に状態の集合Qから状態qeを除去する。これらの処理を行うサブプログラムを“merge”とする。なお、“merge(r,qe)”で集合Qからqeを除去せず、メインプログラム“simin”が完了した後に、集合Qから状態qeをまとめて削除するように構成してもよい。
サブプログラム“merge”の実行中に処理が中断されると、それまでの処理により状態数が削減されたDFAを得ることができなくなる。併合する状態に依存している区別不可能候補の状態も併合する必要がある。これには上述した依存元状態、依存先状態の2つ組の集合を要素とした集合と同等の構造を持つ依存関係の情報を利用すればよい。
まとめると、互いに区別不可能な状態と、それらに依存している互いに区別不可能候補である状態をと併合するアルゴリズム、即ち、サブプログラム“merge_states”は図9に示したようになる。なお、図9では、ステップN256での“merge_states”を前提に説明を進めるが、ステップN232の“merge_states”についても引数が異なるのみで同様の処理が行われる。
まず、状態併合部121は、集合Qeを空集合φとする(ステップN301)。続いて、状態併合部121は、ステップN302のforeach文に従い、集合Gshareの各要素gsに関してステップN303〜N313までの処理を繰り返し実行する。
ステップN303では、状態併合部121が、集合gsから何れか一つの状態を選択し、それを代表状態rとする。ここで、代表状態rは何れの状態であってもよいが、例えば状態番号が一番小さな状態を選択することとしてもよい。
続いて、状態併合部121は、ステップN304のforeach文に従い、状態の集合gsから状態rを除いた集合(gs\{r})に含まれる各状態qeに対して、ステップN305とN306の処理を実行する。ステップN305において、状態併合部121は、代表状態rに集合qeに含まれる状態を併合する。続くステップN306において、状態併合部121は、ステップN305での併合により不要となった状態を集合Qeに追加する。
次に、状態併合部121は、ステップN307のforeach文に従い、D[|S|]に対応するDelmに含まれる各要素ψに対して、ステップN308〜N313の処理を繰り返し実行する。
ステップN308では、状態併合部121が、依存先状態が集合gsに含まれるような依存元の状態を集約し、それを集合gに追加する。次いで、状態併合部121は、集合gのサイズ|g|が2以上か否かを判定する(ステップN309)。ここで集合gのサイズが2以上ならば、それらの状態は併合することが可能である。そのため、状態併合部121は、集合gから何れか一つの状態を選択し、それを代表状態r′とする(ステップN310)。ここで、代表状態r′は何れの状態であってもよいが、例えば状態番号が一番小さな状態を選択することとしてもよい。
続いて、状態併合部121は、ステップN311のforeach文に従い、集合gから状態r′を除いた集合(g\{r′})に含まれる各状態qeに対して、ステップN312とN313の処理を実行する。ステップN312において、状態併合部121は、代表状態r′に各状態qeを併合する。続くステップN313において、状態併合部121は、ステップN312での併合により不要となった状態を集合Qeに追加する。
続いて、状態併合部121は、これまでの処理で得られた集合Qe、即ち、不要になった状態の集合を戻り値として探索部12に返し、“search_equiv”の処理に再び戻る。なお、ステップN304〜N313の処理中に処理を中断すると、それまでの処理により状態数が削減されたDFAを得ることはできない。そのため、後述する第5の実施形態のように、ステップN304〜N313の処理中に処理が中断されないよう制御する構成としてもよい。
次に、図10を参照して、上述したステップN258のサブプログラム“search_sharable_state_candidate”について説明する。図10は、サブプログラム“search_sharable_state_candidate”の擬似コードの一例を示した図である。
なお、図10において、要素ψ及び要素ψstartは(依存元状態,依存先状態)の2つ組の集合に対応し、集合Ψは(ψ,依存先状態のスタックS上での位置)の2つ組の集合に対応し、集合Yは集合Ψを要素とする集合であって、各要素が各入力記号による結果に対応している。また、xstartはψstartの依存先状態のスタックS上での格納位置を表す。
まず、区別不可能候補集合生成部124は、集合Yが空集合φか否かを判定し(ステップN321)、空集合φであればステップN322の処理を実行する。集合Yが空集合φであるということは、もう処理するべき要素が集合Yには残っていないということなので、要素ψstartに含まれる状態は集合Σgに含まれる全ての入力記号に対して区別不可能候補となる。したがって、区別不可能候補集合生成部124は、区別不可能候補の2つ組(ψstart,xstart)を本擬似コードの処理結果である集合Ψsに追加するために戻り値として返す(ステップN322)。
続くステップN323では、区別不可能候補集合生成部124が、集合Yから任意の要素を一つ取り出してそれを集合Ψとする。ここでは、いずれの要素を取り出してもよく、例えば、サイズが最も小さい要素から取り出すこととしてもよい。
続いて、区別不可能候補集合生成部124は、処理結果である区別不可能候補を記憶しておくための集合Ψsを空集合φとすると(ステップN324)、ステップN325のforeach文に従って、集合Ψに含まれる各要素(ψ,xlevel)に対して、ステップN326〜N332までの処理を実行する。
ステップN326では、区別不可能候補集合生成部124が、xstartとxlevelとの大小関係を比較することで、依存先状態が要素ψに含まれる状態となるか、要素ψstartに含まれる状態となるかを判定する。依存先が複数あるときは常にスタックSの底側、つまり循環経路の開始状態に近い側の状態が優先されるので、スタックS上での位置の値が小さいほうの状態が優先されることになる。したがって、区別不可能候補集合生成部124は、xstart<xlevelのときは要素ψstartに含まれる依存先状態を採用する(ステップN327)。一方、xstart≧xlevelのときは、ステップN328に移行し、要素ψに含まれる依存先状態が優先される(ステップN329)。なお、xstart=xlevelのときは、要素ψの状態qdも要素ψstartの状態qdも同じであるためどちらで処理しても良いが、ここではステップN329に含めている。
区別不可能候補は要素ψstartと要素ψの両方に含まれなければならないので、ステップN327もN329も依存元状態に関しては積集合をとったものになる。その結果要素ψisには、区別不可能候補である依存元状態が要素ψstartと要素ψとの両方に含まれ、その依存先がスタックSのより底側にある状態の2つ組に含まれることとなる。この要素ψisのサイズが1以下なら区別不可能候補になることはありえないので、区別不可能候補集合生成部124は、要素ψisのサイズが2以上の場合のみさらに以下処理を行うことになる(ステップN330)。
ステップN331では、区別不可能候補集合生成部124が、後述するxisに含まれる依存先状態のスタックS上での格納位置を求める。依存先状態はスタックS上での格納位置が小さいほうが選択されているので、xstartとxlevelのうち小さいほうの値となる。この値をxisとする。
続いて、区別不可能候補集合生成部124は、ステップN331で処理した要素ψisを第1引数に、xisを第2引数に、集合YからステップN323で選択した集合Ψを除去した集合(Y\{Ψ})を第3引数とし、サブプログラム“search_sharable_state_candidate”を再帰的に実行し、そして得られた結果を集合Ψsに追加する(ステップN332)。そして、区別不可能候補集合生成部124は、これまでの処理で得られた結果となる集合Ψsを戻り値として返し(ステップN333)、“search_sharable_state_candidate”の処理を終了する。
なお、“search_sharable_state_candidate”では、区別不可能な状態を明示的に取り扱ってはいないが、それらの状態は依存先が自分自身である区別不可能候補としてψに含めて処理すればよい。そうすることで区別不可能な状態が区別可能な状態として扱われることなく、区別不可能候補を見つけることができるようになる。この処理は例えば、“search_equiv”のステップN243に見られる。また、区別不可能か否かは“serach_sharable_state”で判明するので、両方を使えば区別可能、区別不可能、区別不可能候補の3種類を扱えることになる。
以下、状態数削減処理部10の動作について、具体例を示しながら説明する。
まず、図11に示したような、循環経路を有さないDFAを処理対象とした場合の状態数削減処理部10の動作について説明する。ここで、図11は、DFAの一例を示した図であって、各円が状態を表しており、円内に記された数値が各状態を識別するための状態番号を表している。また、各円のうち太線の円が初期状態を表しており、二重線の円が終了状態を表している。図中、矢印は遷移を表しており、各矢印に付随する記号が入力記号を表している。
状態数削減処理部10は、図11に示した処理対象となるDFAに対し、メインプログラム“simin”を実行する。以下、各プログラムでの主要な処理内容について説明する。
まず、状態数削減処理部10は、スタックSとテーブルDとを空集合φで初期化する(ステップN201)。続いて、状態分類部11を用いてサブプログラム“create_class”を実行し、状態の終了性と出て行く遷移の入力記号の集合とが同一の状態毎に、処理対象のDFAを構成する各状態を分類する(ステップN202)。この結果、状態0と、状態1、2、3、4と、状態5、6、7と、状態8とに分類されることが分かる。ここで、状態数が1個の分類は不要とするため、G={{1,2,3,4},{5,6,7}}となる。
図12は、図11に示したDFAの状態分類後の構成を示した図である。ここで、破線で囲った部分が夫々の分類であり、状態1、2、3、4が1つの分類に、状態5、6、7がもう1つの分類になっていることが分かる。
このとき、集合Gは空集合φではないので、状態数削減処理部10はステップN203の条件を満たすと判定し、集合Gに含まれる任意の要素を一つ選択する(ステップN204)。ここで、状態数削減処理部10は、g={1,2,3,4}を選択したとする。
次いで、状態数削減処理部10は、サブプログラム“add_path_index”を実行し、集合gの各要素に経路番号を付与し、その結果をγ={(1,1),(2,2),(3,3),(4,4)}としてサブプログラム“search_equiv”の第1引数として使用する。上述したとおり、集合γの要素である2つ組は(状態,経路番号)で構成されているため、(1,1)は状態の名前(状態番号)が1、経路番号が1であることを意味している。
探索部12では、状態数削減処理部10からの指示に応じ、サブプログラム“search_equiv”の処理に入る。まず、探索部12は、ステップN221において、集合γから状態番号のみを取り出すため、その結果はg={1,2,3,4}となり、続くステップN222ではΣg={a}となる。
続いて、探索部12は、集合Ψscを空集合φとすると(ステップN223)、このときの集合Σgが、Σg≠φであるため、ステップN227で集合H、集合Yscを空集合φとし、ステップN228でスタックSに集合γを格納する。
図13は、スタックSの状態を模式的に示した図であって、上述したステップN228直後の状態を表している。同図に示したように、γ={(1,1),(2,2),(3,3),(4,4)}がスタックSに格納される。なお、集合γの左部に示す数値は、スタックSの底から数えた集合γの格納位置を表している。
続いて、探索部12は、ステップN229のforeach文に従い、σの各値についてステップN230〜N254を処理することになるが、Σg={a}であるため、σ=aについて一度だけ処理することになる(ステップN229)
ここで、探索部12は、遷移先集合生成部122を用いてステップN231の“next_gamma”を実行すると、その結果として、γn={(5,1),(6,2),(7,3),(8,4)}が得られる。具体的には、状態1の遷移先が状態5であり、状態1の経路番号が1であるため、状態5の経路番号は1となる。他の要素についても同様である。
このとき、図13に示したように、スタックSには、γ={(1,1),(2,2),(3,3),(4,4)}が記録されているのみであるため、集合γnはスタックSには存在しない。したがって、探索部12は、ステップN233以降の処理を行うことになる。
続く、ステップN234〜N237までの処理では、探索部12が、各集合g′と集合γnに含まれる状態の集合との積集合γniに対して処理を行う。ステップN235の条件にあるように、|γni|>1が成り立つのはg′={5,6,7}の場合のみであり、このときγni={(5,1),(6,2),(7,3)}である。
続くステップN236において、探索部12は、サブプログラム“search_equiv”を再帰的に実行するため、γ={(5,1),(6,2),(7,3)}としてステップN221から処理を行っていくことになる。この再帰処理時におけるステップN221の処理では、g={5,6,7}となる。また、ステップN222の処理でΣg=φとなるため、探索部12は、ステップN225の処理を実行することになり、集合γに含まれる状態、つまり、状態5、6、7を一つの状態に併合する。
ここでは、状態5を残し、状態6、7を状態5へ併合することにすると、図12で示したDFAは図14のようになる。この場合、ステップN225で導出される集合geraseは、gerase={6,7}となる。なお、図14は、図11に示したDFAの状態併合後の構成を示した図である。
また、Ψsc=φであるので、探索部12は、ステップN268の条件を満たすと判定し、ステップN269の処理を実行する。今、g={5,6,7}、G={{1,2,3,4},{5,6,7}}であるので、集合Gの要素に集合gが存在する。したがって、ステップN269の処理で、G={{1,2,3,4}}となる。
また、ステップN270では、探索部12が、集合geraseに含まれる状態、つまり削除された状態を含む集合Gの各要素から削除したものを集合G′とする。このとき、集合geraseに含まれる状態6と7は、ステップN269の処理で集合Gから既に削除されているので、G′={{1,2,3,4}}となる。また、Ψsc=φであるため、({{1,2,3,4}},φ)が戻り値となる。
探索部12は、ステップN236で再帰的に実行したサブプログラム“search_equiv”の戻り値を、集合Gと集合Ψnsctとに夫々代入する。さらに、探索部12は、集合Ψnsctに含まれる全ての要素を集合Ψnscに追加する(ステップN237)。この場合、Ψnsct=φであるため、追加する要素は何もない。
続くステップN238において、探索部12は、集合γに含まれる遷移先状態の集合を再度作成する。先ほどの再帰呼び出しによって、遷移先状態5、6、7は一つの状態5になっているので、gn={5,8}となる。続いて、探索部12は、ステップN240〜N243の処理を集合gnに含まれる全ての要素qnについて実行する(ステップN239)。
ここで、まずqn=5の場合を考える。探索部12は、ステップN240で状態5の遷移元状態を集合gsに代入するので、gs={1,2,3}となる。これにより、|gs|=3となるため、探索部12は、ステップN241の条件を満たすと判定し、ステップN242の処理を実行すると、η={{1,2,3}}となる。また、探索部12は、ステップN243を実行すると、|S|=1であるので、Ψsc={({(1,1),(2,2),(3,3)},1)となる。
次に、qn=8の場合を考える。この場合、ステップN240で得られる集合gsはgs={4}であるので、|gs|=1となる。したがって、探索部12は、ステップN241の条件を満たさないと判定するため、ステップN242とN243の処理は実行されない。また、Ψnsc=φなので、ステップN244〜N248の処理も実行されない。そして、探索部12は、ステップN254の処理を実行することで、Ysc={{({(1,1),(2,2),(3,3)},1)}}と、H={{{1,2,3}}}とを取得する。
これで集合Σgに含まれる全ての入力記号について処理が完了したので、次はステップN255が実行される。ここでは、η={{1,2,3}}であり、集合ηの要素は一つのみであるため、探索部12は、gs={1,2,3}、H\{η}=φを引数とし、区別不可能集合生成部123を用いて、サブプログラム“search_sharable_state”を実行すると、{{1,2,3}}が結果として返る。他に“search_sharable_state”を実行する集合ηの要素はないので、Gshare={{1,2,3}}となる。
続いて、探索部12は、ステップN256において、状態併合部121を用いてサブプログラム“merge_states”を実行することで、集合Gshareに含まれる状態を一つに併合する。このとき、依存関係の情報であるD[|S|]は空集合φなので、状態併合部121は、単に集合Gshareに含まれる状態の集合を一つの状態に併合するだけである。
ここでは、状態1のみを残し、状態2、3を削除することとすると、図14に示したDFAは図15のようになる。この場合、ステップN256で導出される集合geraseは、gerase={2,3}となる。なお、図15は、図14に示したDFAの状態併合後の構成を示した図である。
続くステップN257において、探索部12は集合geraseに含まれる状態を集合Yscから削除するが、今の場合、集合Yscの要素は空集合φのみであるため変化しない。また、ステップN258も同様で、Ψsc=φとなる。さらに、ステップN259〜N265までは何も起きず、ステップN266においても、この処理を実行する以前からD[|S|]=φであるため、D[|S|]に変化はない。
続くステップN267において、探索部12が、スタックSの一番上の要素(つまり、格納位置1のγ)を破棄すると、スタックS=φとなる。
また、探索部12は、Ψsc=φであるため、ステップN268の条件を満たすと判定すると、g={1,2,3,4}、G={{1,2,3,4}}であるので、ステップN269の処理結果はG=φとなる。続くステップN270で探索部12は、集合geraseに含まれる状態を集合Gから除くのだが、今の場合、既に集合Gは空集合であるので集合G′は空集合φとなる。したがって、ステップN251の戻り値は(φ,φ)となる。
メインプログラム“simin”に戻り、状態数削減処理部10は、サブプログラムの“search_equiv”からの戻り値を集合Gに代入すると、G=φとなる。ステップN203に再び戻り、状態数削減処理部10は、条件文を評価するとG≠φの条件を満たさないので、メインプログラム“simin”の処理を終了する。以上の処理により、処理対象としたDFAの状態数は最小化されることになる。
次に、図16に示したような、循環経路を有するDFAを処理対象とした場合の状態数削減処理部10の動作について説明する。ここで、図16は、DFAの一例を示した図である。記法は図11と同じである。
状態数削減処理部10は、図16に示した処理対象となるDFAに対し、メインプログラム“simin”を実行する。以下、各プログラムでの主要な処理内容について説明する。
まず、状態数削減処理部10は、スタックSとテーブルDとを空集合φで初期化する(ステップN201)。続いて、状態分類部11を用いてサブプログラム“create_class”を実行し、状態の終了性と出て行く遷移に付随する入力記号の集合とに基づいて、処理対象のDFAを構成する各状態を分類する(ステップN202)。この結果、状態0と、状態1、2、3、7と、状態4、5、6と、状態8とに分類されることが分かる。ここで、状態数が1個の分類は不要とするため、G={{1,2,3,7},{4,5,6}}となる。
図17は、図16に示したDFAの状態分類後の構成を示した図である。ここで、破線で囲った部分が夫々の分類を表しており、状態1、2、3、7が1つの分類に、状態4、5、6がもう1つの分類になっていることが分かる。
ここで、状態の集合{1,2,3,7}は全て終了状態でなく、出て行く遷移の入力記号から成る集合も全て{a}である。また、状態の集合{4,5,6}も全て終了状態でなく、出て行く遷移の入力記号から成る集合も全て{b,c}である。以下ではまず、{4,5,6}についてのサブプログラム“search_equiv”の実行時について説明する。
探索部12が、ステップN223まで実行した時点では、γ={(4,1),(5,2),(6,3)}、g={4,5,6}、Σg={b,c}となる。
ここで、Σg≠φなのでステップN227以降の処理が実行されることになり、ステップN228でS={{(4,1),(5,2),(6,3)}}となる。ここで、図18は、スタックSの状態を模式的に示した図であって、上述したステップN228直後の状態を表している。なお、同図では、スタックSに記録された要素(集合γ)を矩形で表している。また、各要素に含まれる状態番号と経路番号との2つ組の個数を、その個数に応じた小領域に区分けすることで表している。この例では、スタックSの要素に状態番号と経路番号との2つ組が3つ含まれているので、この要素を3つに区分けしている。
各小領域上に示した数値は、この小領域に対応する2つ組に含まれる状態番号を表しており、各小領域の下部に示した数値は、この小領域に対応する2つ組に含まれる経路番号を表している。また、要素の左部に示す数値は、スタックSの底から数えた要素の位置であり、スタックS上での格納位置を表している。
探索部12は、ステップN229からの処理について、例えば、σ=bから処理を開始すると、ステップN231の処理により、入力記号bによる集合γの遷移先状態の集合γnを得る。具体的には、入力記号bによる状態4の遷移先は状態1であり、状態5は状態2に、状態6は状態3に遷移するが、状態数は減少しないので、経路番号は維持されなければならない。そのため状態1の経路番号には状態4の経路番号である1が割り当てられる。他の状態も同様に処理すると、γn={(1,1),(2,2),(3,3)}となる。
続くステップN232において、探索部12は、集合γnがスタックSには存在しないと判定するため、ステップN233以降の処理を実行することになる。ここで、ステップN235の|γni|>1となるような集合γniは、γni={(1,1),(2,2),(3,3)}のみであるため、探索部12は、この集合γniについてサブプログラム“search_equiv”を再帰的に実行する。
再帰処理時におけるステップN221の処理で、g={1,2,3}が得られる。今、引数として渡されている集合γは、γ={(1,1),(2,2),(3,3)}であるからである。また、ステップN222の処理でΣg={a}が得られる。このとき、Σg≠φであるため、探索部12は、ステップN227の処理に移行し、ステップN228において集合γをスタックSに格納する。即ち、スタックSは、S={{(4,1),(5,2),(6,3)},{(1,1),(2,2),(3,3)}}となる。なお、スタックSの左側の要素ほどスタックの底側にある要素であるとしている。このときのスタックSの状態を図示すると、図19のようになる。ここで、図19は、スタックSの状態を模式的に示した図であって、再帰処理時におけるステップN228直後の状態を表している。
また、集合Σgは入力記号aのみを含んでいるので、探索部12は、σ=aとしてステップN230以降を実行することになる。ステップN231において、探索部12は、γn={(4,1),(5,2),(6,3)}を得る。そのため、ステップN232において、探索部12は、集合γnがスタックSに存在すると判定するため、ステップN249以降の処理を実行することになる。
ステップN250において、探索部12は、ψsc={(1,4),(2,5),(3,6)}を取得する。ここで、各2つ組の1番目は依存元の状態を、2番目は依存先の状態を表している。そして、探索部12は、続くステップN251の処理により、Ψsc={({(1,4),(2,5),(3,6)},1)}を取得する。つまり、依存元状態が集合γに含まれる状態1、2、3であり、夫々に対応する遷移先状態である依存先状態が状態4、5、6ということである。また、最後の値が1なのは、集合γnが見つかったスタックSでの格納位置がスタックの底、つまり1だからである。
また、このときγ≠γn、つまり自己遷移ではないため、探索部12はステップN253の処理を実行せず、ステップN254の処理を実行することで、Ysc={{({(1,4),(2,5),(3,6)},1)}}、H={{}}を取得する。
続くステップN255において、探索部12は、区別不可能集合生成部123を用いて“search_sharable_state”を実行することで、集合Hの要素から区別不可能な状態を探索するが、この場合、集合Hの要素は空集合のみであるため、Gshare=φとなる。そのため、ステップN256の処理では、その状態も併合することができず、gerase=φとなる。
また、gerase=φであるため、探索部12がステップN257を実行しても集合Yscに変化はない。集合Yscのサイズは1であるため、ステップN258で実行されるサブプログラム“search_sharable_state_candidate”は、ステップN321、N322だけが実行され、その結果、Ψsc={({(1,4),(2,5),(3,6)},1)}が得られる。
続いて、探索部12は、ステップN259を実行する。このとき、集合Ψscの要素は一つであり、その要素がxlevel=1、|S|=2であるので、xlevel<|S|となり集合Ψscは変化しない。そして、探索部12は、ステップN260とN261で、集合Ψscで表されている依存関係を、テーブルDに記録する。その結果、D[1]={{(1,4),(2,5),(3,6)}}となる。これは、図示すると図20のようになる。
ここで図20は、テーブルDの状態を模式的に示した図であって、(依存元状態,依存先状態)の2つ組を円で囲んで表している。また、これら2つ組を要素とする集合をハッチングを施した領域で表しており、更に、それを要素とする集合をハッチング領域を囲む矩形領域で表している。
ところで、D[2]=φであるので、探索部12がステップN262〜N266を実行しても変化は生じない。続くステップN267において、探索部12は、スタックSの一番上の要素を取り除くと、S={{{(4,1),(5,2),(6,3)}}となる。このとき、集合Ψscは空集合φではないので、探索部12は、ステップN268の条件を満たさないと判定し、ステップN269の処理を実行しない。
また、ステップN270では、gerase=φであるため集合Gに変化はない。したがって、G′={{1,2,3,7},{4,5,6}}となる。そして、探索部12は、再帰処理により求めた集合G′と集合Ψscとを戻り値として返す。ステップN236の再帰処理から戻ると、G={{1,2,3,7},{4,5,6}}、Ψnsct={({(1,4),(2,5),(3,6)},1)}となる。つまり、集合Gに変化はない。
次いで、探索部12は、ステップN237にてΨnsc={({(1,4),(2,5),(3,6)},1)}を取得する。他に処理すべき集合g′はないので、ステップN238の処理へと移行する。なお、ステップN236の再帰処理時に一つにまとめられた状態はないので、遷移先状態の集合はgn={1,2,3}となる。そのため、ステップN239〜N243の処理では変化は生じない。なぜならば、集合gnに含まれる各状態の入力記号bに対応する遷移元状態の数は全て1であるからである。
次に、探索部12は、ステップN244〜N248の処理を行うことになる。集合Ψnscの要素数は1なので、このループ内の処理はψnsc={(1,4),(2,5),(3,6)}、xlevel=1として1回だけ行われることになる。
ステップN245で集合gに含まれる状態の依存情報が作成されることになり、ψsc={(4,4),(5,5),(6,6)}となる。このとき、|S|=1であるため、ステップN246の条件が満たされることになり、探索部12は、ステップN247でη={{4,5,6}}を取得する。そして、探索部12は、ステップN248の処理で、Ψsc={({(4,5),(5,5),(6,6)},1)}を取得する。そして、ステップN254において、探索部12は、Ysc={{({(4,4),(5,5),(6,6)},1)}}と、H={{{4,5,6}}}とを取得する。
現在、Σg={b,c}であり、先ほど入力記号bに関する処理は終了したので、今度は入力記号cに関する処理を行う。すると、ステップN231では、γn={(7,1),(8,2)}となる。経路番号が変わっているが、これは、サイズが|γ|より減っており、経路番号の付け替えが可能であるためである。なお、理由はサブプログラム“search_equiv”の説明の際に述べたとおりである。
今、G={{1,2,3,7},{4,5,6}}であるので、これと集合γnの要素である2つ組のうち、左側の値として記録されている状態との積集合をとっても、サイズが2以上になるものはない。したがって、ステップN233〜N237では変化は生じない。そして、ステップN238の処理結果は、gn={7,8}となる。
ステップN239〜N243のループにおいて、qn=7の場合は遷移元状態が一つのみなので、qn=8の場合のみを考えればよい。qn=8のときステップN240でgs={4,5}となる。このとき、|gs|=2となるので、これは1よりも大きい。したがって、ステップN241が満たされ、ステップN242へと処理が移行する。続くステップN242でη={{4,5}}となり、ステップN243でΨsc={({(4,4),(5,5)},1)}となる。
次いで、ステップN244〜N248の処理は集合Ψnscが空集合φなので、何も処理されない。これは、σ=cに対応するループの最初の行であるステップN230の処理で、集合Ψnscが空集合φになっているからである。
続いて、探索部12がステップN254を実行すると、Ysc={{({(4,4),(5,5),(6,6)},1)},{({(4,4),(5,5)},1)}}と、H={{{4,5,6}},{{4,5}}}のようになる。これで集合Σgに含まれる入力記号に対する処理を全て終えたので、ステップN255の処理に移行する。
続くステップN255では、探索部12が集合Hから要素を一つ選択して集合ηに設定する。なお、ここではη={{4,5,6}}を選択したとする。この場合、集合ηに含まれる要素は一つであるため、探索部12は、区別不可能集合生成部123を用いて、gs={4,5,6}に対してサブプログラム“search_sharable_state”を実行する。なお、H\{η}={{{4,5}}}である。
サブプログラム“search_sharable_state”が実行されると、引数として集合gsとH\{η}とが渡されているので、gstart={4,5,6}、H={{{4,5}}}となる。集合Hは空集合φではないので、ステップN293から実行されることになる。
区別不可能集合生成部123は、ステップN293において、集合Hから任意の要素を一つ取り出す。いま、集合Hには一つしか要素がないので、η={{4,5}}となる。さらに集合ηの要素は一つなので、ステップN296〜N298の処理はg′={4,5}に対して一度だけ実行されることになる。
続いて、区別不可能集合生成部123は、ステップN296の処理を実行すると、gis={4,5,6}∩{4,5}={4,5}となる。このとき|gis|=2であるため、区別不可能集合生成部123は、ステップN297の条件を満たすと判定し、ステップN298の処理を実行する。次いで、区別不可能集合生成部123は、ステップN298で再帰的にサブプログラム“search_shared_state”を実行する。再帰的に呼び出されたとき、引数はgstart={4,5}、H=φである。したがって、ステップN291の条件が満たされ、ステップN292で{{4,5}}が戻り値として返されることになる。この再帰呼び出しから戻ると、ステップN298でその結果が集合Gsに追加され、Gs={{4,5}}となる。そして、ステップN299でこの集合Gsが戻り値として返される。
サブプログラム“search_shared_state”が完了すると、ステップN255に処理が戻る。集合ηの要素は一つなので、これ以上“search_shared_state”を実行する必要はない。したがって、Gshare={{4,5}}となる。
続くステップN256において、探索部12は集合Gshareに含まれる要素を夫々併合する。今、|S|=1であるため、D[1]={{(1,4),(2,5),(3,6)}}である。ここで、探索部12は、状態併合部121を用いてサブプログラム“merge_states”を実行すると、このときの引数はGshare={{4,5}}、Delm={{(1,4),(2,5),(3,6)}}となる。集合Gshareのサイズは1なので、状態併合部121は、ステップN302でgs={4,5}を選択する。
状態併合部121は、ステップN303で集合gsから任意の要素を一つ取り出し、rに代入する。ここで取り出した状態は、一つにまとめられる状態の集合の代表(代表状態)であり、削除されずに残ることになる。ここでr=4とすると、状態併合部121は、ステップN304〜N306において、gs\{r}に含まれる状態をr=4に併合する。今の場合はqe=5であるため、状態5を状態4へと併合すると、図16に示したDFAは図21となる。なお、図21は、図16に示したDFAの状態併合後の構成を示した図である。
図21に示したように、状態5は併合により不要となり削除対象となるので、状態併合部121は、ステップN306において、qe=5をQeに追加する。したがって、Qe={5}となる。
続いて、状態併合部121は、Delmに含まれる各要素について、ステップN307〜N313の処理を実行する。今はDelmに含まれる要素は一つであるため、ψ={(1,4),(2,5),(3,6)}の場合のみを処理すればよい。ステップN308では、集合gsに含まれる状態を依存先の状態qdとするようなψに含まれる2つ組の依存元状態qsから構成される集合を得ることになる。
gs={4,5}であるため、ψに含まれる要素である2つ組の2番目の要素(依存先状態)が4であるような1番目の要素(依存元状態)の値は1であり、同様に2番目の要素(依存先状態)が5であるような1番目の要素(依存元状態)の値は2である。したがって、g={1,2}となる。|g|=2であるためステップN309の条件を満たし、状態併合部121は、ステップN310以降の処理を実行することになる。
ステップN310では、状態併合部121が、代表状態を選択する。ここでは状態1を選択することにする。集合gに含まれる状態のうち、残りは状態2だけとなるため、図22に示したように、ステップN312で状態1と状態2とを併合する。なお、図22は、図21に示したDFAの状態併合後の構成を示した図である。
図22に示したように、状態2は併合により不要となり削除対象となるので、状態併合部121は、ステップN313において、qe=2をQeに追加する。その結果、 Qe={2,5}となる。そして、状態併合部121は、他に処理する要素が集合Gshareに含まれないと判定するため、ステップN314に処理が移り、削除された状態の集合Qeを戻り値として返す。また、サブプログラム“merge_states”の処理が終了したので、ステップN256の処理に戻る。なお、戻り値は集合geraseに代入されるので、gerase={2,5}となる。
ステップN257では、探索部12が削除された状態を含む2つ組を、集合Yscから除去する。ここで、ステップN257の処理前では、Ysc={{({(4,4),(5,5),(6,6)},1)},{({(4,4),(5,5)},1)}}であるが、処理後はYsc={{({(4,4),(6,6)},1)},{({(4,4)},1)}となる。
また、探索部12は、ステップN258を実行するため、集合Yscから要素を一つ取り出し集合Ψとする。ここでは、Ψ={({(4,4)},1)}とする。さらに、その要素である2つ組からψ={(4,4)}となる。しかし、ψは要素を一つしか含んでいないので、サブプログラム“search_sharable_state_candidate”を実行しても、ステップN330が満たされることがないので、結局、Ψsc=φとなる。さらに、探索部12がステップN259を実行しても、Ψsc=φとなるため、ステップN260〜N265の処理は実行されない。
D[1]={{(1,4),(2,5),(3,6)}}であるが、この情報はもう不要であるため、探索部12は、ステップN264の処理でDを空集合φへと置き換える。続くステップN267で、探索部12は、スタックSに格納された一番上の要素を削除し、ステップN268の処理に移行する。このとき、Ψsc=φであるのでステップN268の条件は満たされ、ステップN269へと処理が移行する。具体的には、g={4,5,6}、G={{1,2,3,7},{4,5,6}}であるため、G={{1,2,3,7}}となる。
また、gerase={2,5}であるため、探索部12は、ステップN270において集合Gの各要素から集合geraseに含まれている状態を取り除くと、G′={{1,3,7}}となる。そのため、ステップN271の戻り値は({{1,3,7}},φ)となり、“simin”のステップN205に戻る。ステップN205において、状態数削減処理部10は“search_equiv”の戻り値を集合Gに代入する。その結果、G={{1,3,7}}となるため、ステップN203の条件を満たし、状態数削減処理部10がステップN204の処理を実行することでg={1,3,7}となる。
続くステップN205において、状態数削減処理部10は、これまでと同様に探索部12を用いg={1,3,7}について“search_equiv”を実行する。なお、g={1,3,7}の場合、“search_equiv”のステップN235の条件を満たすことはなく、また、ステップN241の条件を満たすこともない。一方、ステップN268の条件を満たすため、探索部12は、集合Gからg={1,3,7}が取り除かれ、集合Gは空集合φとなる(ステップN269)。
そして、“search_equiv”の戻り値はG′=(φ,φ)となり、“simin”のステップN205に再び戻る。ステップN205において、状態数削減処理部10は“search_equiv”の戻り値を集合Gに代入する。その結果、G=φであるため、ステップN203の条件を満たさなくなり、処理が終了する。以上の処理により、処理対象としたDFAの状態数は最小化されることになる。
次に、依存情報の付け替えが発生する場合の状態数削減処理部10の動作について説明する。図23は、DFAの一例を示した図である。記法は図11と同じである。以下、図23に示したDFAを処理対象として説明を進める。
まず、状態数削減処理部10は、図23に示した処理対象となるDFAに対し、メインプログラム“simin”を実行していく。まず、DFAを構成する状態を分類すると、G={{1,2},{3,4},{5,6}}が得られる。図24は、図23に示したDFAの状態分類後の構成を示した図である。ここで、破線で囲った部分が夫々の分類を表しており、状態1、2と、状態3、4と、状態5、6とが夫々1つの分類になっていることが分かる。
ここではまず、{1,2}についてサブプログラム“search_equiv”が実行されたとする。ステップN221〜ステップN228までの処理で、γ={(1,1),(2,2)}、g={1,2}、Σg={a}、S={{(1,1),(2,2)}}が得られる。続くステップN229の処理でσ=aとなり、ステップN231の処理でγn={(3,1),(4,2)}となる。この集合γnはスタックSには存在しないので、ステップN233〜ステップN248の処理が行われる。
ステップN233〜ステップN237の処理のうちで、ステップN235の条件を満たすのは、γni={(3,1),(4,2)}のみである。そのため、探索部12は、この集合γniについてサブプログラム“search_equiv”を再帰的に実行する。この再帰処理時のステップN221〜ステップN228までの処理で、γ={(3,1),(4,2)}、g={3,4}、Σg={a,b}、S={{(1,1),(2,2)},{(3,1),(4,2)}}が得られる。
続くステップN229からの処理について、まずσ=aとして処理をしていく。すると、ステップN231でγn={(5,1),(6,2)}となる。この集合γnもスタックSには存在しないので、ステップN233〜ステップN248の処理が行われる。
ステップN233〜ステップN237の処理のうちで、ステップN235の条件を満たすのは、γni={(5,1),(6,2)}のみである。そのため、探索部12は、この集合γniについてサブプログラム“search_equiv”をさらに再帰的に実行する。この再帰処理時のステップN221〜ステップN228までの処理で、γ={(5,1),(6,2)}、g={5,6}、Σg={b}、S={{(1,1),(2,2)},{(3,1),(4,2)},{(5,1),(6,2)}}が得られる。
続くステップN229からの処理は、σ=bとして行われる。すると、ステップN231でγn={(3,1),(4,2)}となる。この集合γnはスタックSに存在するのでステップN249以降の処理が行われる。ステップN250でψsc={(5,3),(6,4)}、ステップN251でΨsc={({(5,3),(6,4)},2)}となる。ステップN252の条件は満たさないので、次はステップN254が処理される。
ステップN254では、Ysc={{({(5,3),(6,4)},2)}}、H={{}}となる。他に処理する入力記号は集合Σgに含まれていないので、次はステップN255が処理されることになる。集合Hには空の集合が一つ含まれるのみであるため、ステップN255の処理結果はGshare=φとなる。したがって、ステップN256で一つにまとめられる状態はなく、gerase=φとなる。また、gerase=φであるため、ステップN257の処理で集合Yscに変化は生じない。
続くステップN258では、Ψsc={({(5,3),(6,4)},2)}となる。今、|S|=3であるため、ステップN259で集合Ψscに変化は生じない。また、ステップN260とN261との処理で、D[2]={{(5,3),(6,4)}}となる。D[3]=φであるので、ステップN264とN265の処理が実行されることはない。また、ステップN266の実行でD[3]が変化することはなく、空集合φのままである。
ステップN267でスタックSの一番上の要素が取り除かれ、S={{(1,1),(2,2)},{(3,1),(4,2)}}となる。集合Ψscは空集合ではないのでステップN268の条件は満たされず、ステップN269の処理が実行されることはない。また、集合geraseは空集合であるので、ステップN270ではG′={{1,2},{3,4},{5,6}}が得られる。そして、ステップN271で戻り値として集合G′と集合Ψscとが返る。
ステップN236に戻ってくるので、得られた戻り値によりG={{1,2},{3,4},{5,6}}、Ψnsct={({(5,3),(6,4)},2)}となる。また、ステップN237でΨnsc={({(5,3),(6,4)},2)}となり、ステップN238でgn={5,6}となる。
ステップN239〜N243の処理では、ステップN241の条件が満たされることがないので、ステップN242とN243の処理が行われることはない。集合Ψnscには要素が一つ含まれているので、ステップN244でψnsc={(5,3),(6,4)}、xlevel=2となり、これについてステップN245〜N248の処理が行われる。
ステップN245の処理では、ψsc={(3,3),(4,4)}となる。|S|=2であるため、ステップN246の条件を満たし、ステップN247でη={{3,4}}となる。ステップN248では、Ψsc={({(3,3),(4,4)},2)}となる。また、ステップN254では、Ysc={{({(3,3),(4,4)},2)}}、H={{{3,4}}}となる。
Σg={a,b}のうち、aについては処理が終わったので、次はσ=bとしてステップN230〜N254までの処理を行う。ステップN231でγn={(1,1),(2,2)}となる。このとき、スタックSに集合γnは存在するので、ステップN232の条件は満たされず、ステップN250からの処理が実行される。
ステップN250では、ψsc={(3,1),(4,2)}となる。また、ステップN251では、Ψsc={({(3,1),(4,2)},1)}となる。ステップN252の条件は満たさないので、ステップN253は実行されない。続くステップN254で、Ysc={{({(3,3),(4,4)},2)},{({(3,1),(4,2)},1})、H={{{3,4}},{}}となる。
集合Σgに含まれる全ての入力記号について処理が完了したので、次はステップN255が実行される。ステップN255では、Gshare=φとなる。そのため、ステップN256でまとめられる状態はなく、gerase=φとなる。gerase=φであるため、ステップN257で集合Yscに変化が生じることはない。
続くステップN258では、まず集合Yscから要素が一つ選択される。ここでは、Ψ={({(3,3),(4,4)},2)が選択されたとする。そして、探索部12は、ψ={(3,3),(4,4)}、xlevel=2、Ysc\{Ψ}={{({(3,1),(4,2)},1)}}を夫々第1、第2、第3引数として、区別不可能候補集合生成部124を用いて“search_sharable_state_candidate”を実行する。
“search_sharable_state_candidate”では、ステップN321の条件を満たさないため、ステップN322の処理は実行されず、続くステップN323で集合Yから要素が一つ選択される。今、集合Yの要素は一つしかない。したがって、Ψ={({(3,1),(4,2)},1)}となる。集合Ψのサイズは1であるため、ステップN325ではψ={(3,1),(4,2)}、xlevel=1となる。また、xstart=2であるため、ステップN326の条件は満たされない。したがって、ステップN329の処理が実行される。このとき、ψstart={(3,3),(4,4)}であるので、ψis={(3,1),(4,2)}となる。
また、|ψis|=2であるため、ステップN331の処理が実行され、xis=1となる。ステップN332で、“search_sharable_state_candidate”が引数ψis={(3,1),(4,2)}、xis=1、Y\{Ψ}=φで再帰的に実行される。すると、ステップN321の条件を満たすので、ステップN322で戻り値を{({(3,1),(4,2)},1)}としてステップN332へと処理が移行する。その結果、Ψs={({(3,1),(4,2)},1)}となる。他に処理する集合Ψの要素はないので、ステップN333が実行され、集合Ψsを戻り値として“search_equiv”のステップN258の処理に戻る。
ステップN258では、他に処理すべき集合Ψの要素はないので、Ψsc={({(3,1),(4,2)},1)}となる。|S|=2であるため、ステップN259の処理では集合Ψscは変化しない。また、ステップN260とN261とにより、D[1]={{(3,1),(4,2)}}となる。
次に、ステップN262〜N265の処理が実行される。これらの処理によって、D[2]に記録されている依存関係の依存先状態が変更されることになる。Ψsc={({(3,1),(4,2)},1)}であるので、ステップN262でψsc={(3,1),(4,2)}、xlevel=1となる。また、ステップN263でd={(5,3),(6,4)}となり、ステップN264では、dp={(5,1),(6,2)}となる。
ここで、dに含まれる2つ組(5,3)を例に説明する。2つ組(5,3)は依存元状態が状態5、依存先状態が状態3である。この状態3を依存元状態とするψscの要素は(3,1)である。この2つ組の依存先状態は状態1である。したがって、dに含まれる2つ組(5,3)の依存先状態は状態1となり、dpに2つ組(5,1)が記録される。また、dpの残りの2つ組(6,2)についても同様である。
続くステップN265では、D[1]={{(3,1),(4,2)},{(5,1),(6,2)}}となる。他に処理すべき集合ΨscやD[2]の要素はないので、ステップN266が実行され、D[2]=φとなる。また、ステップN267の処理により、S={{(1,1),(2,2)}}となる。
集合Ψscは空集合ではないので、ステップN268の条件を満たさず、ステップN269の処理は実行されない。また、削除された状態もないので、ステップN270の結果、G′={{1,2},{3,4},{5,6}}となる。続くステップN271では、戻り値として集合G′と集合Ψscとが返る。そして、ステップN236の処理に再び戻るので、得られた戻り値によりG={{1,2},{3,4},{5,6}}、Ψnsct={({(3,1),(4,2)},1)}となる。
次いで、ステップN237で、Ψnsc={({(3,1),(4,2)},1)}となり、ステップN238で、gn={3,4}となる。また、ステップN239〜N243の処理では、ステップN241の条件を満たすことはないので、ステップN242とN243とが実行されることはない。
集合Ψnscには要素が一つあるので、ステップN244〜N248の処理が行われる。ステップN245の処理により、ψsc={(1,1),(2,2)}となる。今、xlevel=1かつ|S|=1であるため、ステップN246の条件を満たし、ステップN247でη={{1,2}}となる。ステップN248でΨsc={({(1,1),(2,2)},1)となる。また、ステップN254でYsc={{({(1,1),(2,2)},1)}}、H={{{1,2}}}となる。他に処理する集合Σgの要素は残っていないため、処理をステップN255へと移す。
ステップN255が実行されることでGshare={{1,2}}となる。続くステップN256で、探索部12は、状態併合部121を用いてサブプログラム“merge_states”を実行する。このとき、Gshare={{1,2}}、Delm={{(3,1),(4,2)},{(5,1),(6,2)}}である。
“merge_states”では、集合Gshareに一つ要素があるので、それがステップN302で選択されると、gs={1,2}となる。そしてステップN303〜N313までの処理が行われる。ステップN303では、集合gsに含まれる状態が一つ選択される。ここではr=1が選択されたとする。集合gsに含まれるr以外の状態は状態2のみなので、これをステップN305の処理で状態rに併合する。不要になった状態2は、ステップN306でQeに追加され、Qe={2}となる。
また、Delmのサイズが2なので、それぞれの要素についてステップN308〜N313の処理が実行される。ここではまず、ψ={(3,1),(4,2)}から処理を行う。ステップN308でg={3,4}となるので、ステップN309の条件を満たす。そのため、続くステップN310で集合gから任意の要素が一つ選択される。ここではr′=3とする。
そして、ステップN312で、集合gからr′を除いた状態を、状態r′に併合する。このとき、qe=4のみを考えればよいので、状態4は状態3へとまとめられることになる。続くステップN313では、Qe={2,4}となる。
次にψ={(5,1),(6,2)}として処理を行う。先ほどと同様に処理すると、ステップN308でg={5,6}となり、ステップN310でr′=5とすると、ステップN312で状態6が状態5にまとめられる。また、ステップN313でQe={2,4,6}となる。
全ての集合GshareとDelmについて処理が完了したので、ステップN314でQeを戻り値として“search_equiv”のステップN256に戻る。これにより、gerase={2,4,6}となる。
ステップN257で、集合geraseに含まれる2つ組を集合Yscから取り除き、Ysc={{({(1,1)},1)}となる。なお、状態を併合するには二つ以上の2つ組が必要なので、2つ組が一つしかない集合は不要であり、この時点で削除してしまってもよい。ステップN258でΨsc={({(1,1)},1)}となる。
|S|=1であるため、ステップN259でΨsc=φとなる。したがって、ステップN260〜N265までの処理では何も変化しない。続くステップN266でD[1]=φとし、ステップN267でS=φとなる。集合Ψscは空集合φであるため、ステップN268の条件が満たされ、ステップN269の処理で集合Gから集合gに一致する要素が取り除かれる。今、g={1,2}、G={{1,2},{3,4},{5,6}}であるので、G={{3,4},{5,6}}となる。
ステップN270で、G={{3,4},{5,6}}からgerase={2,4,6}に含まれる状態を取り除く。すると。{{3},{5}}となるが、各要素のサイズが1以下のものは含めないので、結局、G′=φとなる。そのため、ステップN271での戻り値は(φ,φ)となる。
“simin”のステップN205に戻ると、G=φとなる。これでステップN203の条件を満たさなくなるので処理は終了する。図25は、図23に示したDFAの状態併合後の最終的な構成を示した図である。以上の処理により、処理対象としたDFAの状態数は最小化されることになる。
以上のように、本実施形態によれば、区別可能な状態の組合せを状態の2つ組の集合として持つ必要がないので、大きな記憶域を使用することがなく、さらにDFAを構成する状態を段階的に併合することで、漸進的に決定性有限状態オートマトンの状態数を減少させることができる。
さらに、他の全ての状態と区別可能であると判明した状態は、その時点で集合Gから取り除かれることになるので、区別可能であると判断された状態に対して、再度区別可能であるか否かの判定が行われることがなくなり、処理の効率化を図ることができる。
[第2の実施形態]
上述した第1の実施形態の構成では、1つの循環経路上にある状態数が増加すると、処理に時間がかかるようになる。具体的には、区別不可能候補である状態の集合が集合Gから除去されないため、既に区別不可能候補であると判明していても、その状態の集合に対して何度も“search_equiv”が実行されることになる。そこで、第2の実施形態では、区別不可能候補であると判明した状態の集合に対して、処理が繰り返し行われないよう構成した形態について説明する。なお、第1の実施形態と同様の構成要素については、同一の符号を付与し説明を省略する。
図26は、第2の実施形態に係る情報処理装置の機能的構成を示したブロック図である。同図に示したように、情報処理装置は、CPU1とROM4又は記憶部6に予め記憶された所定のプログラムとの協働により実現される機能部として、状態数削減処理部20を備えている。
状態数削減処理部20は、状態分類部11と探索部21とを有し、上述したメインプログラム“simin”を実行することで、処理対象となるDFAの状態数を漸進的に削減する。
探索部21は、図26に示したように、状態併合部121と、遷移先集合生成部122と、区別不可能集合生成部123と、区別不可能候補集合生成部124と、実行状態判定部211とを有している。探索部21は、上述したサブプログラム“search_equiv”に対応する、後述するサブプログラム“search_equiv2”を実行することで、処理対象のDFAに含まれる区別不可能な状態同士を一つの状態に併合する。なお、実行状態判定部211は、後述するサブプログラム“find_src_in_D”により実現される機能部である。実行状態判定部211の動作については後述する。
図27は、サブプログラム“search_equiv2”の擬似コードの一例を示した図である。ここで、ステップN401〜N411の処理は、“search_equiv”でのステップN221〜N231と同様である。
ステップN412において、探索部21は、後述するステップN418〜N420の処理の実行状態を記録するためのbfoundを“false”に設定する。続いて、探索部21は、遷移先状態の集合γnのサイズが集合γのサイズと同じであるか否かを判定し(ステップN413)、同じであればステップN414〜N421の処理を行う。
ステップN414では、探索部21が、実行状態判定部211を用いてサブプログラム“find_src_in_D”を実行し、集合γnに含まれる状態が依存元状態となる依存関係をテーブルDから取得する。なお、“find_src_in_D”については後述する。
次いで、探索部21は、集合γに含まれる状態の依存先状態を決定する(ステップN415)。具体的には、集合γに含まれる状態、つまり集合gに含まれる状態をq、qの入力記号σによる遷移先をqs、qsの依存先状態をqd とするとき、qの依存先状態をqdとする。探索部21は、集合gに含まれている状態に対してそれぞれqdを求め、2つ組(q,qd)の集合を生成し、それをψとする。
続いて、探索部21は、集合γとψを用いて集合γの各要素に対応する依存先状態の集合γdを生成する(ステップN416)。探索部21は、集合γdがスタックSに存在するか否かを判定し(ステップN417)、存在すると判定した場合、ステップN418〜N420の処理を実行する。
ステップN418では、探索部21がψとxlevelとの2つ組を集合Ψscに追加する。続いて、探索部21は、xlevelがスタックSのサイズと等しいか否かを判定し(ステップN419)、等しいときのみステップN420の処理を実行する。ステップN420では、探索部21が、ψに含まれる依存元状態から成る状態の集合を集合ηに追加する。そして、探索部21は、ステップN418〜N420の処理を実行したので、bfoundを“true”に設定する(ステップN421)。
続くステップN422において、探索部21は、bfoundが“false”か否かを判定し、“false”と判定した場合には、第1の実施形態で説明した“search_equiv”のステップN232〜N253と同様の処理を実行する(ステップN423)。なお、“search_equiv”のステップN236では、“search_equiv”を再帰的に実行しているが、本実施形態では、“search_equiv2”を実行するようにする。
ステップN424は、第1の実施形態で説明した“search_equiv”のステップN254と同様の処理であり、探索部21は、第1の実施形態1で説明したように処理する。
ステップN425は、第1の実施形態で説明した“search_equiv”のステップN255〜N267と同様の処理であり、探索部21は、第1の実施形態1で説明したように処理する。なお、ステップN425は、ステップN404の条件判定で、集合Σgが空集合φでなかった場合のみ実行される処理群である。
ステップN426は、第1の実施形態で説明した“search_equiv”のステップN268〜N271と同様の処理であり、探索部21は、第1の実施形態1で説明したように処理する。
次に、図28を参照して、ステップN414のサブプログラム“find_src_in_D”について説明する。ここで、図28は、サブプログラム“find_src_in_D”の擬似コードの一例を示した図である。
まず、実行状態判定部211は、集合γnから経路番号を取り除いた状態の集合をgnとする(ステップN431)。続いて、実行状態判定部211は、ステップN432のforeach文に従い、テーブルDに含まれている要素(xlevel,y)毎にステップN433〜N436の処理を実行する。
ステップN433において、実行状態判定部211は、foreach文に従い、yに含まれる要素ψ毎にステップN434〜N436の処理を実行する。ステップN434では、実行状態判定部211が、ψの要素である(依存元状態,依存先状態)の2つ組のうち、依存元状態のみを取り出し、それらを状態の集合gsとする。続いて、実行状態判定部211は、集合gnと集合gsとが等しいか否かを判定し(ステップN435)、等しいと判定した場合、そのときのψとxlevelとの2つ組を戻り値として、“search_equiv2”のステップN414に戻る(ステップN436)。
一方、ステップN432とN433による全ての繰り返しでステップN435の条件を満たさなければ、ステップN437の処理が実行されることになる。この場合、実行状態判定部211は、空集合と零の2つ組(φ,0)を戻り値として、“search_equiv2”のステップN414に戻る(ステップN437)。
上述した処理により、既に循環経路上にあると判明している状態に対して再度アルゴリズム“search_equiv2”を実行する必要がないので、循環経路上の状態が多数存在する場合には、第1の実施形態に比べてより少ない処理量で状態数削減処理を行うことが可能できる。また、状態数削減処理を中断せず、最後まで実行すると状態数最小のDFAを得ることができる。
[第3の実施形態]
DFAの場合には、終了状態が複数あっても出て行く遷移の入力記号の集合が同じであれば、終了状態同士を一つの状態に併合することができる。しかしながら、重み付き有限状態オートマトンのように終了状態に重みが割り当てられている場合、異なる重みが割り当てられている終了状態同士は区別可能であるので、一つにまとめてはならない。その理由は、一つにまとめてしまうと、得られる重みが変わってしまう可能性があるためである。
そこで、第3の実施形態では、終了状態に種類がある場合、言い換えると終了状態に付加情報がある場合に適用することが可能な構成について説明する。なお、第1の実施形態と同様の構成要素については、同一の符号を付与し説明を省略する。
図29は、第3の実施形態に係る情報処理装置の機能的構成を示したブロック図である。同図に示したように、情報処理装置は、CPU1とROM4又は記憶部6に予め記憶された所定のプログラムとの協働により実現される機能部として、状態数削減処理部30を備えている。
状態分類部31は、処理の対象となるDFAに含まれる各状態を、その状態の終了性と、出て行く遷移に付随する入力記号の種別と、終了状態の付加情報とが同じ状態毎に分類する。ここで付加情報は、例えば、上述した重みであってもよいし、距離やコスト等の数値で表すことができるものであってもよい。さらに文字や記号、文字列、記号列等であってもよい。
本実施形態では、付加情報が複数ある場合をも考慮する必要があるため、状態q∈Fの付加情報の集合をρ(q)と表す。そして状態qが終了状態である場合は、終了状態の付加情報が割り当てられ、終了状態でない場合は、ρ(q)=φとする。このρ(q)を用いるように変更した“create_class”の擬似コードを図30に示す。
図30は、サブプログラム“create_class”の擬似コードの一例を示した図である。
まず、状態分類部31は、戻り値に使用する状態の集合を要素とする集合Gを空集合φで初期化するとともに、出て行く遷移の入力記号の集合と付加情報とから構成される2つ組に、状態の集合を関連付けて記憶するためのテーブルCを空集合φで初期化する(ステップN501)。
次いで、状態分類部31は、ステップN502のforeach文に従い、Qに含まれる各状態qについて、ステップN503とN504との処理を実行する。ステップN503では、状態分類部31が、qから出て行く遷移に付随する入力記号の集合を生成し、集合Σqに代入する(ステップN503)。そして、状態分類部31は、集合Σqと付加情報の集合ρ(p)との2つ組に関連付けてテーブルCに記憶されている状態の集合にqを追加する(ステップN504)。
続いて、状態分類部31は、ステップN505のforeach文に従い、テーブルCに含まれる各要素に対して、ステップN506とN507との処理を実行する。ここで、状態分類部31は、出て行く遷移の入力記号の集合と付加情報の集合との2つ組に関連付けられている状態の集合gのみを、ステップN506とN507との処理で使用する。
ステップN506において、状態分類部31は、集合gのサイズが2以上であるか否かを判定し、2以上と判定した場合、集合Gに集合gを追加する(ステップN507)。最後に、状態分類部31は、この“create_class”での処理結果として集合Gを返し、メインプログラム“simin”のステップN202に戻る。
以下、図31〜33を参照し、本実施形態での状態数削減処理部30の動作について説明する。図31は、DFAの一例を示した図である。同図において各遷移に割り当てられている入力記号を“/”の左側に表し、重みを右側に表している。また、終了状態の“/”の左側に状態番号を表し、右側に終了状態の重みを表している。各状態の付加情報の集合は、ρ(0)=φ、ρ(1)=φ、ρ(2)=φ、ρ(3)=φ、ρ(4)={1}、ρ(5)={1}、ρ(6)={2}となる。
図31に示した重み付きDFAに、入力記号列baを入力すると、状態0、2、5と遷移するため、遷移に割り当てられている重みは3と2となり、終了状態の重みは1となる。重みを加算する場合には、3+2+1=6となり、入力記号列baをこの重み付きDFAに入力すると、重み6が得られることになる。
本実施形態での状態数最小化処理は、遷移に割り当てられている入力記号と重みとの組を、一つ入力記号とみなして処理を行うことになる。例えば、状態0から状態1への遷移に割り当てられている入力記号ならば、a/1を一つの入力記号とするということである。
以下、本実施形態の状態数削減方法を用いて、図31のDFAの状態数を削減していく。まず、メインプログラム“simin”では、図30で説明したサブプログラム“create_class”が実行される。すると、G={{1,2,3},{4,5}}となる。この状態を図示すると、図32のようになる。ここで、図32は、図31に示したDFAの状態分類後の構成を示した図である。ここで、破線で囲った部分が夫々の分類を表しており、状態1、2、3と、状態4、5とが夫々1つの分類になっていることが分かる。
メインプログラム“simin”の残りの処理は、第1の実施形態と同様にすればよく、状態4と状態5とが一つにまとめられるとともに、状態1と状態2とが一つにまとめられることになる。その結果、図31のDFAは図33のようになる。ここで、図33は、図31に示したDFAの状態削減後の構成を示した図である。
図33からも明らかなように、最小化後のDFAに入力記号列baを入力すると、状態0、1、4と遷移し、その重みは3+2+1で計6となり、最小化前と同じ重みが得られることがわかる。
以上のように、第3の実施形態によれば、重み付き有限状態オートマトンのように終了状態に種類が付加されている場合であっても、終了状態の種類が異なる状態は一つに併合しないようにしつつ、状態数を漸進的に削減することができる。
[第4の実施形態]
第4の実施形態では、循環経路が存在しないDFA(非循環決定性有限オートマトン)を処理対象とした場合の形態について説明する。なお、第1の実施形態と同様の構成要素については、同一の符号を付与し説明を省略する。
図34は、第4の実施形態に係る情報処理装置の機能的構成を示したブロック図である。同図に示したように、本実施形態に係る情報処理装置は、CPU1とROM4又は記憶部6に予め記憶された所定のプログラムとの協働により実現される機能部として、状態数削減処理部40を備えている。
状態数削減処理部40は、状態分類部11と探索部41とを有し、後述するメインプログラム“simin_ac”を実行することで、処理対象となる非循環決定性有限オートマトンの状態数を漸進的に削減する。ここで「非循環決定性有限オートマトン」とは、循環経路が存在しないDFAのことを意味する。また。「循環経路が存在しない」とは、全ての状態q∈Qに対して、δ(q,w)=qを満たすような入力記号列w∈Σ*\{ε}が存在しないことをいう。なお、w∈Σ*\{ε}であるため、wに空入力記号列は含まれない。
探索部41は、図34に示したように、状態併合部411と、遷移先集合生成部122と、区別不可能集合生成部123とを有している。探索部41は、上述したサブプログラム“search_equiv”に対応する、後述するサブプログラム“search_equiv_ac”を実行することで、処理対象の非循環決定性有限オートマトンに含まれる区別不可能な状態同士を一つの状態に併合する。
状態併合部411は、後述するサブプログラム“merge_states_ac”により実現される機能部である。状態併合部411の動作については後述する。
なお、本実施形態で処理の対象とする非循環決定性有限オートマトンには、循環経路が存在しないため、循環経路に関する処理は不要である。そのため、後述する“simin_ac”、“search_equiv_ac”及び“merge_states_ac”は、第1の実施形態で説明した“simin”、“search_equiv”及び“merge_states”から、循環経路に関する処理を除いたものとなっている。以下、順次説明する。
図35は、状態数削減処理部40が実行するメインプログラム“simin_ac”の擬似コードの一例を示した図である。まず、状態数削減処理部40は、第1の実施形態と同様、状態分類部11を用いて、終了性と出て行く遷移の入力記号とで、処理対象の非循環決定性有限オートマトンに含まれる各状態を分類し、その結果を集合Gに代入する(ステップN601)。
次いで、状態数削減処理部40は、集合Gが空集合φになるまでステップN603、N604の処理を繰り返し実行する(ステップN602)。ステップN603では、状態数削減処理部40が、集合Gから任意の要素を一つ選択し、それを集合gとする。なお、要素の選択順序は特に問わず、例えば集合gのサイズが小さいものから選択してもよいし、大きいものから選択してもよい。
続くステップN604において、状態数削減処理部40は、第1引数を集合g、第2引数を集合Gとし、探索部12を用いて、サブプログラム“search_equiv_ac”を実行する。サブプログラム“search_equiv_ac”の戻り値は、状態の集合の集合であり、状態数削減処理部40は、この戻り値を集合Gに代入する。なお、第1の実施形態とは異なり、本実施形態ではスタックSは不要である。また、経路番号も不要であるため、“add_path_index”は使用する必要がない。
次に、図36を参照して、ステップN604で実行されるサブプログラム“search_equiv_ac”について説明する。図36は、サブプログラム“search_equiv_ac”の擬似コードの一例を示した図である。
まず、探索部41は、集合gに含まれる状態から出て行く遷移に付随している入力記号を全て集め、それを集合Σgに代入する(ステップN611)。次いで、探索部41は、集合Σgが空集合φであるか否かを判定し(ステップN612)、空集合φであればステップN613の処理を実行する。また、集合Σgが空集合φでないと判定した場合、探索部41は、ステップN614以降の処理を実行する。
ステップN613において、探索部41は、状態併合部411を用いてサブプログラム“merge_states_ac”を実行することで、集合gに含まれる状態を一つの状態へと併合し、併合することで不要になった状態を集合geraseへと代入する。なお、サブプログラム“merge_states_ac”については後述する。
一方、ステップN615では、探索部41が、後の処理で使用する集合Hを空集合φとする。続いて、探索部41は、ステップN616のforeach文に従い、集合Σgに含まれる各入力記号に対して、ステップN617〜N628までの処理を実行する。
ステップN617では、探索部41が、状態の集合を要素とする集合ηを空集合φとする。次いで、探索部41は、集合gに含まれる状態からの入力記号σによる遷移先状態の集合gnを取得する。つまり、gn=δ(g,σ)となる。
続いて、探索部41は、ステップN619のforeach文に従い、集合Gの各要素に対して、ステップN620〜N622の処理を実行する。探索部41は、ステップN620において、集合Gの要素g′と集合gnとの積集合gniを算出し、この集合gniのサイズが2以上のときのみ、再帰的にサブプログラム“search_equiv_ac”を実行する(ステップN622)。なお、このときの第1引数には集合gniが、第2引数には集合Gが渡される。また、再帰処理から戻ってくると、探索部41は、その戻り値を集合Gとする。
サブプログラム“search_equiv_ac”の再帰処理中に状態がまとめられる可能性があるので、探索部41は、ステップN618と同様にステップN623で集合gnを更新する。なお、ステップN622が実行されていない場合には、ステップN623を実行する必要はない。
続いて、探索部41は、ステップN624のforeach文に従い、集合gnに含まれる各状態qn対して、ステップN625〜N627の処理を実行することで、入力記号σを伴う遷移に関して区別不可能な状態を見つける。
探索部41は、入力記号σでqnへと遷移するような集合gに含まれる状態の集合を求め、それを集合gsとする(ステップN625)。次いで、探索部41は、集合gsのサイズが2以上か否かを判定し(ステップN626)、集合gsに2以上の状態が含まれていると判定した場合、それを集合ηへと追加する(ステップN627)。
集合gnに含まれる全ての状態に対し、ステップN625〜N627の処理が完了すると、探索部41は、そのときの集合ηを集合Hに追加する(ステップN628)。また、集合Σgに含まれる全ての入力記号に対し、ステップN617〜N628の処理が完了すると、探索部41は、区別不可能集合生成部123を用いてサブプログラム“search_sharable_state”を実行することで、区別不可能な状態の集合を求め、それを集合Gshareとする(ステップN629)。
続いて、探索部41は、状態併合部411を用いて後述するサブプログラム“merge_states_ac”を実行することで、区別不可能な状態を一つにまとめ、その結果不要になった状態を集合geraseとする(ステップN630)。
続くステップN631では、探索部41が、次の2つの条件を満たす集合G′を集合Gから生成する。条件1:集合gに一致する集合Gの要素は集合G′には含めない。条件2:不要になった集合geraseに含まれる状態を集合Gの要素から取り除き、その結果、要素のサイズが2以上になる要素のみを集合G′に含める。
そして、探索部41は、ステップN631で得られた集合G′を戻り値として、ステップN604の処理に返し、“search_equiv_ac”の処理を終了する。
次に、図37を参照して、ステップN613やステップN630で実行されるサブプログラム“merge_states_ac”について説明する。図37は、サブプログラム“merge_states_ac”の擬似コードの一例を示した図である。
まず、状態併合部411は、不要になった状態を記憶するためのQeを空集合φにする(ステップN641)。続いて、状態併合部411は、ステップN642のforeach文に従い、集合Gshareの各要素gsに対して、ステップN643〜N646の処理を実行する。
状態併合部411は、ステップN643において、集合gsから一つの状態に併合する際に残留させる状態を代表状態rとして選択する。なお、選択する状態は特に問わず、例えば状態番号が最小の状態を残すように選択してもよい。
続いて、状態併合部411は、ステップN644のforeach文に従い、集合gsからステップN643で選択したrを除いた各状態qeに対して、ステップN645、N646の処理を実行する。
状態併合部411は、ステップN645において、ステップN643で選択したrと、qeとを併合すると、続くステップN646において、この併合により不要となった状態qeをQeに追加する。
そして、集合Gshareの全ての要素についてステップN643〜N646の処理が完了すると、状態併合部411は、不要になった状態の集合Qeを戻り値として、呼び出し元へ処理を返し(ステップN647)、“merge_states_ac”の処理を終了する。
上記した処理で、非循環決定性有限状態オートマトンの状態数削減処理が完了することになる。このように、本実施形態によれば、循環経路のための処理を含まないため、非循環決定性有限状態オートマトンの状態数を、第1の実施形態より効率的に削減することができる。
なお、第3の実施形態で説明した、終了状態に種類があるDFAについても、そのDFAに循環経路が存在しない場合には、本実施形態の構成を適用することができる。具体的には、メインプログラム“simin_ac”のステップN601で実行するサブプログラム“create_class”を第3の実施形態説明したものと置き換えればよい。
[第5の実施形態]
第5の実施形態では、DFAの状態数削減を任意の時点で中断することが可能な構成について説明する。なお、第1の実施形態と同様の構成要素については、同一の符号を付与し説明を省略する。
図38は、第5の実施形態に係る情報処理装置の機能的構成を示したブロック図である。同図に示したように、情報処理装置は、CPU1とROM4又は記憶部6に予め記憶された所定のプログラムとの協働により実現される機能部として、状態数削減処理部50を備えている。
状態数削減処理部50は、状態分類部11と探索部12とを有し、上述したメインプログラム“simin”を実行することで、処理対象となるDFAの状態数を漸進的に削減する。
また、状態数削減処理部50は、自己が実行するメインプログラム“simin”の実行状態を監視し、操作部2等を介して状態数削減処理の中断を受け付けた場合に、現在実行中の箇所が中断可能な箇所か否かを判定し、中断可能な箇所を実行中であれば状態数削減処理を中断する。ここで「中断可能な箇所」とは、状態数削減処理を中断した場合に、この中断が行われた時点でのDFAを得ることが可能なステップ位置を意味する。
具体的に、状態数削減処理部50は、サブプログラム“merge_states”のステップN304〜N313、又は、サブプログラム“merge”の実行時に、中断不可能な箇所と判定する。この場合、状態数削減処理部50は、中断可能な箇所まで処理を継続し、この中断可能な箇所まで到達すると処理を中断し、そのときのDFAを記憶部6に記録する。なお、上述した中断不可能な箇所以外では、どこで処理を中断しても、この中断が行われた時点でのDFAを得ることが可能である。
次に、図39を参照して状態数削減処理部50の動作について説明する。ここで、図39は、状態数削減処理部50が実行する中断制御処理の手順を示したフローチャートである。なお、本中断制御処理は、上述した状態数削減処理とは独立的に実行され、操作部2等を介して入力された状態数削減処理の中断指示による割り込み発生時に実行される処理である。
操作部2等を介しユーザから記憶部6に記憶されているDFAの状態数削減が指示されると、状態数削減処理部50は、メインプログラム“simin”から始まる一連のプログラムを第1の実施形態で説明したように実行する。
状態数削減処理部50は、一連のプログラムが実行されている最中に、操作部2等を介して処理の中断指示を受け付けると(ステップN702)、現在実行している箇所が中断可能な箇所か否かを判定する(ステップN703)。ここで、中断可能な箇所を実行中と判定すると(ステップN703;Yes)、状態数削減処理部50は直ちに処理を中断し(ステップN705)、ステップN706の処理に移行する。
一方、ステップN703において、中断不可能な箇所を実行中と判定した場合(ステップN703;No)、状態数削減処理部50は、中断可能な箇所まで処理を継続し(ステップN704)、中断可能な箇所まで到達した時点で処理を中断する(ステップN705)。
続くステップN706において、状態数削減処理部50は、処理を中断した時点でのDFAを記憶部6に記録し(ステップN706)、本処理を終了する。
以上のように、第5の実施形態によれば、状態数削減処理を任意のタイミングで中断でき、そのときまでに削減できた状態数のDFAを得ることができるため、状態数の削減に時間制約があり、その制約のために最小化が完了できない場合においても、元の状態数より状態数を減少させたDFAを得ることができる。
なお、第2、第3の実施形態に対しても本実施形態と同様の構成を適用することにより、状態数削減処理を任意のタイミングで中断することができる。また、第4の実施形態に対しても本実施形態と同様の構成を適用することにより、状態数削減処理を任意のタイミングで中断することができる。ただし、中断不可能な箇所は、サブプログラム“merge_states_ac”のステップN644〜N646、サブプログラム“merge”となる。
また、本実施形態では、操作部2を介して入力される指示信号に応じて、状態数削減処理を中断する態様としたが、これに限らないものとする。例えば、図40に示したように、情報処理装置に時間計時を行うタイマ部8を設け、このタイマ部からの信号に応じて、状態数削減処理を中断する態様としてもよい。ここで、図40は、情報処理装置の他のハードウェア構成例を示したブロック図である。
図40の構成の場合、状態数削減処理を開始する前に処理時間の上限値をユーザが操作部2を通して指示し、それをタイマ部8に設定しておく。そして、ユーザがDFAの状態数削減処理を指示すると、状態数削減処理部50が、メインプログラム“simin”から始まる一連のプログラムの実行を開始するとともに、タイマ部8が計時を開始する。このとき、状態数削減処理が完了する前に設定時間を経過した旨の信号が、タイマ部8から状態数削減処理部50に伝えられると、状態数削減処理部50は、上述した中断制御処理を開始し、状態数削減処理を中断することになる。
以上、本発明に係る実施形態について説明したが、これに限定されるものではなく、本発明の主旨を逸脱しない範囲での種々の変更、置換、追加などが可能である。
例えば、上記した各実施形態の処理にかかるプログラムを、コンピュータで読み取り可能な記憶媒体に格納して提供することも可能である。記憶媒体としては、磁気ディスク、光ディスク(CD−ROM、CD−R、DVD等)、光磁気ディスク(MO等)、半導体メモリ等、プログラムを記憶でき、且つ、コンピュータが読み取り可能な記憶媒体であれば、その記憶形式は何れの形態であってもよい。
また、上記した各実施形態の処理にかかるプログラムを、インターネット等のネットワークに接続されたコンピュータ上に格納し、ネットワーク経由でダウンロードさせることにより提供するように構成しても良い。