Collatz Ecology Generator


/ Published in: Perl
Save to your folder(s)

See [blog post](http://highered.blogspot.com/2010/11/collatz-ecologies.html)


Copy this code and paste it in your HTML
  1. local $| = 1; #forces stdout to flush so the dots show up.
  2.  
  3. #set up parameters..................................
  4. $first = 3;
  5. $end = 100; # upper bound on the N to use
  6. $max_gen = 1000; # how many generations to run for each
  7. $max_pop = 100; # carrying capacity C
  8.  
  9. open(OUT,'>output.txt') or die 'hard'; # this is where the summary output goes
  10. open(MISS,'>missing.txt'); # this creates a list of all the 'missing' values for N
  11.  
  12. # first add some column headings
  13. print OUT "Start,Generation,PopSize,Last,Demand,Kids,Died,Total\n";
  14.  
  15. # main loop to generate summary stats and individual report files for each N
  16. for ($start = $first ;$start < $end; $start+=2) { #just do the odd numbers
  17. sim($start);
  18. print ".";
  19. }
  20. print "\n";
  21.  
  22. # run the simulation for the given N
  23. sub sim {
  24. undef %n; #keeps track of what numbers are still in the ecology. Zero out before each run
  25. undef %all; #keeps track of any number ever hit
  26. $id = $_[0]; # the starting number N is the argument
  27.  
  28. # you need to have a folder called 'sim' to dump the details in
  29. open(START,">sim//$id.txt") or die; #set up for windows. If you run Linux change the slashes
  30.  
  31. $generation = 0; #initialize for this run
  32.  
  33. $all{$id} = $n{$id} = 1; # associative arrays will keep track of who was and is alive
  34.  
  35. $last = $start; #keeps track of the biggest number reached for the summary report
  36.  
  37. while($generation < $max_gen) {
  38.  
  39. $generation++;
  40. $pop = scalar(keys(%n)); # get the size
  41.  
  42. print OUT "$start,$generation,$pop,$last,";
  43. $kids = $died = 0; #keeps track of reproduction and extinction for this generation
  44.  
  45. foreach $v (keys(%n)) { #go through the population and iterate
  46.  
  47. if ($v % 2 == 0) { # if even divide by two
  48. $v /=2;
  49. if ($v == 1) { # kill it if it reaches 1
  50. # it will vanish because it doesn't get copied to %n1
  51. $died++; # keep track of how many we lost
  52. } else {
  53. $all{$v} = $n1{$v} = 1; # %n1 is the temp array for this work
  54. }
  55. } else { # it's odd, so do (3n+1)/2. Unless we're about to blow up our precision.
  56. # have to have a rule about overflow. I'll chose to kill it off as being a hog.
  57. if ($v > 1000000000) { # overflow problem
  58. $died++;
  59. } else {
  60. $v = (3*$v + 1)/2;
  61. $all{$v} = $n1{$v} = 1;
  62. copy($v); # make the mutant--see function below
  63. }
  64. }
  65. }
  66.  
  67. $demand = scalar(keys(%n2)); #save this for reporting
  68. %n = %n1; # reset for the next trial. Yes, I should use pointers instead. I know.
  69. $npop = scalar(keys(%n));
  70.  
  71. #now add in the new generation
  72. foreach $num (sort(keys(%n2))) { # sorted so that we give the smaller ones priority
  73. last if $npop >= $max_pop; # stop when we get to the capacity
  74. next if $n{$num}; # already have this one in the population
  75. $n{$num} = 1; # add it in
  76. $npop++; # increment the total current population
  77. $kids++;
  78. }
  79.  
  80. $total = scalar(keys(%all)); # count the types who ever lived
  81.  
  82. print OUT "$demand,$kids,$died,$total\n";
  83.  
  84. # this prints out the whole population for this generation and N into N.txt in the sim folder
  85. foreach $key (sort {$a <=> $b} (keys(%n))) {
  86. print START "$key,";
  87. }
  88. print START "\n"; # all done with that row
  89.  
  90. undef %n1; # wipe our workspace clean
  91. undef %n2;
  92. }
  93. close START;
  94.  
  95. # the sim is done. Print out what integers were missed between 2 and 1000
  96. for($i =2;$i<1000;$i++) {
  97. print MISS "$start,$i\n" unless $all{$i} > 0;
  98. }
  99. }
  100.  
  101. sub copy { #reproduce a number with mutation
  102. $t = $_[0] - 2;
  103. $all{$t} = $n2{$t}=1; #keep the kids separate, so we can apply the carrying capacity
  104. $last = $t if $t > $last; #find the biggest one reproduced
  105. }

URL: http://highered.blogspot.com/2010/11/collatz-ecologies.html

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.