{{위키데이터 속성 추적}}
[[파일:Relatively small NFA.svg|100px|섬네일|[[정규식|(0<nowiki>|</nowiki>1)<sup>*</sup>&nbsp;1&nbsp;(0<nowiki>|</nowiki>1)<sup>3</sup>]]을 인지하는 NFA.<br>같은 언어를 인지하는 [[결정론적 유한 상태 기계|DFA]]는 적어도 16개의 상태가 필요하다.]]
[[오토마타 이론]]에서, 어떤 [[유한 상태 기계]]가 [[결정론적 유한 상태 기계]](DFA)라는 것은 다음을 뜻한다.
* 현재 상태와 입력에 따라 다음 상태가 유일하게 결정된다.
* 상태가 바뀌려면 입력이 필요하다.
'''비결정론적 유한 상태 기계'''(Nondeterministic finite automaton, NFA)는 이러한 제한을 따르지 않을 수도 있다. 모든 DFA는 NFA이기도 하다. NFA는 좁은 뜻으로는 DFA가 아닌 유한 상태 기계만을 가리키기도 하지만, 이 문서에서는 그렇게 하지 않는다.

[[멱집합 구성]]을 사용하면 주어진 NFA와 동등한 DFA를 만들 수 있다. 즉, 주어진 NFA와 같은 언어를 인지하는 DFA를 만들 수 있다.<ref>{{서적 인용|title=Introduction to Languages and the Theory of Computation |last1=Martin |first1=John |year=2010 |page=108 |publisher=McGraw Hill |isbn= 978-0071289429}}</ref> DFA와 마찬가지로 NFA가 인지할 수 있는 언어는 [[정규 언어]]뿐이다.

[[미하엘 라빈]]과 [[데이나 스콧]]은 1959년에 비결정론적 유한 상태 기계를 처음 도입했고<ref>{{저널 인용|doi=10.1147/rd.32.0114 |last=Rabin |first=M. O. |last2=Scott |first2=D. |title=Finite Automata and Their Decision Problems |journal=IBM Journal of Research and Development |volume=3 |issue=2 |pages=114–125 |date=April 1959 }}</ref> NFA와 DFA가 동등함을 보였다. NFA는 [[정규 표현식]]의 구현에 사용된다. [[톰슨 구성]]은 정규 표현식을 NFA로 바꾸어 효율적인 문자열 [[패턴 매칭]]을 가능케 하는 알고리즘이다. 반대로 [[클레이니 알고리즘]]은 NFA를 정규 표현식으로 바꾸어 준다. (이때 정규 표현식의 길이는 NFA의 크기에 따라 지수적으로 증가한다.)

