File Coverage

blib/lib/Computer/Theory/FSA.pm
Criterion Covered Total %
statement 10 127 7.8
branch 0 54 0.0
condition 0 18 0.0
subroutine 4 22 18.1
pod 15 16 93.7
total 29 237 12.2


line stmt bran cond sub pod time code
1             # Finite State Automaton
2             #
3             # { Q, Z, T, S, F }
4             # | | | | `---> Is a set of final (or accepting) states.
5             # | | | `------> Is the starting state.
6             # | | `---------> Is the transition function..
7             # | `------------> Is a alphabet.
8             # `---------------> Is a finite set of states.
9             #
10             # Copyright 2003 Fabiano Reese Righetti
11             # All rights reserved.
12             #
13             # This program is free software; you can redistribute it and/or
14             # modify it under the terms of the GNU General Public License as
15             # published by the Free Software Foundation; either version 2 of the
16             # License, or (at your option) any later version.
17             # This program is distributed in the hope that it will be useful,
18             # but WITHOUT ANY WARRANTY; without even the implied warranty of
19             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20             # General Public License for more details.
21              
22             package Computer::Theory::FSA;
23             require 5.005;
24              
25             =head1 NAME
26              
27             Computer::Theory::FSA - Computer theory of Finite State Automanton.
28              
29             =head1 SYNOPSIS
30              
31             #!/usr/bin/perl
32            
33             use Computer::Theory::FSA;
34            
35             my $FA = new Computer::Theory::FSA();
36            
37             $FA->addState("q0");
38             $FA->addState("q1");
39             $FA->addState("q2");
40             $FA->addState("q3");
41             $FA->addAlphabet("a");
42             $FA->addAlphabet("b");
43             $FA->setStarting("q0");
44             $FA->addFinal("q3");
45             $FA->addTransition("a","q0","q1");
46             $FA->addTransition("a","q1","q2");
47             $FA->addTransition("a","q2","q3");
48             $FA->addTransition("b","q0","q0");
49            
50             my $valide = $FA->DFA($word);
51              
52             =head1 DESCRIPTION
53              
54             "A Finite State Automaton is an abstract machine used in the
55             study of computation and languages that has only a finite, constant
56             amount of memory (the state). It can be conceptualised as a directed
57             graph. There are a finite number of states, and each state has
58             transitions to zero or more states. There is an input string that
59             determines which transition is followed. Finite state machines are
60             studied in automata theory, a subfield of theoretical computer
61             science". [Wikipedia - Mon Jun 23 2003]
62              
63             =head1 METHODS
64              
65             =over 4
66              
67             =cut
68              
69 1     1   48632 use vars qw($VERSION);
  1         2  
  1         60  
70 1     1   6 use strict;
  1         1  
  1         39  
71 1     1   5 use warnings;
  1         7  
  1         50  
