use
lib
qw( ../../../lib )
;
our
@ISA
=
qw(Exporter)
;
our
$VERSION
=
sprintf
"3.4"
;
our
@EXPORT_OK
=
qw( entropy genotypic_entropy consensus hamming
random_bitstring random_number_array average
parse_xml decode_string vector_compare)
;
sub
entropy {
my
$population
=
shift
;
my
%frequencies
;
map
( (
defined
$_
->Fitness())?
$frequencies
{
$_
->Fitness()}++:1,
@$population
);
my
$entropy
= 0;
my
$gente
=
scalar
(
@$population
);
for
my
$f
(
keys
%frequencies
) {
my
$this_freq
=
$frequencies
{
$f
}/
$gente
;
$entropy
-=
$this_freq
*log
(
$this_freq
);
}
return
$entropy
;
}
sub
genotypic_entropy {
my
$population
=
shift
;
my
%frequencies
;
map
(
$frequencies
{
$_
->{
'_str'
}}++,
@$population
);
my
$entropy
= 0;
my
$gente
=
scalar
(
@$population
);
for
my
$f
(
keys
%frequencies
) {
my
$this_freq
=
$frequencies
{
$f
}/
$gente
;
$entropy
-=
$this_freq
*log
(
$this_freq
);
}
return
$entropy
;
}
sub
hamming {
my
(
$string_a
,
$string_b
) =
@_
;
return
( (
$string_a
^
$string_b
) =~
tr
/\1//);
}
sub
consensus {
my
$population
=
shift
;
my
$rough
=
shift
;
my
@frequencies
;
for
(
@$population
) {
for
(
my
$i
= 0;
$i
<
$_
->size();
$i
++ ) {
if
( !
$frequencies
[
$i
] ) {
$frequencies
[
$i
]={
0
=> 0,
1
=> 0};
}
$frequencies
[
$i
]->{
substr
(
$_
->{
'_str'
},
$i
, 1)}++;
}
}
my
$consensus
;
for
my
$f
(
@frequencies
) {
if
( !
$rough
) {
if
(
$f
->{
'0'
} >
$f
->{
'1'
} ) {
$consensus
.=
'0'
;
}
else
{
$consensus
.=
'1'
;
}
}
else
{
my
$difference
=
abs
(
$f
->{
'0'
} -
$f
->{
'1'
} );
if
(
$difference
< 0.4 ) {
$consensus
.=
'-'
;
}
else
{
if
(
$f
->{
'0'
} >
$f
->{
'1'
} ) {
$consensus
.=
'0'
;
}
else
{
$consensus
.=
'1'
;
}
}
}
}
return
$consensus
;
}
sub
average {
my
$population
=
shift
;
my
@frequencies
;
my
@fitnesses
=
map
(
$_
->Fitness(),
@$population
);
return
mean(
@fitnesses
);
}
sub
random_bitstring {
my
$bits
=
shift
|| croak
"No bits!"
;
my
$generator
= new String::Random;
my
$regex
=
"\[01\]{$bits}"
;
return
$generator
->randregex(
$regex
);
}
sub
random_number_array {
my
$dimensions
=
shift
|| croak
"No bits!"
;
my
$min
=
shift
|| -1;
my
$range
=
shift
|| 2;
my
@array
;
for
(
my
$i
= 0;
$i
<
$dimensions
;
$i
++ ) {
push
@array
,
$min
+
rand
(
$range
);
}
return
@array
;
}
sub
parse_xml {
my
$string
=
shift
|| croak
"No string to parse!\n"
;
my
$p
=new XML::Parser(
Style
=>
'EasyTree'
);
$XML::Parser::EasyTree::Noempty
=1;
my
$xml_dom
=
$p
->parse(
$string
) || croak
"Problems parsing $string: $!\n"
;
return
$xml_dom
;
}
sub
decode_string {
my
(
$chromosome
,
$gene_size
,
$min
,
$range
) =
@_
;
my
@output_vector
;
my
$max_range
=
eval
"0b"
.
"1"
x
$gene_size
;
for
(
my
$i
= 0;
$i
<
length
(
$chromosome
)/
$gene_size
;
$i
++ ) {
my
$substr
=
substr
(
$chromosome
,
$i
*$gene_size
,
$gene_size
);
push
@output_vector
, ((
$range
-
$min
) *
eval
(
"0b$substr"
) /
$max_range
) +
$min
;
}
return
@output_vector
;
}
sub
vector_compare {
my
(
$vector_1
,
$vector_2
) =
@_
;
if
(
scalar
@$vector_1
!=
scalar
@$vector_2
) {
croak
"Different lengths, can't compare\n"
;
}
my
$length
=
scalar
@$vector_1
;
my
@results
=
map
(
$vector_1
->[
$_
] <=>
$vector_2
->[
$_
], 0..(
$length
-1));
my
%comparisons
;
map
(
$comparisons
{
$_
}++,
@results
);
if
(
$comparisons
{1} && !
$comparisons
{-1} ) {
return
1;
}
if
( !
$comparisons
{1} &&
$comparisons
{-1} ) {
return
-1;
}
if
(
defined
$comparisons
{0} &&
$comparisons
{0} ==
$length
) {
return
0;
}
}
"Still there?"
;