NFA를 더 일반화한 개념으로 [[#ε-이동을 허용하는 NFA|ε-이동을 허용하는 NFA]], [[유한 상태 트랜스듀서]], [[푸시다운 오토마타]], [[교대 유한 상태 기계]], [[ω-오토마타]], [[확률적 오토마타]] 등이 있다. NFA의 특수한 예로는 DFA 말고도 [[비중의적 유한 상태 기계]](UFA)와 [[자기 검증 유한 상태 기계]](SVFA) 등이 있다.

== 개요 ==
비결정론적 유한 상태 기계를 직관적으로 설명하는 방법은 여러 가지가 있다.
* NFA는 DFA처럼 입력 문자열을 받아들인다. 입력 기호 하나를 읽을 때마다 상태가 바뀌고, 모든 입력 기호를 읽을 때까지 계속 동작한다. 매 단계마다 NFA는 가능한 다음 상태 중 하나를 임의로 선택한다. 모든 기호를 읽은 뒤에 “운 좋게” 최종 상태 중 하나에 도착할 수 있다면, 입력을 수용한다. 그런 방법이 없다면 입력을 수용하지 않는다.<ref name="Hopcroft.Ullman.1979">{{서적 인용| isbn=0-201-02988-X | author=John E. Hopcroft and Jeffrey D. Ullman | title=Introduction to Automata Theory, Languages, and Computation | location=Reading/MA | publisher=Addison-Wesley | year=1979 | url=https://archive.org/details/introductiontoau00hopc }}</ref>{{rp|19}}<ref name="Aho.Hopcroft.Ullman.1974">{{서적 인용| isbn=0-201-00029-6 | author=Alfred V. Aho and John E. Hopcroft and Jeffrey D. Ullman | title=The Design and Analysis of Computer Algorithms | url=https://archive.org/details/designanalysisof00ahoarich | url-access=registration | location=Reading/MA | publisher=Addison-Wesley | year=1974 }}</ref>{{rp|319}}
* NFA는 입력 기호를 하나씩 받아들인다. 매 단계마다, 가능한 다음 상태가 하나보다 많다면, NFA는 스스로를 필요한 만큼 “복제”하고 각 복사본은 서로 다른 가능한 상태로 진입한다. 가능한 다음 상태가 없다면, 그 복사본은 막다른 길에 다다랐으므로 “죽는다”. 모든 기호를 읽은 뒤에 복사본 중 하나라도 최종 상태에 도착했다면, 입력을 수용한다. 최종 상태에 도달한 복사본이 없다면 입력을 수용하지 않는다.<ref name="Hopcroft.Ullman.1979"/>{{rp|19–20}}<ref name="Sipser.1997">{{서적 인용| author=Michael Sipser | title=Introduction to the Theory of Computation | location=Boston/MA | publisher=PWS Publishing Co. | year=1997 | isbn=0-534-94728-X | url=https://archive.org/details/introductiontoth00sips }}</ref>{{rp|48}}<ref name="Hopcroft.Motwani.Ullman.2003">{{서적 인용 | url=http://148.216.38.247/~rrusiles/Fie/Horizontal/Hopcroft_Introduction_to_Automata_Theory_Languages_and_Computation.pdf | isbn=0-201-44124-1 | author=John E. Hopcroft and Rajeev Motwani and Jeffrey D. Ullman | title=Introduction to Automata Theory, Languages, and Computation | location=Upper Saddle River/NJ | publisher=Addison Wesley | year=2003 | access-date=2021-04-03 | archive-date=2019-08-30 | archive-url=https://web.archive.org/web/20190830090046/http://148.216.38.247/~rrusiles/Fie/Horizontal/Hopcroft_Introduction_to_Automata_Theory_Languages_and_Computation.pdf | url-status=dead }}</ref>{{rp|56}}

== 정의 ==
=== 기계 ===
비결정론적 유한 상태 기계는 순서 5짝
<math>(Q, \Sigma, \Delta, q_0, F)</math>으로 정의된다. 각 요소의 의미는 다음과 같다.
* 가능한 상태의 유한집합 <math>Q</math>.
* 입력 기호의 유한집합 <math>\Sigma</math>.
* 전이 함수 <math>\Delta</math> : <math>Q\times\Sigma \rightarrow P(Q)</math>.
* 초기 상태 <math>q_0 \in Q</math>.
* 최종 상태 (또는 수용 상태)의 집합 <math>F \subseteq Q</math>.

이때 <math>P(Q)</math>는 <math>Q</math>의 [[멱집합]]을 나타낸다.

=== 언어 ===
NFA <math>M = (Q, \Sigma, \Delta, q_0, F)</math>이 인지하는 언어를 <math>L(M)</math>이라 쓰고, <math>M</math>이 수용하는 <math>\Sigma</math> 위의 모든 문자열의 집합으로 정의한다.

<math>M</math>이 문자열 <math>w = a_1 a_2 ... a_n</math>을 수용한다는 것은 여러 가지 방식으로 정의할 수 있는데, 앞서 소개한 [[#개요|직관적인 정의]]에 어느 정도 대응한다.
*<math>w</math>가 수용된다는 것은, <math>Q</math>에 속한 상태 <math>r_0, r_1, ..., r_n</math>이 존재하여 다음을 만족한다는 것이다.
*# <math>r_0 = q_0</math>
*# <math>r_{i+1} \in \Delta (r_i, a_{i+1})</math>, (<math>i = 0, \ldots, n-1</math>)
*# <math>r_n \in F</math>.
: 풀어서 설명하면, 첫째 조건은 기계가 초기 상태 <math>q_0</math>에서 시작한다는 것이다. 둘째 조건은 문자열 <math>w</math>의 각 기호를 읽을 때마다 기계가 전이 함수 <math>\Delta</math>에 따라 한 상태에서 다른 상태로 바뀐다는 것이다. 셋째 조건은 기계가 <math>w</math>의 마지막 기호를 읽고 최종 상태 중 하나로 바뀐다면 <math>w</math>를 수용한다는 것이다. <math>M</math>이 <math>w</math>를 수용하려면 가능한 모든 상태의 수열이 최종 상태로 끝날 필요는 없다. 가능한 상태의 수열 중 하나라도 최종 상태로 끝나면 충분하다. 만약 그렇지 않다면, 즉 <math>q_0</math>에서 출발해서 <math>w</math>를 따라 <math>F</math>에 속한 상태로 갈 방법이 전혀 없다면 NFA가 문자열을 수용하지 않는다. <math>M</math>이 수용하는 모든 문자열의 집합을 <math>M</math>이 인지하는 [[형식 언어|언어]]라고 하며 <math>L(M)</math>으로 나타낸다.<ref name="Aho.Hopcroft.Ullman.1974"/>{{rp|320}}<ref name="Sipser.1997"/>{{rp|54}}

* 다른 정의로, <math>w</math>가 수용된다는 것은 <math>\Delta^*(q_0, w) \cap F \not = \emptyset</math>라는 뜻이다. 이때 <math>\Delta^*: Q \times \Sigma^* \rightarrow P(Q)</math>는 다음과 같이 재귀적으로 정의된다.
*# <math>\Delta^*(r, \epsilon) = \{r\}</math>, (<math>\epsilon</math>은 빈 문자열을 나타낸다)
*# 모든 <math>x \in \Sigma^*, a \in \Sigma</math>에 대해 <math>\Delta^*(r, xa)= \bigcup_{r' \in \Delta^*(r, x)} \Delta(r', a)</math>.
: 폴어서 설명하면, <math>\Delta^*(r, x)</math>은 상태 <math>r</math>에서 출발해서 문자열 <math>x</math>를 읽고 도달할 수 있는 모든 상태의 집합이다. <math>q_0</math>에서 출발해서 문자열 <math>w</math>를 따라 <math>F</math>에 속한 상태 중 하나에 도달할 수 있다면, 문자열 <math>w</math>를 수용한다.<ref name="Hopcroft.Ullman.1979"/>{{rp|21}}<ref name="Hopcroft.Motwani.Ullman.2003"/>{{rp|59}}

=== 초기 상태 ===
위의 정의에서는 초기 상태가 하나뿐이지만 꼭 그럴 필요는 없다. 어떤 경우에는 여러 개의 초기 상태를 갖도록 NFA를 정의하기도 한다. 이렇게 하면 표기가 편리해지는 경우가 있다. 초기 상태가 여럿인 NFA를 초기 상태가 하나인 동등한 NFA로 변환하는 것은 간단하다.

== 예시 ==
{| style="float: right; border-spacing: 0;"
|-
| style="vertical-align:top;" | [[파일:NFASimpleExample.svg|섬네일|250px|''M''의 상태 도표. 상태 ''p''에서 입력 1을 받으면 ''p'' 또는 ''q''로 갈 수 있기 때문에 비결정론적이다.]]
| style="vertical-align:top;" | [[파일:NFASimpleExample Runs10.gif|섬네일|250px|입력 “10”을 받았을 때 ''M''의 가능한 모든 작동.]]
|-
| colspan="2"  | [[파일:NFASimpleExample Runs1011.gif|섬네일|530px|입력 “1011”을 받았을 때 ''M''의 가능한 모든 작동.<br/>호 첨자: 입력 기호, 노드 첨자: 상태, {{color|#00c000|초록}}: 초기 상태, {{color|#c00000|빨강}}: 최종 상태.]]
|}
다음 기계 <math>M</math>은 {0, 1} 위의 입력을 받아들여 입력이 1로 끝나는지 판정한다.

<math>M = (\{p, q\}, \{0, 1\}, \Delta, p, \{q\})</math>이라 하자.
단, 전이 함수 <math>\Delta</math>는 다음 상태 전이 표와 같이 정의한다. (왼쪽 위 그림 참조)
{| class="wikitable" style="text-align:center;"
! {{diagonal split header|상태|입력}}
! 0
! 1
|-
! <math>p</math>
| <math>\{p\}</math>
| <math>\{p,q\}</math>
|-
! <math>q</math>
| <math>\emptyset</math>
| <math>\emptyset</math>
|}
집합 <math>\Delta(p,1)</math>은 하나보다 많은 상태를 포함하므로, <math>M</math>은 비결정론적이다.
<math>M</math>의 언어는 [[정규 표현식]] <code>(0|1)*1</code>에 대응하는 [[정규 언어]]이다.

입력 “1011”을 받았을 때 <math>M</math>이 작동할 수 있는 모든 경우의 수는 아래쪽 그림에 나타나 있다.
<!---replaced by image:---{| class="wikitable"
|-
!Input:            ||       || 1 ||       || 0 ||       || 1 ||       || 1 ||
|-
|State sequence 1: || ''p'' ||   || ''q'' ||   ||'''?'''||   ||       ||   || 
|-
|State sequence 2: || ''p'' ||   || ''p'' ||   || ''p'' ||   || ''q'' ||   || '''?'''
|-
|State sequence 3: || ''p'' ||   || ''p'' ||   || ''p'' ||   || ''p'' ||   || ''q''
|}--->
상태의 수열 중 하나가 위 정의를 만족시키므로 <math>M</math>은 이 문자열을 수용한다. 다른 수열이 실패하는 것은 상관없다.
이 그림은 여러 가지 방식으로 읽을 수 있다.
* 첫번째 직관적 설명에 따르면, 그림에 나타난 각 경로는 <math>M</math>이 취할 수 있는 일련의 선택을 나타낸다.
* “복제”에 기반한 설명에 따르면, 각 세로줄은 어느 시점에서 <math>M</math>의 모든 복사본을 보여준다. 한 노드에서 여러 화살표가 나오는 것은 복제를 나타내고, 화살표가 나오지 않는 노드는 복사본이 “죽었음”을 나타낸다.
같은 그림을 두 가지 방식으로 읽을 수 있다는 데서 두 가지 설명이 동치임을 알 수 있다.
* 위의 첫번째 형식적 정의에 따르면, <math>M</math>은 “1011”을 읽고 상태를 <math>\langle r_0,r_1,r_2,r_3,r_4 \rangle = \langle p, p, p, p, q \rangle</math>와 같이 바꿔 나갈 수 있기 때문에 “1011”을 수용한다.
* 두번째 형식적 정의에 따르면, <math>\Delta^*(p,\epsilon) = \{ p \}</math>이므로 <math>\Delta^*(p,1) = \Delta(p,1) = \{ p,q \}</math>이고, 따라서 <math>\Delta^*(p,10) = \Delta(p,0) \cup \Delta(q,0) = \{ p \} \cup \{\}</math>이므로 <math>\Delta^*(p,101) = \Delta(p,1) = \{ p,q \}</math>이고, 따라서 <math>\Delta^*(p,1011) = \Delta(p,1) \cup \Delta(q,1) = \{ p,q \} \cup \{\}</math>이다. 이 집합은 <math>\{ q \}</math>와 서로소가 아니므로 “1011”은 수용된다.

반면에 <math>M</math>은 문자열 “10”을 수용하지 않는데, 마지막 기호인 0을 읽고 유일한 최종 상태인 <math>q</math>에 도달하는 것은 불가능하기 때문이다. (오른쪽 위 그림 참조) 첫 기호인 1을 읽으면 상태 <math>q</math>에 도달하게 되겠지만, 이는 “10”이 수용된다는 뜻이 아니라 “1”이 수용된다는 뜻이다.

== 같이 보기 ==
* [[결정론적 유한 상태 기계]]
* [[푸시다운 자동 기계]]
* [[비결정론적 튜링 기계]]
== 각주 ==
{{각주}}

== 참고 문헌 ==
* M. O. Rabin and D. Scott, "Finite Automata and their Decision Problems", ''IBM Journal of Research and Development'', '''3''':2 (1959) pp.&nbsp;115–125.
* Michael Sipser, ''Introduction to the Theory of Computation''. PWS, Boston. 1997. {{isbn|0-534-94728-X}}. ''(see section 1.2: Nondeterminism, pp. 47–63.)''
* John E. Hopcroft and Jeffrey D. Ullman, ''Introduction to Automata Theory, Languages, and Computation'', Addison-Wesley Publishing, Reading Massachusetts, 1979. {{isbn|0-201-02988-X}}. ''(See chapter 2.)''

{{형식 언어 및 형식 문법}}

[[분류:유한 상태 기계]]