72              
73             BEGIN
74             {
75 1     1   14330 our $VERSION = '0.1_04';
76             }
77              
78             =item B
79              
80             The constructor method.
81              
82             my $FA = new Computer::Theory::FSA();
83              
84             =cut
85              
86             sub new
87             {
88 0     0 1   my $type = shift;
89 0   0       my $class = ref $type || $type;
90              
91 0           my $self = {
92             Q => [],
93             Z => [],
94             S => '',
95             F => [],
96             T => {},
97             @_,
98             };
99              
100 0           bless $self, $class;
101 0           return $self;
102             }
103              
104             =item B
105              
106             Set new state in the list of states.
107              
108             $FA->addState("qX");
109              
110             =cut
111              
112             sub addState
113             {
114 0     0 1   my $self = shift;
115 0           my $state = shift;
116              
117 0 0         if (defined $state) {
118 0           push(@{$self->{Q}}, $state)
  0            
119 0 0         if &_search(\@{$self->{Q}}, $state) < 0;
120             }
121             }
122              
123             =item B
124              
125             Remove state in the list of states.
126              
127             $FA->delState("qX");
128              
129             =cut
130              
131             sub delState
132             {
133 0     0 1   my $self = shift;
134 0           my $state = shift;
135              
136 0 0         if (defined $state) {
137 0           my $position = &_search(\@{$self->{Q}}, $state);
  0            
138 0 0         splice(@{$self->{Q}}, $position, 1) if $position > -1;
  0            
139             }
140             }
141              
142             =item B
143              
144             Get the list of states.
145              
146             foreach my $state ($FA->getState()) {
147             print $state." ";
148             }
149              
150             =cut
151              
152             sub getState
153             {
154 0     0 1   my $self = shift;
155              
156 0           return @{$self->{Q}};
  0            
157             }
158              
159             =item B
160              
161             Set new caracter in the list of alphabet.
162              
163             $FA->addAlphabet("x");
164              
165             =cut
166              
167             sub addAlphabet
168             {
169 0     0 1   my $self = shift;
170 0           my $caracter = shift;
171              
172 0 0         if (defined $caracter) {
173 0           push(@{$self->{Z}}, $caracter)
  0            
174 0 0         if &_search(\@{$self->{Z}}, $caracter) < 0;
175             }
176             }
177              
178             =item B
179              
180             Remove caracter in the list of alphebet.
181              
182             $FA->delAlphabet("x");
183              
184             =cut
185              
186             sub delAlphabet
187             {
188 0     0 0   my $self = shift;
189 0           my $caracter = shift;
190 0           my $position = &_search(\@{$self->{Z}}, $caracter);
  0            
191              
192 0 0         if (defined $caracter) {
193 0 0         splice(@{$self->{Z}}, $position, 1) if $position > -1;
  0            
194             }
195             }
196              
197             =item B
198              
199             Get the list of alphabet.
200              
201             foreach my $caracter ($FA->getAlphabet()) {
202             print $i." ";
203             }
204              
205             =cut
206              
207             sub getAlphabet
208             {
209 0     0 1   my $self = shift;
210            
211 0           return @{$self->{Z}};
  0            
212             }
213              
214             =item B
215              
216             Attribute starting state.
217              
218             $FA->setStarting("qX");
219              
220             =cut
221              
222             sub setStarting
223             {
224 0     0 1   my $self = shift;
225 0           my $state = shift;
226              
227 0 0         if (defined $state) {
228 0 0         $self->{S} = $state if &_search(\@{$self->{Q}}, $state) > -1;
  0            
229             }
230             }
231              
232             =item B
233              
234             Get starting state.
235              
236             my $starting = $FA->getStarting();
237              
238             =cut
239              
240             sub getStarting
241             {
242 0     0 1   my $self = shift;
243              
244 0           return $self->{S};
245             }
246              
247             =item B
248              
249             Set new state in the list of final states.
250              
251             $FA->addFinal("qX");
252              
253             =cut
254              
255             sub addFinal
256             {
257 0     0 1   my $self = shift;
258 0           my $state = shift;
259              
260 0 0         if (defined $state) {
261 0           push(@{$self->{F}}, $state)
  0            
262 0           if &_search(\@{$self->{Q}}, $state) > -1 &&
263 0 0 0       &_search(\@{$self->{F}}, $state) < 0;
264             }
265             }
266              
267             =item B
268              
269             Remove state in the list of final states.
270              
271             $FA->delFinal("qX");
272              
273             =cut
274              
275             sub delFinal
276             {
277 0     0 1   my $self = shift;
278 0           my $state = shift;
279 0           my $position = &_search(\@{$self->{F}}, $state);
  0            
280              
281 0 0         if (defined $state) {
282 0 0         splice(@{$self->{F}}, $position, 1) if $position > -1;
  0            
283             }
284             }
285              
286             =item B
287              
288             Get the list of final states.
289              
290             foreach my $fstate ($FA->getFinal()) {
291             print $fstate." ";
292             }
293              
294             =cut
295              
296             sub getFinal
297             {
298 0     0 1   my $self = shift;
299              
300 0           return @{$self->{F}};
  0            
301             }
302              
303             =item B
304              
305             Set new transition in the list of transitions.
306              
307             $FA->addTransition("x","qX","qY");
308              
309             =cut
310              
311             sub addTransition
312             {
313 0     0 1   my $self = shift;
314 0           my $caracter = shift;
315 0           my $from = shift;
316 0           my $destine = shift;
317              
318 0 0         if (defined $destine) {
319 0           push(@{$self->{T}{$caracter}{$from}},$destine)
  0            
320 0           if &_search(\@{$self->{Z}}, $caracter) > -1 &&
321 0           &_search(\@{$self->{Q}}, $from) > -1 &&
322 0           &_search(\@{$self->{Q}}, $destine) > -1 &&
323 0 0 0       &_search(\@{$self->{T}{$caracter}{$from}}, $destine) < 0;
      0        
      0        
324             }
325             }
326              
327             =item B
328              
329             Remove transition in the list of transitions.
330              
331             $FA->delTransition("x","qX","qY");
332             $FA->delTransition("x","qX");
333              
334             =cut
335              
336             sub delTransition
337             {
338 0     0 1   my $self = shift;
339 0           my $caracter = shift;
340 0           my $from = shift;
341 0           my $destine = shift;
342 0           my $position = -1;
343              
344 0 0         if (defined $destine) {
    0          
345 0           $position = &_search(\@{$self->{T}{$caracter}{$from}},$destine);
  0            
346 0 0         splice(@{$self->{T}{$caracter}{$from}}, $position, 1)
  0            
347             if $position > -1;
348 0           delete($self->{T}{$caracter}{$from})
349 0 0         if $#{$self->{T}{$caracter}{$from}} < 0;
350             } elsif (defined $from) {
351 0           delete($self->{T}{$caracter}{$from});
352             }
353             }
354              
355             =item B
356              
357             Get the list of transitions.
358              
359             foreach my $caracter (sort keys %tt) {
360             foreach my $from (sort keys %{$tt{$caracter}}) {
361             print " $caracter - $from => ";
362             foreach my $destine (@{$tt{$caracter}{$from}}) {
363             print "$destine ";
364             }
365             print "\n";
366             }
367             }
368              
369             =cut
370              
371             sub getTransition
372             {
373 0     0 1   my $self = shift;
374            
375 0           return %{$self->{T}};
  0            
376             }
377              
378             =item B
379              
380             Algorithm of valide the Deterministic Finite Automaton.
381             "The machine starts in the start state and reads in a string of
382             symbols from its alphabet. It uses the transition function T to
383             determine the next state using the current state and the symbol just
384             read. If, when it has finished reading, it is in an accepting state,
385             it is said to accept the string, otherwise it is said to reject the
386             string. The set of strings it accepts form a language, which is the
387             language the DFA recognises". [Wikipedia - Mon Jun 23 2003]
388              
389             my $valide = $FA->DFA('xxx');
390              
391             =cut
392              
393             sub DFA
394             {
395 0     0 1   my $self = shift;
396 0           my $word = shift;
397 0 0         my @word = split(//, defined $word ? $word : "" );
398              
399 0 0         return($#word > -1 ? ${&_dfa($self, \@word, $self->{S}, 0)}[0] : 0);
  0            
400             }
401              
402             sub _dfa
403             {
404 0     0     my ($self,$word,$state,$position) = @_;
405 0           my $valide = 1;
406              
407 0 0 0       if ((defined $self->{T}{$word->[$position]}{$state}) and
  0            
408             ($#{$self->{T}{$word->[$position]}{$state}} == 0)) {
409 0           ($valide,$state) = $position < $#{$word} ?
  0            
410 0 0         @{&_dfa($self,$word,
411             $self->{T}{$word->[$position]}{$state}[0],
412             ++$position)} :
413             ($valide,
414             $self->{T}{$word->[$position]}{$state}[0]);
415             } else {
416 0           ($valide,$state) = (0, '');
417             }
418              
419 0 0         if ($valide) {
420 0           for my $i (@{$self->{F}}) {
  0            
421 0 0         if ($state ne $i) {
422 0           $valide = 0;
423             } else {
424 0           $valide = 1;
425 0           last;
426             }
427             }
428             }
429              
430 0           return([$valide, $state]);
431             }
432              
433             # Valide Non-deterministic Finite Automaton.
434             #sub NFA
435             #{
436             # my $self = shift;
437             # my @word = split(//, shift);
438             #
439             # return(${&_nfa($self, \@word, $self->{S}, 0)}[0]);
440             #}
441              
442             #sub _nfa
443             #{
444             #}
445              
446             # Search position of the element in the Array.
447             sub _search
448             {
449 0     0     my $array = shift;
450 0           my $element = shift;
451 0           my $position = -1;
452              
453 0           for my $i (0 .. $#{$array}) {
  0            
454 0 0         if ($array->[$i] eq $element) {
455 0           $position = $i;
456             }
457             }
458              
459 0           return $position;
460             }
461              
462             1;
463             __END__