In this code I take non-looping FSAs and process the description using
XML::Twig and search the defined paths looking for a solution.
here is a pictorial representation of the paths
(A) --B--> (C) --1--> (R) --L--> (F)
(A) --D--> (D) --2--> (Q) --3--> (F)
(A) --P--> (M) --4--> (P) --9--> (F)
and here is the XML graph description
<fsm initial_state="A" final_state="F">
<delta><start>A</start><input>B</input><rest>C</rest></delta>
<delta><start>C</start><input>1</input><rest>R</rest></delta>
<delta><start>R</start><input>L</input><rest>F</rest></delta>
<delta><start>A</start><input>P</input><rest>M</rest></delta>
<delta><start>M</start><input>4</input><rest>P</rest></delta>
<delta><start>P</start><input>9</input><rest>F</rest></delta>
<delta><start>A</start><input>Q</input><rest>D</rest></delta>
<delta><start>D</start><input>2</input><rest>Q</rest></delta>
<delta><start>Q</start><input>3</input><rest>F</rest></delta>
</fsm>
use XML::Twig;
my $twig = XML::Twig->new;
my @input = qw(Q 2 3);
$twig->parsefile("fsa.xml");
my $root = $twig->root;
my $I = $root->att('initial_state');
my $F = $root->att('final_state');
my @delta = $root->children;
sub bfs {
my ($type, $search_text, @nodes) = @_;
grep { $_->first_child($type)->text eq $search_text } @nodes ;
}
my @start_candidate = bfs('start', 'A', @delta);
&DFS(\@start_candidate,\@input);
sub DFS {
my ($start_candidate,$input) = @_;
for my $path (@$start_candidate) {
my $current_position = $path->next_elt('start')->text;
warn "currently at: $current_position";
return 1 if $F eq $current_position and !@$input;
my @input = @$input;
if ($path->next_elt('input')->text eq shift(@input)) {
my $next = $path->next_elt('rest');
my @new_paths = bfs('start', $next->text, @delta);
return DFS(\@new_paths, \@input);
} else {
next;
}
}
return 0;
}