Revision: 36415
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at November 22, 2010 01:05 by StanislavZza
Initial Code
local $| = 1; #forces stdout to flush so the dots show up.
#set up parameters..................................
$first = 3;
$end = 100; # upper bound on the N to use
$max_gen = 1000; # how many generations to run for each
$max_pop = 100; # carrying capacity C
open(OUT,'>output.txt') or die 'hard'; # this is where the summary output goes
open(MISS,'>missing.txt'); # this creates a list of all the 'missing' values for N
# first add some column headings
print OUT "Start,Generation,PopSize,Last,Demand,Kids,Died,Total\n";
# main loop to generate summary stats and individual report files for each N
for ($start = $first ;$start < $end; $start+=2) { #just do the odd numbers
sim($start);
print ".";
}
print "\n";
# run the simulation for the given N
sub sim {
undef %n; #keeps track of what numbers are still in the ecology. Zero out before each run
undef %all; #keeps track of any number ever hit
$id = $_[0]; # the starting number N is the argument
# you need to have a folder called 'sim' to dump the details in
open(START,">sim//$id.txt") or die; #set up for windows. If you run Linux change the slashes
$generation = 0; #initialize for this run
$all{$id} = $n{$id} = 1; # associative arrays will keep track of who was and is alive
$last = $start; #keeps track of the biggest number reached for the summary report
while($generation < $max_gen) {
$generation++;
$pop = scalar(keys(%n)); # get the size
print OUT "$start,$generation,$pop,$last,";
$kids = $died = 0; #keeps track of reproduction and extinction for this generation
foreach $v (keys(%n)) { #go through the population and iterate
if ($v % 2 == 0) { # if even divide by two
$v /=2;
if ($v == 1) { # kill it if it reaches 1
# it will vanish because it doesn't get copied to %n1
$died++; # keep track of how many we lost
} else {
$all{$v} = $n1{$v} = 1; # %n1 is the temp array for this work
}
} else { # it's odd, so do (3n+1)/2. Unless we're about to blow up our precision.
# have to have a rule about overflow. I'll chose to kill it off as being a hog.
if ($v > 1000000000) { # overflow problem
$died++;
} else {
$v = (3*$v + 1)/2;
$all{$v} = $n1{$v} = 1;
copy($v); # make the mutant--see function below
}
}
}
$demand = scalar(keys(%n2)); #save this for reporting
%n = %n1; # reset for the next trial. Yes, I should use pointers instead. I know.
$npop = scalar(keys(%n));
#now add in the new generation
foreach $num (sort(keys(%n2))) { # sorted so that we give the smaller ones priority
last if $npop >= $max_pop; # stop when we get to the capacity
next if $n{$num}; # already have this one in the population
$n{$num} = 1; # add it in
$npop++; # increment the total current population
$kids++;
}
$total = scalar(keys(%all)); # count the types who ever lived
print OUT "$demand,$kids,$died,$total\n";
# this prints out the whole population for this generation and N into N.txt in the sim folder
foreach $key (sort {$a <=> $b} (keys(%n))) {
print START "$key,";
}
print START "\n"; # all done with that row
undef %n1; # wipe our workspace clean
undef %n2;
}
close START;
# the sim is done. Print out what integers were missed between 2 and 1000
for($i =2;$i<1000;$i++) {
print MISS "$start,$i\n" unless $all{$i} > 0;
}
}
sub copy { #reproduce a number with mutation
$t = $_[0] - 2;
$all{$t} = $n2{$t}=1; #keep the kids separate, so we can apply the carrying capacity
$last = $t if $t > $last; #find the biggest one reproduced
}
Initial URL
http://highered.blogspot.com/2010/11/collatz-ecologies.html
Initial Description
See [blog post](http://highered.blogspot.com/2010/11/collatz-ecologies.html)
Initial Title
Collatz Ecology Generator
Initial Tags
Initial Language
Perl