in reply to Re: optimization help
in thread optimization help
#!/usr/local/bin/perl -w # Based on ideas and code by bjm@paralynx.com # (Brad Murray), posted to perl-ai list June 3 1999. use strict; use Time::HiRes 'time'; require 'dumpvar.pl'; no strict "refs"; my @functions = ( 'sub { # sin(x) my $in = shift; return sin($in); }', 'sub { # add(x,y) my ($left,$right) = @_; return ($left + $right); }', 'sub { # mul(x,y) my ($left,$right) = @_; return ($left * $right); }', 'sub { # log(x) my $in = shift; return ($in == 0) ? 0 : log(abs($in)); }', ); my @terminals = ( \&identity, \&constant ); my $x; my %tree; my $maxdepth = 5; my $pop = 200; my $mates = 10; my $gen = 3; # syntax tree is a set of hashes: # # %node{left} = $nodereference or undef # %node{right} = $nodereference or undef # %node{contents} = $funcref or 'x' or constant # # sin(0.231 * log($x)) # # sin(multiply(0.231,log($x,0)),0) # # undef # sin---multiply----0.231< # | | undef undef # 0 +--------log----------$x< # | undef # 0 # # # get target data set my $inline = <DATA>; my @target = split /,/, $inline; # build a starting population of $pop my @world = map {{organism => new Organism}} 0..$pop; my $count = 0; for (1..$gen) { print "\nGENERATION ", ++$count, "\n"; foreach (@world) { $_->{fitness} = &fitness($_->{organism}{tree},@target); $_->{as_string} = $_->{organism}->as_string; } @world = sort { $a->{fitness} <=> $b->{fitness} or length $a->{as_string} <=> length $b->{as_string} } @world; foreach (@world) { print "=== Fitness: $_->{fitness} ===\n"; print $_->{as_string}, "\n"; } # Kill off some organisms, mate some others to take their spots for (0..($mates-1)) { pop @world; my ($org1, $org2) = ($world[$_]{organism}, $world[rand @world]{organism}); my $child = $org1->mate($org2); unshift @world, {organism => $child}; print "Created '@{[$child->as_string]}' from " . "'@{[$org1->as_string]}' and '@{[$org2->as_string]}'\n"; } # mutate one organism at random my $to_mutate = $world[rand @world]{organism}; print "Mutated '@{[$to_mutate->as_string]}' into "; $to_mutate->mutate; print "'@{[$to_mutate->as_string]}'\n"; } # ------------ subs sub fitness { my ($org, @target) = @_; my $sumdiff = 0; my %p; my $starttime; my $endtime; foreach (0..$#target) { $starttime = time(); $p{'x'} = $_; my $value = &evalTree($org,\%p); $sumdiff += abs($value - $target[$_]); $endtime = time(); $sumdiff += ($endtime - $starttime); } return $sumdiff/(scalar @target); } sub evalTree { my $intree = shift; my $param = shift; local $_ = $intree->{contents}; # A shortcut for the current node return 0 unless defined; if (/^sub /) { return eval->( evalTree($intree->{left},$param), evalTree($intree->{right},$param) ); } elsif (/^[A-Za-z]$/) { return $param->{$_}; } else { return $_; } } # ------------ terminal subs sub identity { return 'x'; } sub constant { return int(rand(20) - 10); } ###################################################### package Organism; use Storable qw(dclone); sub new { my $package = shift; my $self = {tree => $package->_buildTree() }; return bless $self, $package; } sub _buildTree { my $self = shift; my $depth = shift || 0; my %tree; if ($depth > $maxdepth) { $tree{contents} = &{$terminals[rand @terminals]}; } else { $tree{contents} = (int rand(3) ? $functions[rand @functions] : &{$terminals[rand @terminals]} ); } if ($tree{contents} =~ /^sub /) { $tree{left} = $self->_buildTree($depth + 1); $tree{right} = $self->_buildTree($depth + 1); } return \%tree; } sub mate { my ($self, $partner) = @_; my $self_clone = dclone($self); my $partner_clone = dclone($partner); # Get a node from $partner and stick it somewhere in $self_clone my @clone_index = $self_clone->_treeIndex; my @partner_index = $partner_clone->_treeIndex; %{ $clone_index[rand @clone_index] } = %{ $partner_index[rand @partner_index]}; return $self_clone; } sub mutate { my $self = shift; my @index = $self->_treeIndex; %{ $index[rand @index] } = %{ $self->_buildTree($maxdepth-1) }; } sub _treeIndex { # Generates a list of all the nodes in this tree. These are # references to the stuff in the object itself, so changes to the # elements of this list will change the object. my $self = shift; my $tree = shift || $self->{tree}; my @sofar = @_; # Dump the content nodes into a list if ($tree->{contents} =~ /^sub /) { return(@sofar, $tree, $self->_treeIndex($tree->{left}, @sofar), $self->_treeIndex($tree->{right}, @sofar) ); } else { return(@sofar, $tree); } } sub as_string { my $self = shift; my $tree = shift || $self->{tree}; if ($tree->{contents} =~ /^sub \{ \# (\w+)/) { return "$1(" . $self->as_string($tree->{left}) . ',' . $self->as_string($tree->{right}) . ')'; } else { return $tree->{contents}; } } #Total Elapsed Time = 5.147911 Seconds # User+System Time = 4.886911 Seconds #Exclusive Times #%Time ExclSec CumulS #Calls sec/call Csec/c Name # 97.4 4.760 4.973 153323 0.0000 0.0000 main::evalTree # 11.4 0.560 5.580 603 0.0009 0.0093 main::fitness # 4.36 0.213 0.213 71536 0.0000 0.0000 main::__ANON__ # 1.64 0.080 0.080 9733 0.0000 0.0000 Organism::as_string # 0.96 0.047 0.047 20502 0.0000 0.0000 Time::HiRes::time # 0.63 0.031 0.031 7 0.0044 0.0044 IO::File::BEGIN # 0.33 0.016 0.016 6 0.0027 0.0026 ActiveState::Path::BEGIN # 0.33 0.016 0.047 4 0.0040 0.0116 main::BEGIN # 0.31 0.015 0.015 60 0.0002 0.0002 Storable::dclone # 0.31 0.015 0.015 843 0.0000 0.0000 main::constant # 0.29 0.014 0.014 858 0.0000 0.0000 main::identity # 0.08 0.004 0.032 3198 0.0000 0.0000 Organism::_buildTree # 0.00 0.000 0.000 1 0.0000 0.0000 Config::launcher # 0.00 0.000 0.000 1 0.0000 0.0000 Config::fetch_string # 0.00 0.000 0.000 1 0.0000 0.0000 Exporter::Heavy::heavy_e +xport_to_l # evel __END__ -1407,-931,-577,-327,-163,-67,-21,-7,-7,-3,23,89,213,413,707,1113,16 +49
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^3: optimization help
by ikegami (Patriarch) on Oct 15, 2007 at 23:05 UTC | |
by samtregar (Abbot) on Oct 15, 2007 at 23:06 UTC | |
by GSF (Acolyte) on Oct 16, 2007 at 16:24 UTC | |
by ikegami (Patriarch) on Oct 16, 2007 at 16:29 UTC | |
by GSF (Acolyte) on Oct 16, 2007 at 17:10 UTC |