Skip to content

Instantly share code, notes, and snippets.

@SeanTAllen
Created May 11, 2016 13:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SeanTAllen/dd6267195ca4107fc9a0020b47479d04 to your computer and use it in GitHub Desktop.
Save SeanTAllen/dd6267195ca4107fc9a0020b47479d04 to your computer and use it in GitHub Desktop.
use "random"
use "collections"
class CreationFactory
let _desired: String
new create(d: String) =>
_desired = d
fun apply(c: String): Creation =>
Creation(c, _fitness(c))
fun _fitness(s: String): USize =>
var f = USize(0)
for i in Range(0, s.size()) do
try
if s(i) == _desired(i) then
f = f +1
end
end
end
f
class val Creation
let string: String
let fitness: USize
new val create(s: String = "", f: USize = 0) =>
string = s
fitness = f
class Mutator
embed _rand: MT = MT
let _possibilities: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
let _cf: CreationFactory
new create(cf: CreationFactory) =>
_cf = cf
fun ref apply(parent: Creation, rate: F64): Creation =>
let ns = _new_string(parent.string, rate)
_cf(ns)
fun ref _new_string(parent: String, rate: F64): String =>
var mutated = recover String(parent.size()) end
for char in parent.values() do
mutated.push(_mutate_letter(char, rate))
end
consume mutated
fun ref _mutate_letter(current: U8, rate: F64): U8 =>
if _rand.real() <= rate then
_random_letter()
else
current
end
fun ref _random_letter(): U8 =>
let ln = _rand.int(_possibilities.size().u64()).usize()
try _possibilities(ln) else ' ' end
class Generation
let _size: USize
let _desired: Creation
let _mutator: Mutator
new create(size: USize = 100, desired: Creation, mutator: Mutator) =>
_size = size
_desired = desired
_mutator = consume mutator
fun ref apply(parent: Creation): Creation =>
var best = parent
let mutation_rate = _mutation_rate(best)
for i in Range(0, _size) do
let candidate = _mutator(best, mutation_rate)
if candidate.fitness > best.fitness then
best = candidate
end
end
best
fun _mutation_rate(best: Creation): F64 =>
let min_mutate_rate: F64 = 0.09
let df = _desired.fitness.f64()
let bf = best.fitness.f64()
((df - bf) / df) * (1.0 - min_mutate_rate)
actor Main
new create(env: Env) =>
let d = "METHINKS IT IS LIKE A WEASEL"
let cf = CreationFactory(d)
let desired = cf(d)
let mutator = Mutator(cf)
let start = mutator(desired, 1.0)
let spawn_per_generation = USize(100)
var iterations = U64(0)
var best = start
repeat
best = Generation(spawn_per_generation, desired, mutator)(best)
iterations = iterations + 1
if (iterations % 100) == 0 then
env.out.print(
iterations.string() + ": "
+ best.string + ", fitness: " + best.fitness.string()
)
end
until best.string == desired.string end
env.out.print(best.string + ", " + iterations.string())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment