通常の言語の単語数を数えるのはなぜ簡単ではないのですか?


8

DFA、Aが与えられた場合、L(A)がAが受け入れる単語数を示すものとします。L(A)を計算するのは簡単だと思います。Aのエンコーディングを正規表現に変換します。クリーネの星が式のどこかに現れる場合-言語は無限です。それ以外の場合:式を使用して作成できるすべての単語の組み合わせを調べて数えます(基本的に、式に+演算子がある場合は、有効な単語の量に+で接続された文字列の量を掛けます。)

これは間違っていますか?前もって感謝します


3
ε∗は無限の言語ではありません。
— David Richerby 2017年

回答:


12

ええ、あいまいさのため、これは間違っています。

次の言語について考えてみましょう: (a+aa)+a(a+ε)。

あなたの方法では、我々は4ワード、参照、A 、A 、。しかし、重複があります!特定の正規表現内で同じ単語を作成する方法は複数あります。a、aa、aa、a

より良い方法は、「デッド」状態のない、言語の最小限のDFAで動的プログラミングを使用することです。最小DFAが循環的である場合、言語は無限であるため、循環はないと想定できます。確定性とは、各単語に対してDFAを通るパスが1つしかないため、DFAを使用することが重要です。

あなたがすることは、与えられた状態で終わる単語の数の繰り返しを構築することです:

  • 1ワードは開始状態で終了します:ε
  • 各状態、終了する単語の数は、各状態で終了する単語の数の合計であり、qへの遷移があります。qq

単語の総数は、各最終状態で終了する単語の数の合計になります。


2
これらの再帰は、たとえば生成関数の場合など、常にコンピュータ代数によって解決できることに注意してください。ええ、通常の言語は実際に数えるのは簡単です。
— ラファエル

9

jmiteの答えを補足すると、「転送マトリックス」メソッドを使用して、通常の言語で単語数を計算することはそれほど難しくありません。これはjmiteの動的プログラミングと同じですが、この手法には漸近列挙などのアプリケーションがさらにあります。

DFAを指定して、行列M(Qは状態のセット)を作成します。ここで、M (i 、j )は、DFAを状態jから状態iに移動させる文字の数です。ましょう1 、Q 0及び1 Fは、初期状態に対するそれぞれ受容状態、の指標です。最後に、n = | Q | 。Q×QMQM(i,j)ji1q01Fn=|Q|

長さの単語の数はc m:= 1 F M m 1 q 0です。計算C 、M用の0 ≤ M < 2 N。もしC N + ⋯ + C 2 N - 1 > 0、次いでDFAによって受け入れ言語は無限です。それ以外の場合、言語の単語数はc 0 + ⋯ + c n − 1です。mcm:=1FMm1q0cm0≤m<2ncn+⋯+c2n−1>0c0+⋯+cn−1

(べき乗を計算する場合、mの指数関数であるエントリの大きさについて注意する必要があります。それらのサイズは多項式だけなので、結果のアルゴリズムは多項式時間で実行されます。)Mm


2
私はこのアプローチが大好きです。また、の固有値の計算は、実際には生成関数アプローチの分母の根に対応し、おそらく驚くことではないが、これらの固有値はDFAの最小化に不変であることもわかりました。ただし、これを正しく解釈する方法はまったくわかりません。M
— Lee

1
これには、生成関数であることを考えると、驚くことではないに簡素化、P (Z )= 1 F(I - Z M )- 1 1 q 0。固有値を特徴とするMのヨルダン形式を使用してこの計算をやり直すことにより、さらに明確な結果を得ることができます。P(z)=Σん=0∞1FMん1q0zんP(z)=1F(I−zM)−11q0M
— Yuval Filmus

7

実際には、クリーネの星を含む明確な正規表現のカウント式を引き続き導出できます。

:正規表現の誘導定義として考えると

e∈Re:=x∈Σ∣e0 e1∣e0+e1∣e∗

次の翻訳を検討してください正規表現を使用して、それを複素数値有理関数に変換します。[[⋅]]:Re→C(z)

[[x∈Σ]]=z[[e0 e1]]=[[e0]]×[[e1]][[e0+e1]]=[[e0]]+[[e1]][[e∗]]=11−[[e]]

この変換がで構造的帰納を行うことにより有理式を返すことを示すことができ、右側で使用されるすべての演算が有理性を保持することに注意してください。e

入力した正規表現が明確であるとすると、[で表される有理関数がe実際には、基礎となる言語によって受け入れられる単語の家族のための生成機能である Eは、その長さによってランク付け。[[e]]∈C(z)e

例えば、言語検討のランの言語定義、で区切らBを。さて、この正規表現は明確であるため、翻訳トリックを実行できます。(a∗b)∗ab

[[(a∗b)∗]]=11−[[a∗b]]=11−([[a∗]]×[[b]])=11−(11−[[a]]×z)=11−z1−z=12+12−4z

結局のところ、上記の生成関数を考えると、その係数抽出は ここで、 δ(n)={ n = 0の場合は1 、  それ以外の場合は0

[zn][[(a∗b)∗]]=2n−1+δ(n)2
δ(n)={1if n=00otherwise

実際、私たちの翻訳有理関数を生成します。部分分数分解を使用して、明確な正規表現の列挙式を作成できます。[[⋅]]

既約有理関数

r(z)+p(z)q(z)
r,p,q
r(z)+C0z−q0∗+⋯+Cnz−qn∗
where qk∗ are the roots of q(z). There's a bit of technical corner-cases (like multiplicity of roots, etc), but it's relatively easy to do coefficient extraction on the expression above:
[zn]Cz−q∗=C×q∗−n

In fact, the partial fraction decomposition generalize to multivariate rational functions, so you can actually construct counting formulas for queries such as "How many words are there where there are n as and m bs?"

Unfortunately, the extent to which this method will be useful ends when you have an ambiguous expression.

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.