74 lines
2.0 KiB
Pony
74 lines
2.0 KiB
Pony
use "random"
|
|
|
|
actor Main
|
|
let _env: Env
|
|
let _rand: MT = MT // Mersenne Twister
|
|
let _target: String = "METHINKS IT IS LIKE A WEASEL"
|
|
let _possibilities: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
|
|
let _c: U16 = 100 // number of spawn per generation
|
|
let _min_mutate_rate: F64 = 0.09
|
|
let _perfect_fitness: USize = _target.size()
|
|
var _parent: String = ""
|
|
|
|
new create(env: Env) =>
|
|
_env = env
|
|
_parent = mutate(_target, 1.0)
|
|
var iter: U64 = 0
|
|
while not _target.eq(_parent) do
|
|
let rate: F64 = new_mutate_rate()
|
|
iter = iter + 1
|
|
if (iter % 100) == 0 then
|
|
_env.out.write(iter.string() + ": " + _parent)
|
|
_env.out.write(", fitness: " + fitness(_parent).string())
|
|
_env.out.print(", rate: " + rate.string())
|
|
end
|
|
var best_spawn = ""
|
|
var best_fit: USize = 0
|
|
var i: U16 = 0
|
|
while i < _c do
|
|
let spawn = mutate(_parent, rate)
|
|
let spawn_fitness = fitness(spawn)
|
|
if spawn_fitness > best_fit then
|
|
best_spawn = spawn
|
|
best_fit = spawn_fitness
|
|
end
|
|
i = i + 1
|
|
end
|
|
if best_fit > fitness(_parent) then
|
|
_parent = best_spawn
|
|
end
|
|
end
|
|
_env.out.print(_parent + ", " + iter.string())
|
|
|
|
fun fitness(trial: String): USize =>
|
|
var ret_val: USize = 0
|
|
var i: USize = 0
|
|
while i < trial.size() do
|
|
try
|
|
if trial(i)? == _target(i)? then
|
|
ret_val = ret_val + 1
|
|
end
|
|
end
|
|
i = i + 1
|
|
end
|
|
ret_val
|
|
|
|
fun new_mutate_rate(): F64 =>
|
|
let perfect_fit = _perfect_fitness.f64()
|
|
((perfect_fit - fitness(_parent).f64()) / perfect_fit) * (1.0 - _min_mutate_rate)
|
|
|
|
fun ref mutate(parent: String box, rate: F64): String =>
|
|
var ret_val = recover trn String end
|
|
for char in parent.values() do
|
|
let rnd_real: F64 = _rand.real()
|
|
if rnd_real <= rate then
|
|
let rnd_int: U64 = _rand.int(_possibilities.size().u64())
|
|
try
|
|
ret_val.push(_possibilities(rnd_int.usize())?)
|
|
end
|
|
else
|
|
ret_val.push(char)
|
|
end
|
|
end
|
|
consume ret_val
|