AMONKEYS Annotation

advertisement
Evolve 2012.01.28
Mark Spahn markspahn@verizon.net
This program crudely simulates evolution by taking a target-string of characters, then producing successive
generations of a string whose characters randomly vary until the character in a given position becomes the
same as the corresponding character in the target-string, after which that character remains the same. How
many generations does it take for the random string to “evolve” to become the target-string?
Here we imagine an N-character string (such as the Gettysburg Address, for which N=1456) and N monkeys,
each before a keyboard offering a selection of M characters. Each monkey repeatedly hits a key at random,
and if he hits “his” target character, his choice of character is henceforth locked in. The monkeys keep going
until, in K random guesses, the target string has been zeroed in on.
Program:AMonkeys
If 0:0rand
; if desired, use fixed sequence of random numbers
FnOff
; turn off the graphing functions Yn
“ABCDEFGHIJKLMNOPQRSTUVWXYZ .’:,-”Str0; A to Z, space, period, apostrophe, colon, hyphen
length(Str0)M
; how many characters to randomly choose from
AxesOff:ClrDraw
“FOUR SCORE AND”Str1
; set Str1 to the default target string
If 0:Then
Disp “INPUT TARGET STR”
Disp “HIT 2ND ALPHA”
Disp “END W/ <ENTER>”
Input Str1
For(I,1,length(Str1))
If inString(Str0,sub(Str1,I,1))=0
Then
Disp “BAD CHAR”,I,Str1
Stop
End
End
End
; If desired,
; tell user how to input his own string,
length(Str1)N
For(I,1,N)
Text(0,4(I-1),sub(Str1,I,1))
End
1D
prgmRun
; length of the string (target string, evolving string)
; Show target string
; at top, each char in its 4-pixel-wide space
; and input a user-defined string:
; make sure that each char is in the alphabet in Str0
; if not, start over
; End of If inString(
; End of For(I
; End of If 0/1:Then
; turn on the “Display” mode
Given a random N-char target-string Str1, guess at it till you guess it all (in K guesses).
A run is a guess-till-success sequence of string-guesses in which each character is guessed at randomly from
an alphabet of M characters and any correctly guessed character is retained in all subsequent guesses. That
is, in each string-guess, only the still-unguessed characters are guessed at.
Program:Run
“<theta>”Str2
; set guess-string to N <theta>s (all wrong characters)
For(I,2,N):Str2+“<theta>”Str2:End
NU
; how many unmatched (unguessed) chars are left
0K
; how many string-guesses made
Repeat U=0
1+KK
For(I,1,N)
If sub(Str2,I,1).ne.sub(Str1,I,1)
; if corresponding letters are different,
Then
sub(Str0,randInt(1,M),1)Str3
; pick a random character Str3
If Str3=sub(Str1,I,1):U-1U
; if char was guessed right, decrement Unguessed count
If I=1:Then
; put character Str3 into position I of string Str2
Str3+sub(Str2,2,N-1) Str2:Else
If I=N:Then
sub(Str2,1,N-1)+Str3Str2:Else
sub(Str2,1,I-1)+Str3+sub(Str2,I+1,N-I) Str2
End
; End of If I=N:Then:..:Else
End
; End of If I=1:Then:..:Else
End
; End of If sub(Str2,I,1).ne.sub(Str1,I,1)
End
; End of For(I
If D:Then
; if “display” mode is turned on,
K-1T
; K-th string should appear on line T = ((K-1) mod 9)+1
T-9int(T/9)+1T
T+1I:If I>9:1I
; Erase the following line I (for easy-to-read spacing)
6TT:6II
; (each line is 6 pixels tall)
For(J,0,4(N+5),4)
; erase N+5 chars (each 4 pixels wide)
Text(I,J, “ ”)
; 4 spaces
End
For(I,1,N)
; show each char of Str2 on line T of screen
Text(T,4(I-1),sub(Str2,I,1))
; positioned in its 4-pixel-wide space
End
Text(T,4N,“ ”,K,“ ”,U, “ ”)
; 3 spaces, generation number K, 2 spaces, how many
; U unmatched chars left, 4 spaces to overwrite previous
getKeyT:If T=103:Pause
; Pause if decimal-point key has been pressed
End
; End of If D
End
; End of Repeat U=0
Graphs the probability density function Y1(x) = (1 – q^x)^n – (1 – q^(x-1))^n for a specified m, n
Program:BPrbCurv
Prompt M,N
; hm chars in alphabet, length of target-string
1/MP
; prb that a random guess at a char will be correct
1-PQ
; prb of guessing a given char wrongly
“(1-Q^X)^N-(1-Q^(X-1))^N”Y1
; prb of guessing an N-char string in exactly X guesses
2Xres
; faster than Xres=1 (8 sec vs 27 sec), little degradation
0Ymin
; Y1(x) reaches its max at L. Find L, Ymax:
If N=1:Then
; For N=1, a hand analysis say max Y1(x) is at
1L:P/QYmax
; x=0, where Y1(0)=P/Q
Else
Q^(1/(N-1))T
; Y1 reaches its maximum at this L; that’s where Y1’(x)=0,
(log(1-T)-log(1-QT))/log(Q)+1L
; says a calculus analysis by hand
Y1(L)Ymax
End
prgmSetAB
; Determine a suitable A=Xmin, B=Xmax for graphing
AXmin:BXmax
Xmax-XminV:prgmTickSize:TXscl
; set size of tick-marks on X- and Y-axes
Ymax-YminV:prgmTickSize:TYscl
FnOff
; turn functions off (don’t graph just yet)
AxesOff:ClrDraw:AxesOn
4dim(L1)
; store values for .25, .50, .75, .99 temporarily in L1
Fill(0,L1)
; ensures real number is L1, even if held complex numbers
.25S:prgmSplitAtS:CL1(1)
.50S:prgmSplitAtS:CL1(2)
.75S:prgmSplitAtS:CL1(3)
.99S:prgmSplitAtS:CL1(4)
95-max(4+1+int(log(max({B,M,N})))),2+4(5+int(log(L1(dim(L1)))))) C ; set margin
0I
Text(I,C,“A=”,A):6+II
; Display list of values
Text(I,C,“.25:”,L1(1)):6+II
Text(I,C,“ MX:”,L):6+II
Text(I,C “.50:”,L1(2)):6+II
Text(I,C “.75:”,L1(3)):6+II
Text(I,C “.99:”,L1(4)):6+II
Text(I,C, “B=”,B):6+II
95-4(3+int(log(max(M,N))))C
; set margin
Text(I,C, “M=”,M):6+II
Text(I,C, “N=”,N)
FnOn 1:DispGraph
; turn on function Y1 and graph it
For graphing assuming Xmin=Ymin=0, select a proper tick-mark size T for the X- or Y-axis,
given maximum positive value V.
Program:TickSize
10^(int(log(V)))T
; find correct power of 10
If V/T<2:T/5T
; if too few ticks, use smaller tick size
If V/T<3:T/2T
Given probability s, show a dotted line on the graph at k, where P{success within k guesses} = s.
Program:SplitAtS
log(1-N xsqrt S)/log(Q)C
int(94(C-Xmin)/(Xmax-Xmin))J
; how far across the screen
int(62-62(Y1(C)-Ymin)/(Ymax-Ymin))+1I ; show the dividing line as a dotted line
If I>50:Return
; if too narrow to show dotted line, don’t
59T:Repeat T.le.I
; show dotted line in pixel column J
Pxl-On(T,J)
T-2T:End
In drawing the curve Y1(x) from x=A to x=B, determine what A and B should be.
The function’s maximum value is at x=L.
Program:SetAB
Ymax/100T
; target value T, 1/100 the maximum value
1A
; take A=1 if Y1(1).ge.T
If Y1(1)<T:Then
1I:int(L)K
; Y1 increases from Y1(I)<T to Y1(K)>T
Repeat K-I.le.1
; move I and K together, bracketing target T
int(I+K)/2) J
; set J to midpoint integer between I and K
If Y1(J)>T:Then:JK:Else:JI:End
End
IA
; Y1(A) is near target value T
End
int(L)+1I:1E6K
; Y1 decreases from L to infinity
Repeat K-I.le.1
; squeeze I and K together around target value T
int(I+K)/2)J
If Y1(J)<T:Then:JK:Else:JI:End
End
KB
; Y1(B) is near the target value T
End
If 1:Return
; Done. But to ensure that the pixel distance between
1I:While A+47I<B:1+II:End
; successive integers is constant, adjust B so that
A+47IB
; (B-A) is a multiple of 47 (half the pixels 0-94 on screen).
Assuming that the routine GuessCrv has just been run, this routine makes multiple runs of guesses at an Ncharacter target-string randomly chosen from an alphabet of M characters, and makes a bar graph for K from
A to B, of how many times the target-string was fully guessed in K characters. This bar graph (histogram) is
superimposed on the curve giving the theoretical probability for each value K in the range.
This routine is practical only for small M and N. For a good demonstration, run GuessCrv with M=2, N=3,
and do R=200 runs. The histogram will be similar to the curve. Or try M=4, N=3, R=500, which will take
about 17 minutes.
Program:CBarGraf
; was: GetStats
sub(“ABCDEFGHIJKLMNOPQRSTUVWXYZ .’:,-”,1,M)Str0 ; get M-character alphabet
B-A+1dim(L1):Fill(0,L1)
; keep count in list L1, for K from A to B
Input “HM RUNS=”,R
; how many runs to do in guessing at a target string
DispGraph
; display the graph of the curve, then overwrite it
Text(12,40,“R=”,R)
; how many runs will be made
Text(18,40,“W=”,W)
; which-number run this is
Text(24,40,“K=”,K)
; how many guesses it took to guess the target-string
startTmrO
; Time how many seconds the R runs take
0D
; turn off “Display” mode (for the routine Run)
For(W,1,R)
“<theta>”Str1
; set Str1 to an N-char random string of the first M letters
For(I,1,N)
sub(Str0,randInd(1,M),1)+Str1Str1
End
sub(Str1,1,N) Str1
; drop the <theta> from Str1
Text(0,C-4N-4,Str1)
; show the target string Str1
prgmRun
Text(24,48,K,“ ”)
; show how many guesses this run took
If K<A:AK
; increment the proper item in list L1
If K>B:BK
K-A+1T
1+L1(T)L1(T)
61-L1(T)I
; turn on the proper pixel of the bar graph
If I.ge.0:Pxl-On(I,int(94(K-A)/(B-A)))
Text(18,48,W)
; how many runs have been completed so far
If 0:Text(06,40,startTmr-O)
; if desired, how many seconds these W runs have taken
End
startTmr-OO
; how many seconds the R runs took
For(J,40,63)
; erase 6 4-pixel-wide characters
Text(00,J,“ ”)
; erase test string
Text(18,J,“ ”)
; erase W line
Text(24,J,“ ”)
; erase K line
If 0:StorePic 1
; if desired, store a picture of the resulting screen
Given alphabet size M and target-string length N, for a given degree of certainty (probability S), compute
how many string-guesses K are needed so that (1-q^k)^n = P{completely guessing the target-string in k or
fewer guesses} = s. Solving for k, we get k = log(1 – n-th root of s)/log q, where q = 1-1/M.
Program:HmSure
; how many guesses needed to be S sure of success
Prompt M,N
1/MP:1-PQ
While 1
Prompt S
ln(1-N xSqrt S)/ln(Q)X
; real x for which f(x) = s, where f(x) := (1-q^x)^n
Disp X
int(X)K:Disp K+(1-Q^K)^N
; integer k.P{guessing the string in k guesses}
1+KK:Disp K+(1-Q^K)^N
; next integer (k+1).P{guessing the string in (k+1) guesses}
End
Example: For M=27, N=15,
S=?.5
82.07610326 means f(82.0761032) = .5
82.49898073 means f(82) = .49898073, just under .5
83.51229367 means f(83) = .51229367, just over .5
S=?.95
150.5009374 means this is the real number x where f(x) = .95 (95% sure of success)
150.9490688 means that with 150 guesses, you are 94.90688% sure of success
151.9509112 means that with 151 guesses, you are 95.09112% sure of success
Uses the algorithm given on page 320 of the Chemical Rubber Company (CRC) Handbook of Chemistry and
Physics, 44th Edition, 1962-63, and explained at http://www.sosmath.com/algebra/factor/fac11/fac11.html .
SSolve the cubic equation y^3 + py^2 + qy + r = 0 by reducing it to the equation x^3 + ax + b = 0 (where
there is no x^2 term) by setting y = x – p/3 and taking a = (1/3)(3q – p^2), b = (1/27)(2p^3 – 9pq + 27r),
then finding the three roots for x, and converting these roots back to y by y = x – p/3.
Program:ACubic
a+bi
; set to “complex number” mode (hit MODE, scroll)
Prompt P,Q,R
(3Q-P^2)/3A
2P^3/27+PQ/3+RB
A^3/27+B^2/4D
-B/2T
3Sqrt(T+Sqrt(D))F
; cube root of [–b/2 + sqrt(a^3/27+b^2/4)]
3Sqrt(T-Sqrt(D))G
; (for “cube root” 3Sqrt, hit MATH, 4)
3dim(L1)
F+GL1(1)
; first root
-.5(F+G)+.5sqrt(3)(F-G)iL1(2)
; second root
-.5(F+G)-.5sqrt(3)(F-G)iL1(3)
; third root
L1-P/3L1
; convert x roots back into y roots
If D.le.0:real(L1)L1
; if all-real roots, convert complex numbers to reals
Real
; restore Real mode; F, G, L1 might contain complex numbers
Download