home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / Perl / Non-RPC / !Perl / scripts / harness < prev    next >
Text File  |  1997-06-06  |  7KB  |  334 lines

  1. #!perl -w
  2. # !"k$mwd()¡,eea/wh |4bc789w;y=xpnAgCDEF|tIsKmMNOPlRSTU¡gwro[u]^_i
  3. BEGIN
  4. {
  5.     srand ($$ ^ time);
  6.     push @INC, '.';
  7. }
  8.  
  9. $boom = 0;
  10. $SIG{USR1} = sub {
  11.     $boom = 1;
  12. };
  13.  
  14. # sub { open(DEATH,">>$$") and print DEATH "Dying from:\n",@_ };
  15. # $SIG{__WARN__} = sub { open(WARN,">>$$") and print WARN "Warning about:\n",@_ };
  16.  
  17. use Victim qw( &individual &fitness $alphabet $target &intersection &other &alphabet &indexes &duplicates );
  18.  
  19. $pop_size = 1600;
  20. @best_fitness = undef;
  21. @best_individual = undef;
  22.  
  23. $mutate_prob = 0.001;
  24. $invert_prob = 0.003;
  25. $cheat_prob  = 0.006;
  26.  
  27. sub pront
  28. {
  29.     foreach (@_)
  30.     {
  31.         y/\r/¡/;
  32.         print;
  33.     }
  34. }
  35.  
  36. sub generate_population ($)
  37. {
  38.     my $i = shift;
  39.  
  40.     my (@pop, @inv);
  41.  
  42.     while( $i-- )
  43.     {
  44.     push @pop, [&individual];
  45.     }
  46.  
  47.     @pop;
  48. }
  49.  
  50. sub select_individual ($@)
  51. {
  52.     my $sum = shift;
  53.  
  54.     my( $rand, $partial_sum, $i ) = ( rand $sum, 0, scalar @_ );
  55.  
  56.     die $i unless $i > 0;
  57.     while( $i-- && $partial_sum <= $rand )
  58.     {
  59.     $partial_sum += $_[$i];
  60.     }
  61.  
  62.     --$i;
  63. }
  64.  
  65. sub old_permute_crossover ($$)
  66. {
  67.     # OK, so they are hermaphrodites
  68.  
  69.     my( $mum, $dad ) = @_;
  70.  
  71.     my( $mum_l, $dad_l ) = (length $mum, length $dad);
  72.  
  73.     die "'$mum'\n'$dad'\nOops. $mum_l != $dad_l" unless $mum_l == $dad_l;
  74.  
  75.     my( $where, $length, $chop );
  76.  
  77.     # Note that this can crossover after the last character!
  78.  
  79.     $where = rand $mum_l;
  80.     
  81.     $chop = substr $mum, $where, 1;
  82.     
  83.     if( -1 != ($length = index ($dad, $chop, $where + 1)))
  84.     {
  85. #        die "'$chop' '" . substr ($dad, $length, 1) ."'\n";
  86.     $length = $length - $where + 1;
  87.     }
  88.     else
  89.     {
  90.     $length = $mum_l - $where;
  91.     }
  92.  
  93.     $chop = substr $mum, $where, $length;
  94.     (substr $mum, $where, $length) = substr $dad, $where, $length;
  95.     (substr $dad, $where, $length) = $chop;
  96.  
  97.     ($mum, $dad);
  98. }
  99.  
  100. sub crossover ($$)
  101. {
  102.     # OK, so they are hermaphrodites
  103.  
  104.     my( $mum, $dad ) = @_;
  105.  
  106.     my( $mum_l, $dad_l ) = (length $$mum[0], length $$dad[0]);
  107.  
  108.     my( $sprog1, $sprog2 );
  109.     die "'$mum'\n'$dad'\nOops. $mum_l != $dad_l" unless $mum_l == $dad_l;
  110.  
  111.     my( $where, $length, $chop );
  112.  
  113.     # Note that this can crossover after the last character!
  114.  
  115.     $where = rand $mum_l;
  116.     $length = $mum_l - $where;
  117.  
  118.     $sprog1 = [@$mum];
  119.     $sprog2 = [@$dad];
  120.  
  121.     (substr $$sprog1[0], $where, $length) = substr $$dad[0], $where, $length;
  122.     (substr $$sprog2[0], $where, $length) = substr $$mum[0], $where, $length;
  123.  
  124.     # Unset cached fitness unless identical
  125.     @$sprog1 = ($$sprog1[0]) unless $$sprog1[0] eq $$mum[0];
  126.     @$sprog2 = ($$sprog2[0]) unless $$sprog2[0] eq $$dad[0];
  127.  
  128. #    print "Cache win\n" if defined $$sprog2[1];
  129.     ($sprog1, $sprog2);
  130. }
  131.  
  132. sub mutate ($)
  133. {
  134.     (substr $_[0], rand( length $_[0] ), 1)
  135.     = substr $alphabet, rand (length $alphabet), 1;
  136.  
  137.     $_[0];
  138. }
  139.  
  140. sub old_cheat ($)
  141. {
  142.     my ($where) = rand( length $_[0] );
  143.     
  144.     (substr $_[0], $where, 1)
  145.     = substr $Victim::uuchars, $where, 1;
  146.  
  147.     $_[0];
  148. }
  149.  
  150. sub cheat ($)
  151. {
  152.     my ($g) = shift;
  153.     my ($duplicates) = &duplicates ($g);
  154.     
  155.  
  156.     if( defined $duplicates )
  157.     {
  158.     my $char = substr $duplicates, rand (length $duplicates), 1;
  159.  
  160.     my (@where) = indexes( $g, $char );
  161.  
  162.     my $where = $where[rand $#where];
  163.  
  164.     die "$where in '$g' isn't $char" . join( ',', @where )
  165.         unless $char eq substr $g, $where, 1;
  166.  
  167.     my $replacements = &other( $Victim::chars, $g );
  168.  
  169.     $replacements = $alphabet if( $replacements eq '' );
  170.     
  171. #    print STDERR"'$g' '$replacements'\n'$char' -> '";
  172.     
  173.     (substr $g, $where, 1)
  174.         = substr $replacements, rand (length $replacements), 1;
  175.  
  176. #    die ((substr $g, $where, 1) . "'\n'$g'" )
  177.     }
  178.     else
  179.     {
  180.     (substr $g, $where, 1)
  181.         = substr $Victim::uuchars, $where, 1;
  182.     }
  183.  
  184.     $g;
  185. }
  186.  
  187. sub invert ($)
  188. {
  189.     my ($in, $out) = (shift);
  190.     
  191.     my ($in_l, $i) = length $in;
  192.     
  193.     my ($where, $length);
  194.  
  195.     $where = int rand $in_l;
  196.     $length = int rand ($in_l - $where);
  197.     
  198. #    print "$in_l $where $length\n";
  199. #    print "»$in«\n";
  200.     $out = substr $in, 0, $where;
  201.     
  202.     $i = $length;
  203.     while( $i-- )
  204.     {
  205.         $out .= substr $in, $where + $i, 1;
  206.     }
  207.     
  208.     $out .= substr $in, $where + $length;
  209. #    print "»$out«\n";
  210.     $out;
  211. }
  212.  
  213.  
  214. @population = generate_population( $pop_size );
  215. $generation = 0;
  216.  
  217. print "Here we go\n";
  218. $^W = 0; # Turn off warnings in the evals
  219. do
  220. {
  221.  
  222.     $sum_fitness = 0;
  223.     @best_fitness = undef;
  224.     @worst_fitness = undef;
  225.  
  226.     $i = $pop_size;
  227.     while( $i-- )
  228.     {
  229.     $this = $population[$i];
  230.     
  231.     unless( defined $$this[1] )
  232.     {
  233.         $genes = $$this[0];
  234.         $population[$i] = $this = [$genes, &fitness( $genes )];
  235.     }
  236.  
  237.     $sum_fitness += $fitness[$i] = $$this[1];
  238.      
  239.     @best_fitness = @$this
  240.         unless( defined $best_fitness[1] and $$this[1] < $best_fitness[1] );
  241.     @worst_fitness = @$this
  242.         unless( defined $worst_fitness[1] and $$this[1] > $worst_fitness[1] );
  243.     }
  244.  
  245.     $mean_fitness = $sum_fitness / $pop_size;
  246.     $best = $best_fitness[1];
  247.     $worst = $worst_fitness[1];
  248.  
  249.     $shift = ($best - $worst) * +0 - $worst;
  250.  
  251.     pront "Generation $generation\tBest = $best"
  252.     ."\tMean = $mean_fitness\tWorst = $worst"
  253.         ."\n$Victim::uuchars"
  254.         ."\n$best_fitness[0]\n$best_fitness[2]\n$best_fitness[3]"
  255.         ." \t\t$best_fitness[4]\n";
  256.  
  257.     # print ($population[0] . "\n");
  258.  
  259.     $sec = 0;
  260.     foreach( (@fitness) )
  261.     {
  262.         $_ += $shift;
  263.     
  264.  
  265.     $_ = 0 unless $_ > 0;    # $_ *= $_;
  266.         $sec += $_;
  267.     }
  268.  
  269. #    $sum_fitness += $shift * $pop_size;
  270.     
  271. #    print "$sum_fitness $sec\n";
  272.     @intermediate = ();
  273.     $i = $pop_size;
  274.  
  275. #    printf "%s\n%s\n", ${$population[0]}[0], ${$population[1]}[0];
  276.  
  277.     while( $i-- )
  278.     {
  279.     push @intermediate,
  280.     $population[select_individual($sec,@fitness)];
  281.     }
  282.  
  283. #    printf "%s\n%s\n", ${$intermediate[0]}[0], ${$intermediate[1]}[0];
  284.  
  285.     @population = ();
  286.  
  287.     while( scalar @intermediate )
  288.     {
  289.     push @population, crossover( shift @intermediate, shift @intermediate );
  290.     }
  291.  
  292.     $this_mutate = $mutate_prob * $pop_size;
  293.  
  294.     while( $this_mutate-- > 1 || (rand( 1 ) -1) < $this_mutate )
  295.     {
  296.     $victim = rand $pop_size;
  297.     $genes = mutate( ${$population[$victim]}[0] );
  298.     $population[$victim] = [$genes];
  299.     }
  300.  
  301.     $this_cheat = $cheat_prob * $pop_size;
  302.  
  303.     while( $this_cheat-- > 1 || (rand( 1 ) -1) < $this_cheat )
  304.     {
  305.     $victim = rand $pop_size;
  306.     $genes = cheat( ${$population[$victim]}[0] );
  307.     $population[$victim] = [$genes];
  308.     }
  309.     
  310.     $this_invert = $invert_prob * $pop_size;
  311.  
  312.     while( $this_invert-- > 1 || (rand( 1 ) -1) < $this_invert )
  313.     {
  314.     $victim = rand $pop_size;
  315.     $genes = invert( ${$population[$victim]}[0] );
  316.     $population[$victim] = [$genes];
  317.     }
  318.     
  319.     $generation++;
  320.  
  321.     if( $boom )
  322.     {
  323.     $boom = 0;
  324.     print "pop_size  = $pop_size\tmutate_prob = $mutate_prob\n";
  325.     print "pop_size  = $pop_size\tcheat_prob = $cheat_prob\n";
  326.     print "pop_size  = $pop_size\tinvert_prob = $invert_prob\n";
  327.     }
  328. }
  329. while( 1 );
  330.  
  331.  
  332.  
  333.  
  334.