view release on metacpan or search on metacpan
AI/Gene/Sequence.pm view on Meta::CPAN
splice @{$self->[1]}, $pos2, 0, @{$self->[1]}[$pos1..($pos1+$len-1)];
$rt++;
}
return $rt;
}
##
# Duplicates a sequence and writes it on top of some other position
# 0: num to perform (or 1)
# 1: pos to get from (undef for rand)
# 2: pos to start replacement (undef for rand)
# 3: length to operate on (undef => 1, 0 => rand)
sub mutate_overwrite {
my $self = shift;
my $num = +$_[0] || 1;
my $rt = 0;
for (1..$num) {
my $new = $self->[0];
my $length = length $self->[0];
AI/Gene/Sequence.pm view on Meta::CPAN
@{$self->[1]}[$pos1..($pos1+$len-1)] );
$rt++;
}
return $rt;
}
##
# Takes a run of tokens and reverses their order, is a noop with 1 item
# 0: number to perform
# 1: posn to start from (undef for rand)
# 2: length (undef=>1, 0=>rand)
sub mutate_reverse {
my $self = shift;
my $num = +$_[0] || 1;
my $rt = 0;
for (1..$num) {
my $length = length $self->[0];
my $new = $self->[0];
AI/Gene/Sequence.pm view on Meta::CPAN
$self->[1][$pos] = $token[1];
$rt++;
}
return $rt;
}
##
# swaps over two sequences within the gene
# any sort of oddness can occur if regions overlap
# 0: number to perform
# 1: start of first sequence (undef for rand)
# 2: start of second sequence (undef for rand)
# 3: length of first sequence (undef for 1, 0 for rand)
# 4: length of second sequence (undef for 1, 0 for rand)
sub mutate_switch {
my $self = shift;
my $num = $_[0] || 1;
my $rt = 0;
for (1..$num) {
my $length = length $self->[0];
my $pos1 = defined $_[1] ? $_[1] : int rand $length;
AI/Gene/Sequence.pm view on Meta::CPAN
# your specific needs
sub clone {
my $self = shift;
my $new = [$self->[0]];
$new->[1] = [@{$self->[1]}];
return bless $new, ref $self;
}
# You need some way to use the gene you've made and mutated, but
# this will let you have a look, if it starts being odd.
sub render_gene {
my $self = shift;
my $return = "$self\n";
$return .= $self->[0] . "\n";
$return .= (join ',', @{$self->[1]}). "\n";
return $return;
}
# used for testing
AI/Gene/Sequence.pm view on Meta::CPAN
overriding any you do not like in the module.
=item C<mutate_insert([num, pos])>
Inserts a single token into the string at position I<pos>.
The token will be randomly generated by the calling object's
C<generate_token> method.
=item C<mutate_overwrite([num, pos1, pos2, len])>
Copies a section of the gene (starting at I<pos1>, length I<len>)
and writes it back into the gene, overwriting current elements,
starting at I<pos2>.
=item C<mutate_reverse([num, pos, len])>
Takes a sequence within the gene and reverses the ordering of the
elements within that sequence. Starts at position I<pos> for
length I<len>.
=item C<mutate_shuffle([num, pos1, pos2, len])>
This takes a sequence (starting at I<pos1> length I<len>)
from within a gene and moves
it to another position (starting at I<pos2>). Odd things might occur if the
position to move the sequence into lies within the
section to be moved, but the module will try its hardest
to cause a mutation.
=item C<mutate_duplicate([num, pos1, pos2, length])>
This copies a portion of the gene starting at I<pos1> of length
I<length> and then splices it into the gene before I<pos2>.
=item C<mutate_remove([num, pos, length]))>
Deletes I<length> tokens from the gene, starting at I<pos>. Repeats
I<num> times.
=item C<mutate_minor([num, pos])>
This will mutate a single token at position I<pos> in the gene
into one of the same type (as decided by the object's C<generate_token>
method).
=item C<mutate_major([num, pos])>
This changes a single token into a token of any token type.
Token at postition I<pos>. The token is produced by the object's
C<generate_token> method.
=item C<mutate_switch([num, pos1, pos2, len1, len2])>
This takes two sequences within the gene and swaps them
into each other's position. The first starts at I<pos1>
with length I<len1> and the second at I<pos2> with length
I<len2>. If the two sequences overlap, then no mutation will
be attempted.
=back
The following methods are also provided, but you will probably
want to overide them for your own genetic sequences.
=over 4
AI/Gene/Simple.pm view on Meta::CPAN
splice @{$self->[0]}, $pos2, 0, @{$self->[0]}[$pos1..($pos1+$length-1)];
$rt++;
}
return $rt;
}
##
# Duplicates a sequence and writes it on top of some other position
# 0: num to perform (or 1)
# 1: pos to get from (undef for rand)
# 2: pos to start replacement (undef for rand)
# 3: length to operate on (undef => 1, 0 => rand)
sub mutate_overwrite {
my $self = shift;
my $num = +$_[0] || 1;
my $rt = 0;
for (1..$num) {
my $glen = scalar @{$self->[0]};
my $length = !defined($_[3]) ? 1 : ($_[3] || int rand $glen);
AI/Gene/Simple.pm view on Meta::CPAN
@{$self->[0]}[$pos1..($pos1+$length-1)] );
$rt++;
}
return $rt;
}
##
# Takes a run of tokens and reverses their order, is a noop with 1 item
# 0: number to perform
# 1: posn to start from (undef for rand)
# 2: length (undef=>1, 0=>rand)
sub mutate_reverse {
my $self = shift;
my $num = +$_[0] || 1;
my $rt = 0;
for (1..$num) {
my $length = scalar @{$self->[0]};
my $pos = defined($_[1]) ? $_[1] : int rand $length;
AI/Gene/Simple.pm view on Meta::CPAN
$self->[0][$pos] = $token;
$rt++;
}
return $rt;
}
##
# swaps over two sequences within the gene
# any sort of oddness can occur if regions overlap
# 0: number to perform
# 1: start of first sequence (undef for rand)
# 2: start of second sequence (undef for rand)
# 3: length of first sequence (undef for 1, 0 for rand)
# 4: length of second sequence (undef for 1, 0 for rand)
sub mutate_switch {
my $self = shift;
my $num = $_[0] || 1;
my $rt = 0;
for (1..$num) {
my $glen = scalar @{$self->[0]};
my $pos1 = defined $_[1] ? $_[1] : int rand $glen;
AI/Gene/Simple.pm view on Meta::CPAN
# your specific needs
sub clone {
my $self = shift;
my $new = [];
$new->[0] = [@{$self->[0]}];
return bless $new, ref $self;
}
# You need some way to use the gene you've made and mutated, but
# this will let you have a look, if it starts being odd.
sub render_gene {
my $self = shift;
my $return = "$self\n";
$return .= (join ',', @{$self->[0]}). "\n";
return $return;
}
# used for testing
AI/Gene/Simple.pm view on Meta::CPAN
overriding any you do not like in the module.
=item C<mutate_insert([num, pos])>
Inserts a single token into the string at position I<pos>.
The token will be randomly generated by the calling object's
C<generate_token> method.
=item C<mutate_overwrite([num, pos1, pos2, len])>
Copies a section of the gene (starting at I<pos1>, length I<len>)
and writes it back into the gene, overwriting current elements,
starting at I<pos2>.
=item C<mutate_reverse([num, pos, len])>
Takes a sequence within the gene and reverses the ordering of the
elements within that sequence. Starts at position I<pos> for
length I<len>.
=item C<mutate_shuffle([num, pos1, pos2, len])>
This takes a sequence (starting at I<pos1> length I<len>)
from within a gene and moves
it to another position (starting at I<pos2>). Odd things might occur if the
position to move the sequence into lies within the
section to be moved, but the module will try its hardest
to cause a mutation.
=item C<mutate_duplicate([num, pos1, pos2, length])>
This copies a portion of the gene starting at I<pos1> of length
I<length> and then splices it into the gene before I<pos2>.
=item C<mutate_remove([num, pos, length]))>
Deletes I<length> tokens from the gene, starting at I<pos>. Repeats
I<num> times.
=item C<mutate_minor([num, pos])>
This will mutate a single token at position I<pos> in the gene
into one of the same type (as decided by the object's C<generate_token>
method).
=item C<mutate_major([num, pos])>
This changes a single token into a token of any token type.
Token at postition I<pos>. The token is produced by the object's
C<generate_token> method.
=item C<mutate_switch([num, pos1, pos2, len1, len2])>
This takes two sequences within the gene and swaps them
into each other's position. The first starts at I<pos1>
with length I<len1> and the second at I<pos2> with length
I<len2>. If the two sequences overlap, then no mutation will
be attempted.
=back
The following methods are also provided, but you will probably
want to overide them for your own genetic sequences.
=over 4
demo/Regexgene.pm view on Meta::CPAN
=head2 Constructor
As we want to be able to fill our regular expression at the same
time as we create it and because we will want to nest sequences
we will need some way to know how deep we are, then a different
B<new> method is needed.
If called as an object method (C<$obj->new>), this decreases the depth
count by one from the invoking object. It also adds tokens to the regular
expression and uses the B<valid_gene> method to ensure we stay sane
from the start.
As can be seen, we use array offsets above $self->[1] to store information
which is specific to our implementation.
=cut
sub new {
my $gene = ['',[], ref($_[0]) ? $_[0]->[2]-1 : 3 ]; # limit recursion
bless $gene, ref($_[0]) || $_[0];
my $length = $_[1] || 5;
demo/Regexgene.pm view on Meta::CPAN
sub clone {
my $self = shift;
my $new = bless [$self->[0], [], $self->[2]], ref($self);
@{$new->[1]} = map {ref($_) ? $_->clone : $_} @{$self->[1]}; # woohoo, recursive objects
return $new;
}
=head2 generate_token
This is where we really start needing to have our own implementation.
This method is used by AI::Gene::Sequence when it needs a new
token, we also use it ourselves when we create a new object, but we
did not have to.
If we are provided with a token type, we use that, otherwise we chose
one at random. We make sure that we return a two element list.
If we had wanted, when passed a type of 'g' along with a second
argument, we could have caused this method to mutate the nested
regex, instead, we just create a different one.
demo/music.pl view on Meta::CPAN
use strict;
use warnings;
use Musicgene;
# make something to start from
my @seeds;
for (0..9) {
$seeds[$_] = Musicgene->new(20);
print "$_ : ", ($seeds[$_]->_test_dump)[0], "\n";
$seeds[$_]->write_file('music'.$_.'.mid');
}
print "Enter number to retain (0-9):";
while (<>) {
chomp;
demo/spamscan.pl view on Meta::CPAN
my $num_mutates = 3;
# read in our passes and failures.
my (@wanted, @spam);
while (<DATA>) {
if (1../^$/) { push @wanted, $_;}
else { push @spam, $_}
}
print "Best score possible is: ", scalar(@spam), "\n";
my $regex = seed_match(); # start off with something quite good
my $best_yet = 0;
my $temp = 1;
while (1) {
my $child = $regex->clone; # copy the parent
$child->mutate($num_mutates); # change it slightly
my $rex = $child->regex;
$rex = qr/$rex/;
my $score = 0; # see if the kid is better
$score += grep {$_ =~ $rex} @spam; # we don't want spam
$score -= grep {$_ =~ $rex} @wanted; # but we do want our mail
$rt = $gene->mutate_reverse(1,0,10); # whole gene
ok($rt,1);
ok($gene->d, 'jihgfedcba');
ok($gene->g, 'jihgfedcba');
$gene = $main->clone;
$rt = $gene->mutate_reverse(1,8,4); # extends beyond gene
ok($rt,0);
ok($gene->d, 'abcdefghij');
ok($gene->g, 'abcdefghij');
$gene = $main->clone;
$rt = $gene->mutate_reverse(1,10,1); # starts outside gene
ok($rt,0);
ok($gene->d, 'abcdefghij');
ok($gene->g, 'abcdefghij');
# hammer randomness
$rt = 0;
for (1..$hammer) {
$gene = $main->clone;
eval '$gene->mutate_reverse(1,undef,0)';
$rt = 1 if $@;
}
ok($gene->d, 'bacdefghij');
$gene = $main->clone;
$rt = $gene->mutate_reverse(1,0,10); # whole gene
ok($rt,1);
ok($gene->d, 'jihgfedcba');
$gene = $main->clone;
$rt = $gene->mutate_reverse(1,8,4); # extends beyond gene
ok($rt,0);
ok($gene->d, 'abcdefghij');
$gene = $main->clone;
$rt = $gene->mutate_reverse(1,10,1); # starts outside gene
ok($rt,0);
ok($gene->d, 'abcdefghij');
# hammer randomness
$rt = 0;
for (1..$hammer) {
$gene = $main->clone;
eval '$gene->mutate_reverse(1,undef,0)';
$rt = 1 if $@;
}
ok($rt,0);
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.)
BEGIN { $| = 1; print "1..1\n"; }
END {print "not ok 1\n" unless $loaded;}
use AI::Gene::Sequence;
use AI::Gene::Simple;
$loaded = 1;
print "ok 1\n";