Data update

This commit is contained in:
Ingy döt Net 2025-08-11 18:05:26 -07:00
parent 4d5544505c
commit 4924dd0264
3073 changed files with 55820 additions and 4408 deletions

View file

@ -19,17 +19,17 @@ extension evoHelper
= 0.repeatTill(self).selectBy::(x => randomChar).summarize(new StringWriter());
fitnessOf(s)
= self.zipBy(s, (a,b => a==b ? 1 : 0)).summarize(new Integer()).toInt();
= self.zipBy(s, (a,b => (a==b) ? 1 : 0)).summarize(new Integer()).toInt();
mutate(p)
= self.selectBy::(ch => rnd.nextReal() <= p ? randomChar : ch).summarize(new StringWriter());
= self.selectBy::(ch => (rnd.nextReal() <= p) ? randomChar : ch).summarize(new StringWriter());
}
class EvoAlgorithm : Enumerator
{
object _target;
object _current;
object _variantCount;
object _target;
object? _current;
object _variantCount;
constructor new(s,count)
{
@ -67,10 +67,10 @@ public program()
var attempt := new Integer();
EvoAlgorithm.new(Target,C).forEach::(current)
{
console
Console
.printPaddingLeft(10,"#",attempt.append(1))
.printLine(" ",current," fitness: ",current.fitnessOf(Target))
};
console.readChar()
Console.readChar()
}

View file

@ -1,7 +1,7 @@
(var c 100) ;number of children in each generation
(var p 0.05) ;mutation probability
(var c 100 ;number of children in each generation
p 0.05) ;mutation probability
(var target "METHINKS IT IS LIKE A WEASEL")
(var tsize (len target))
(var target "METHINKS IT IS LIKE A WEASEL"
tsize (len target))
(var alphabet (to-vec " ABCDEFGHIJLKLMNOPQRSTUVWXYZ"))

View file

@ -0,0 +1,114 @@
const std = @import("std");
const math = std.math;
const print = std.debug.print;
pub fn main() !void {
const target = "METHINKS IT IS LIKE A WEASEL";
const copies: usize = 100;
const mutation_rate: u32 = 20; // 1/20 = 0.05 = 5%
var prng = std.Random.DefaultPrng.init(@as(u64, @intCast(std.time.milliTimestamp())));
const rng = prng.random();
// Generate first sentence, mutating each character
const start = try mutate(rng, target, 1, std.heap.page_allocator); // 1/1 = 1 = 100%
print("{s}\n", .{target});
print("{s}\n", .{start});
_ = try evolve(rng, target, start, copies, mutation_rate, std.heap.page_allocator);
}
/// Evolution algorithm
///
/// Evolves `parent` to match `target`. Returns the number of evolutions performed.
fn evolve(
rng: std.Random,
target: []const u8,
parent: []const u8,
copies: usize,
mutation_rate: u32,
allocator: std.mem.Allocator,
) !usize {
var counter: usize = 0;
var parent_fitness: usize = target.len + 1;
var current_parent = try allocator.dupe(u8, parent);
defer allocator.free(current_parent);
while (true) {
counter += 1;
var best_fitness: usize = std.math.maxInt(usize);
const best_sentence = try allocator.alloc(u8, target.len);
for (0..copies) |_| {
// Copy and mutate a new sentence
const sentence = try mutate(rng, current_parent, mutation_rate, allocator);
defer allocator.free(sentence);
// Find the fitness of the new mutation
const current_fitness = fitness(target, sentence);
if (current_fitness < best_fitness) {
best_fitness = current_fitness;
@memcpy( best_sentence, sentence);
}
}
// If the best mutation of this generation is better than `parent` then "the fittest
// survives" and the next parent becomes the best of this generation.
if (best_fitness < parent_fitness) {
allocator.free(current_parent);
current_parent = best_sentence;
parent_fitness = best_fitness;
print("{s} : generation {} with fitness {}\n", .{ current_parent, counter, best_fitness });
if (best_fitness == 0) {
return counter;
}
} else {
allocator.free(best_sentence);
}
}
}
/// Computes the fitness of a sentence against a target string, returning the number of
/// incorrect characters.
fn fitness(target: []const u8, sentence: []const u8) usize {
var count: usize = 0;
for (sentence, 0..) |c, i| {
if (c != target[i]) {
count += 1;
}
}
return count;
}
/// Mutation algorithm.
///
/// It mutates each character of a string, according to a `mutation_rate`.
fn mutate(
rng: std.Random,
sentence: []const u8,
mutation_rate: u32,
allocator: std.mem.Allocator,
) ![]u8 {
var result = try allocator.alloc(u8, sentence.len);
for (sentence, 0..) |c, i| {
if (rng.int(u32) % mutation_rate == 0) {
result[i] = randomChar(rng);
} else {
result[i] = c;
}
}
return result;
}
/// Generates a random letter or space.
fn randomChar(rng: std.Random) u8 {
// Returns a value in the range [A, Z] + an extra slot for the space character.
const c = rng.intRangeAtMost(u8, 'A', 'Z' + 1);
return if (c == 'Z' + 1) ' ' else c;
}