Algorithm-ConstructDFA-XS
view release on metacpan or search on metacpan
t/02simple.t view on Meta::CPAN
vertices => int(rand(32)),
edges_fill => 0.2
);
my %labels;
my @vertices = $g->vertices;
for my $v (@vertices) {
next unless rand > 0.3;
my $label = ['a', 'b', 'c']->[int rand 3];
$g->set_vertex_attribute($v, 'label', $label);
}
my $start = [sort_by { scalar $g->successors($_) } @vertices]->[-1];
next unless defined $start;
my $final = [$g->all_successors($start), $start]
->[int rand(1 + scalar $g->all_successors($start))];
next unless defined $final;
my $dfa = construct_dfa_xs(
is_nullable => sub {
not $g->has_vertex_attribute($_[0], 'label')
},
is_accepting => sub { grep { $_ eq $final } @_ },
successors => sub { $g->successors($_[0]) },
get_label => sub { $g->get_vertex_attribute($_[0], 'label') },
start => [ $start ],
);
if (rand > 0.5) {
$dfa = construct_dfa_xs(
is_nullable => sub {
return 1;
},
is_accepting => sub { grep { $dfa->{$_}{Accepts} } @_ },
edges_from => sub {
my ($src) = @_;
my @edges;
for my $via (keys %{ $dfa->{$src}{NextOver} }) {
my $dst = $dfa->{$src}{NextOver}{$via};
push @edges, [$dst, $via];
}
return @edges;
},
start => [ 1 ],
);
} elsif (rand > 0.5) {
$dfa = revdet(revdet( $dfa ));
}
my $dfa_g = Graph::Directed->new;
my $dfa_g_final = "final";
for my $s (keys %$dfa) {
for my $label (keys %{$dfa->{$s}{NextOver}}) {
my $mid = $s . ':' . $label;
$dfa_g->add_edge($s, $mid);
$dfa_g->add_edge($mid, $dfa->{$s}{NextOver}{$label});
$dfa_g->set_vertex_attribute($mid, 'label', $label) if length $label;
$dfa_g->add_edge($s, $dfa_g_final)
if $dfa->{$s}{Accepts};
$dfa_g->add_edge($dfa->{$s}{NextOver}{$label}, $dfa_g_final)
if $dfa->{$dfa->{$s}{NextOver}{$label}}{Accepts};
}
}
my $make_random_path_enumerator = sub {
return Graph::RandomPath->create_generator(@_);
my ($graph, $src, $dst) = @_;
my %to_src = map { $_ => 1 } $src, $graph->all_successors($src);
my %to_dst = map { $_ => 1 } $dst, $graph->all_predecessors($dst);
my $copy = Graph::Directed->new(edges => [ grep {
$to_src{$_->[0]} and $to_src{$_->[1]} and
$to_dst{$_->[0]} and $to_dst{$_->[1]}
} $graph->edges]);
return sub {
my @path = ($src);
for (1 .. int(rand(100))) {
my $s = $copy->random_successor($path[-1]);
last unless defined $s;
push @path, $s;
}
unless ($path[-1] eq $dst) {
splice @path, $#path, 1, $copy->SP_Dijkstra($path[-1], $dst);
}
return @path;
}
};
for my $config ([$g, $start, $final, $dfa_g, 1, $dfa_g_final],
[$dfa_g, 1, $dfa_g_final, $g, $start, $final]
) {
my ($g1, $start, $final, $g2, $start2, $final2) = @$config;
my $rnd;
eval {
$rnd = Graph::RandomPath->create_generator($g1, $start, $final);
};
next if $@;
for (1 .. 4) {
my @path = $rnd->();
my @word =
map { $g1->get_vertex_attribute($_, 'label') }
grep { $g1->has_vertex_attribute($_, 'label') }
@path[0 .. $#path - 1];
# use YAML::XS;
# warn Dump { path => \@path, word => join('/', @word), };
my @word_copy = @word;
my @state = $start2;
while (1) {
my %seen;
( run in 1.546 second using v1.01-cache-2.11-cpan-39bf76dae61 )