Ada beberapa metode untuk melakukan konversi dari automata terbatas ke ekspresi reguler. Di sini saya akan menjelaskan yang biasanya diajarkan di sekolah yang sangat visual. Saya percaya ini adalah yang paling banyak digunakan dalam praktik. Namun, menulis algoritme bukanlah ide yang bagus.
Metode penghapusan negara
Algoritma ini adalah tentang penanganan grafik automaton dan oleh karena itu sangat tidak cocok untuk algoritma karena perlu grafik primitif seperti ... penghapusan negara. Saya akan menggambarkannya menggunakan primitif tingkat tinggi.
Ide kuncinya
Idenya adalah untuk mempertimbangkan ekspresi reguler pada tepian dan kemudian menghapus negara perantara sambil menjaga label tepi konsisten.
Pola utama dapat dilihat pada gambar di bawah ini. Yang pertama memiliki label antara yang merupakan ekspresi reguler dan kami ingin menghapus .e , f , g , h , i qp,q,re,f,g,h,iq
Setelah dihapus, kami menyusun bersamaan (sambil mempertahankan tepi lainnya antara dan tetapi ini tidak ditampilkan pada ini):p re,f,g,h,ipr
Contoh
Menggunakan contoh yang sama seperti dalam jawaban Raphael :
kami berhasil menghapus :q2
lalu :q3
maka kita masih harus menerapkan bintang pada ekspresi dari hingga . Dalam hal ini, keadaan akhir juga awal sehingga kita benar-benar hanya perlu menambahkan bintang:q 1q1q1
(ab+(b+aa)(ba)∗(a+bb))∗
Algoritma
L[i,j]
adalah regexp dari bahasa dari ke . Pertama, kami menghapus semua multi-edge:q jqiqj
for i = 1 to n:
for j = 1 to n:
if i == j then:
L[i,j] := ε
else:
L[i,j] := ∅
for a in Σ:
if trans(i, a, j):
L[i,j] := L[i,j] + a
Sekarang, penghapusan status. Misalkan kita ingin menghapus status :qk
remove(k):
for i = 1 to n:
for j = 1 to n:
L[i,i] += L[i,k] . star(L[k,k]) . L[k,i]
L[j,j] += L[j,k] . star(L[k,k]) . L[k,j]
L[i,j] += L[i,k] . star(L[k,k]) . L[k,j]
L[j,i] += L[j,k] . star(L[k,k]) . L[k,i]
Perhatikan bahwa kedua dengan pensil kertas dan dengan algoritma Anda harus menyederhanakan ekspresi seperti star(ε)=ε
, e.ε=e
, ∅+e=e
, ∅.e=∅
(Dengan tangan Anda hanya tidak menulis tepi ketika itu tidak , atau bahkan untuk diri loop dan Anda mengabaikan ketika ada tidak ada transisi antara dan atau dan )∅q j q kεq kqiqkqjqk
Sekarang, bagaimana cara menggunakannya remove(k)
? Anda tidak boleh menghapus status akhir atau awal dengan ringan, jika tidak, Anda akan kehilangan bagian bahasa.
for i = 1 to n:
if not(final(i)) and not(initial(i)):
remove(i)
Jika Anda hanya memiliki satu status akhir dan satu status awal maka ekspresi terakhirnya adalah:q sqfqs
e := star(L[s,s]) . L[s,f] . star(L[f,s] . star(L[s,s]) . L[s,f] + L[f,f])
Jika Anda memiliki beberapa keadaan akhir (atau bahkan keadaan awal) maka tidak ada cara sederhana untuk menggabungkan yang ini, selain menerapkan metode penutupan transitif. Biasanya ini bukan masalah dengan tangan tetapi ini aneh ketika menulis algoritma. Solusi yang jauh lebih sederhana adalah menghitung semua pasangan dan menjalankan algoritma pada grafik (sudah dihapus) untuk mendapatkan semua ekspresi seandainya adalah satu-satunya keadaan awal dan adalah satu-satunya final nyatakan, lalu lakukan penyatuan semua .e s , f s f e s , f(s,f)es,fsfes,f
Ini, dan fakta bahwa ini memodifikasi bahasa lebih dinamis daripada metode pertama membuatnya lebih rentan kesalahan saat pemrograman. Saya sarankan menggunakan metode lain.
Cons
Ada banyak kasus dalam algoritme ini, misalnya untuk memilih simpul mana yang harus kita hapus, jumlah keadaan akhir di akhir, fakta bahwa keadaan akhir dapat menjadi awal, juga dll.
Perhatikan bahwa sekarang setelah algoritme ditulis, ini sangat mirip dengan metode penutupan transitif. Hanya konteks penggunaannya yang berbeda. Saya tidak merekomendasikan menerapkan algoritma, tetapi menggunakan metode untuk melakukannya dengan tangan adalah ide yang bagus.