OPTION BASE 1
CONST Target$ = "Brave New World!"
CONST DomainSize = 400
CONST CloneRate = 40
CONST MutateRate = 20
DECLARE Population$[DomainSize]
DECLARE Nextgen$[DomainSize]
CONST TLen = LEN(Target$)
FUNCTION Fitness(STRING chromosome$)
LOCAL x, status
FOR x = 1 TO TLen
DECR status, ABS(ASC(MID$(chromosome$, x, 1)) - ASC(MID$(Target$, x, 1)))
NEXT
RETURN status
END FUNCTION
SUB Populate
LOCAL x, y
FOR x = 1 TO DomainSize
Population$[x] = ""
FOR y = 1 TO TLen
Population$[x] = Population$[x] & CHR$(RANDOM(94)+32)
NEXT y
NEXT x
END SUB
SUB Generate
LOCAL m1, m2, m3, m4, x, pos
LOCAL mutant1$, mutant2$
FOR x = 1 TO DomainSize STEP 2
m1 = RANDOM(DomainSize)+1
m2 = RANDOM(DomainSize)+1
m3 = RANDOM(DomainSize)+1
m4 = RANDOM(DomainSize)+1
IF RANDOM(100)+1 < CloneRate THEN
IF Fitness(Population$[m1]) > Fitness(Population$[m2]) THEN
Nextgen$[x] = Population$[m1]
ELSE
Nextgen$[x] = Population$[m2]
END IF
IF Fitness(Population$[m3]) > Fitness(Population$[m4]) THEN
Nextgen$[x+1] = Population$[m3]
ELSE
Nextgen$[x+1] = Population$[m4]
END IF
ELSE
pos = RANDOM(TLen-2)+2
Nextgen$[x] = MID$(Population$[m1], 1, pos) & MID$(Population$[m2], pos+1)
Nextgen$[x+1] = MID$(Population$[m2], 1, pos) & MID$(Population$[m1], pos+1)
END IF
IF RANDOM(100)+1 < MutateRate THEN
pos = RANDOM(TLen)+1
mutant1$ = "" : mutant2$ = ""
FOR y = 1 TO TLen
IF y = pos THEN
m1 = ASC(MID$(Nextgen$[x], pos, 1)) + RANDOM(11) - 5
IF m1 > 126 THEN m1 = m1 - 127 + 32
IF m1 < 32 THEN m1 = m1 + 127 - 32
mutant1$ = mutant1$ & CHR$( m1 )
m2 = ASC(MID$(Nextgen$[x], pos, 1)) + RANDOM(11) - 5
IF m2 > 126 THEN m2 = m2 - 127 + 32
IF m2 < 32 THEN m2 = m2 + 127 - 32
mutant2$ = mutant2$ & CHR$( m2 )
ELSE
mutant1$ = mutant1$ & MID$(Nextgen$[x], y, 1)
mutant2$ = mutant2$ & MID$(Nextgen$[x+1], y, 1)
END IF
NEXT
Nextgen$[x] = mutant1$
Nextgen$[x+1] = mutant2$
END IF
NEXT
FOR x = 1 TO DomainSize
Population$[x] = Nextgen$[x]
NEXT
END SUB
FUNCTION FindMatch
LOCAL x, closest = -127*TLen, ind
FOR x = 1 TO DomainSize
IF Fitness(Population$[x]) > closest THEN
closest = Fitness(Population$[x])
ind = x
END IF
NEXT
RETURN ind
END FUNCTION
gen = 0
Populate
REPEAT
Generate
INCR gen
ind = FindMatch()
IF NOT(MOD(gen, 5)) THEN PRINT "Generation ", gen, " best: ", Population$[ind]
UNTIL Fitness(Population$[ind]) IS 0
PRINT "-----------------------------------"
PRINT "Generation ", gen, " best: ", Population$[ind]
PRINT "-----------------------------------"