Another update from ingydotnet^djgoku
This commit is contained in:
parent
91df62d461
commit
948b86eafa
7604 changed files with 108452 additions and 22726 deletions
|
|
@ -11,3 +11,25 @@ Starting with:
|
|||
Cf: [[wp:Weasel_program#Weasel_algorithm|Weasel algorithm]] and [[wp:Evolutionary algorithm|Evolutionary algorithm]]
|
||||
|
||||
<small>Note: to aid comparison, try and ensure the variables and functions mentioned in the task description appear in solutions</small>
|
||||
|
||||
===========
|
||||
A cursory examination of a few of the solutions reveals that the instructions have not been followed rigorously in some solutions. Specifically,
|
||||
* While the <code>parent</code> is not yet the <code>target</code>:
|
||||
:* copy the <code>parent</code> C times, each time allowing some random probability that another character might be substituted using <code>mutate</code>.
|
||||
|
||||
Note that some of the the solutions given retain characters in the mutated string that are ''correct'' in the target string. However, the instruction above does not state to retain any of the characters while performing the mutation. Although some may believe to do so is implied from the use of "converges"
|
||||
|
||||
(:* repeat until the parent converges, (hopefully), to the target.
|
||||
|
||||
Strictly speaking, the new parent should be selected from the new pool of mutations, and then the new parent used to generate the next set of mutations with parent characters getting retained only by ''not'' being mutated. It then becomes possible that the new set of mutations has no member that is fitter than the parent!
|
||||
|
||||
As illustration of this error, the code for 8th has the following remark.
|
||||
|
||||
Create a new string based on the TOS, '''changing randomly any characters which
|
||||
don't already match the target''':
|
||||
|
||||
''NOTE:'' this has been changed, the 8th version is completely random now
|
||||
|
||||
Clearly, this algo will be applying the mutation function only to the parent characters that don't match to the target characters!
|
||||
|
||||
To ensure that the new parent is never less fit than the prior parent, both the parent and all of the latest mutations are subjected to the fitness test to select the next parent.
|
||||
|
|
|
|||
62
Task/Evolutionary-algorithm/AWK/evolutionary-algorithm.awk
Normal file
62
Task/Evolutionary-algorithm/AWK/evolutionary-algorithm.awk
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#!/bin/awk -f
|
||||
function randchar(){
|
||||
return substr(charset,randint(length(charset)+1),1)
|
||||
}
|
||||
function mutate(gene,rate ,l,newgene){
|
||||
newgene = ""
|
||||
for (l=1; l < 1+length(gene); l++){
|
||||
if (rand() < rate)
|
||||
newgene = newgene randchar()
|
||||
else
|
||||
newgene = newgene substr(gene,l,1)
|
||||
}
|
||||
return newgene
|
||||
}
|
||||
function fitness(gene,target ,k,fit){
|
||||
fit = 0
|
||||
for (k=1;k<1+length(gene);k++){
|
||||
if (substr(gene,k,1) == substr(target,k,1)) fit = fit + 1
|
||||
}
|
||||
return fit
|
||||
}
|
||||
function randint(n){
|
||||
return int(n * rand())
|
||||
}
|
||||
function evolve(){
|
||||
maxfit = fitness(parent,target)
|
||||
oldfit = maxfit
|
||||
maxj = 0
|
||||
for (j=1; j < D; j++){
|
||||
child[j] = mutate(parent,mutrate)
|
||||
fit[j] = fitness(child[j],target)
|
||||
if (fit[j] > maxfit) {
|
||||
maxfit = fit[j]
|
||||
maxj = j
|
||||
}
|
||||
}
|
||||
if (maxfit > oldfit) parent = child[maxj]
|
||||
}
|
||||
|
||||
BEGIN{
|
||||
target = "METHINKS IT IS LIKE A WEASEL"
|
||||
charset = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
mutrate = 0.10
|
||||
if (ARGC > 1) mutrate = ARGV[1]
|
||||
lenset = length(charset)
|
||||
C = 100
|
||||
D = C + 1
|
||||
parent = ""
|
||||
for (j=1; j < length(target)+1; j++) {
|
||||
parent = parent randchar()
|
||||
}
|
||||
print "target: " target
|
||||
print "fitness of target: " fitness(target,target)
|
||||
print "initial parent: " parent
|
||||
gens = 0
|
||||
while (parent != target){
|
||||
evolve()
|
||||
gens = gens + 1
|
||||
if (gens % 10 == 0) print "after " gens " generations,","new parent: " parent," with fitness: " fitness(parent,target)
|
||||
}
|
||||
print "after " gens " generations,"," evolved parent: " parent
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
|
||||
std::string allowed_chars = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ dchar rnd() { return (uppercase ~ " ")[uniform(0, $)]; }
|
|||
enum mut = (dchar[] s) => s.map!(a => uniform01 < P ? rnd : a).array;
|
||||
|
||||
void main() {
|
||||
auto parent = target.length.iota.map!(_ => rnd).array;
|
||||
auto parent = generate!rnd.take(target.length).array;
|
||||
for (auto gen = 1; parent != target; gen++) {
|
||||
// parent = parent.repeat(C).map!mut.array.max!fitness;
|
||||
parent = parent.repeat(C).map!mut.array
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
defmodule Rand do
|
||||
def init do # Initialize the random values.
|
||||
<< a :: 32, b :: 32, c :: 32 >> = :crypto.strong_rand_bytes(12)
|
||||
:random.seed(a,b,c)
|
||||
end
|
||||
|
||||
def num do # Returns a value between 0.0 and 1.0.
|
||||
init
|
||||
:random.uniform
|
||||
end
|
||||
|
||||
def char(list) do # Returns a random letter or a space.
|
||||
Enum.at(list, :random.uniform(length(list)) - 1)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
defmodule Log do
|
||||
def show(offspring,i) do
|
||||
IO.puts "Generation: #{i}, Offspring: #{offspring}"
|
||||
end
|
||||
|
||||
def found([target|i]) do
|
||||
IO.puts "#{target} found in #{i} iterations"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
defmodule Evolution do
|
||||
def select(target) do
|
||||
# Generate char list from A to Z; 32 is the ord value for space.
|
||||
chars = (?A..?Z) |> Enum.to_list() |> List.insert_at(0, 32)
|
||||
|
||||
(1..String.length(target)) # Creates parent for generation 0.
|
||||
|> Enum.map(fn _-> Rand.char(chars) end)
|
||||
|> mutate(String.to_char_list(target),0,[],chars)
|
||||
|> Log.found()
|
||||
end
|
||||
|
||||
# w is used to denote fitness in population genetics.
|
||||
|
||||
def mutate(parent,target,i,_,_) when target == parent, do: [parent|i]
|
||||
def mutate(parent,target,i,_,chars) when target != parent do
|
||||
w = fitness(parent,target)
|
||||
prev = reproduce(target,parent,w,0,mu_rate(w),chars)
|
||||
|
||||
# Check if the most fit member of the new gen has a greater fitness than the parent.
|
||||
if w < fitness(prev,target) do
|
||||
parent = prev
|
||||
Log.show(parent,i)
|
||||
end
|
||||
mutate(parent,target,i+1,prev,chars)
|
||||
end
|
||||
|
||||
# Generate 100 offspring and select the one with the greatest fitness.
|
||||
|
||||
def reproduce(target,parent,_,_,rate,chars) do
|
||||
(1..100)
|
||||
|> Enum.to_list()
|
||||
|> Stream.map(fn _-> mutation(parent,rate,chars) end)
|
||||
|> List.insert_at(0, parent)
|
||||
|> Enum.max_by(fn n -> fitness(n,target) end)
|
||||
end
|
||||
|
||||
# Calculate fitness by checking difference between parent and offspring chars.
|
||||
|
||||
def fitness(t,r) do
|
||||
(0..length(t)-1)
|
||||
|> Stream.map(fn n -> abs(Enum.at(t,n) - Enum.at(r,n)) end)
|
||||
|> Enum.reduce(fn a,b -> a + b end)
|
||||
|> calc()
|
||||
end
|
||||
|
||||
# Generate offspring based on parent.
|
||||
|
||||
def mutation(p,r,chars) do
|
||||
# Copy the parent chars, then check each val against the random mutation rate
|
||||
(0..length(p)-1)
|
||||
|> Stream.map(fn n -> Enum.at(p,n) end)
|
||||
|> Enum.map(fn n -> if Rand.num <= r, do: Rand.char(chars), else: n end)
|
||||
end
|
||||
|
||||
def calc(sum), do: 100 * :math.exp(sum/-10)
|
||||
def mu_rate(n), do: 1 - :math.exp(-(100-n)/400)
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
Evolution.select("METHINKS IT IS LIKE A WEASEL")
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
function evolve(parent,target,mutation_rate,num_children)
|
||||
println("Initial parent is $parent, its fitness is $(fitness(parent,target))")
|
||||
gens=0
|
||||
while parent!=target
|
||||
children=[mutate(parent,mutation_rate) for i=1:num_children]
|
||||
bestfit,best=findmax(map(child->fitness(child,target),children))
|
||||
parent=children[best]
|
||||
gens+=1
|
||||
if gens%10==0
|
||||
println("After $gens generations, the new parent is $parent and its fitness is $(fitness(parent,target))")
|
||||
end
|
||||
end
|
||||
println("After $gens generations, the parent evolved into the target $target")
|
||||
end
|
||||
|
||||
fitness(s1,s2)=count(x->x,convert(Array{Char,1},s1).==convert(Array{Char,1},s2))
|
||||
|
||||
function mutate(s,rate)
|
||||
new_s=""
|
||||
for c in s
|
||||
new_s*=string(rand()<rate?
|
||||
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"[rand(1:27)]:c)
|
||||
end
|
||||
return new_s
|
||||
end
|
||||
|
||||
evolve("IU RFSGJABGOLYWF XSMFXNIABKT","METHINKS IT IS LIKE A WEASEL",0.08998,100)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Initial parent is IU RFSGJABGOLYWF XSMFXNIABKT, its fitness is 1
|
||||
After 10 generations, the new parent is M TBINGJ IGOYSYV KIAM WIAXEL and its fitness is 13
|
||||
After 20 generations, the new parent is MRTBINKJ IT SYO KT Z WEAIEL and its fitness is 18
|
||||
After 30 generations, the new parent is MGTHINKJ IT ISYLMKJ A WEASEL and its fitness is 23
|
||||
After 40 generations, the new parent is MBTHINKS IT ISYLIKE A WEASEL and its fitness is 26
|
||||
After 49 generations, the parent evolved into the target METHINKS IT IS LIKE A WEASEL
|
||||
110
Task/Evolutionary-algorithm/MATLAB/evolutionary-algorithm-3.m
Normal file
110
Task/Evolutionary-algorithm/MATLAB/evolutionary-algorithm-3.m
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
%% Genetic Algorithm -- Solves For A User Input String
|
||||
|
||||
% #### PLEASE NOTE: you can change the selection and crossover type in the
|
||||
% parameters and see how the algorithm changes. ####
|
||||
|
||||
clear;close all;clc; %Clears variables, closes windows, and clears the command window
|
||||
tic % Begins the timer
|
||||
|
||||
%% Select Target String
|
||||
target = 'METHINKS IT IS LIKE A WEASEL';
|
||||
% *Can Be Any String With Any Values and Any Length!*
|
||||
% but for this example we use 'METHINKS IT IS LIKE A WEASEL'
|
||||
|
||||
%% Parameters
|
||||
popSize = 1000; % Population Size (100-10000 generally produce good results)
|
||||
genome = length(target); % Genome Size
|
||||
mutRate = .01; % Mutation Rate (5%-25% produce good results)
|
||||
S = 4; % Tournament Size (2-6 produce good results)
|
||||
best = Inf; % Initialize Best (arbitrarily large)
|
||||
MaxVal = max(double(target)); % Max Integer Value Needed
|
||||
ideal = double(target); % Convert Target to Integers
|
||||
|
||||
selection = 0; % 0: Tournament
|
||||
% 1: 50% Truncation
|
||||
|
||||
crossover = 1; % 0: Uniform crossover
|
||||
% 1: 1 point crossover
|
||||
% 2: 2 point crossover
|
||||
%% Initialize Population
|
||||
Pop = round(rand(popSize,genome)*(MaxVal-1)+1); % Creates Population With Corrected Genome Length
|
||||
|
||||
for Gen = 1:1e6 % A Very Large Number Was Chosen, But Shouldn't Be Needed
|
||||
|
||||
%% Fitness
|
||||
|
||||
% The fitness function starts by converting the characters into integers and then
|
||||
% subtracting each element of each member of the population from each element of
|
||||
% the target string. The function then takes the absolute value of
|
||||
% the differences and sums each row and stores the function as a mx1 matrix.
|
||||
|
||||
F = sum(abs(bsxfun(@minus,Pop,ideal)),2);
|
||||
|
||||
|
||||
|
||||
% Finding Best Members for Score Keeping and Printing Reasons
|
||||
[current,currentGenome] = min(F); % current is the minimum value of the fitness array F
|
||||
% currentGenome is the index of that value in the F array
|
||||
|
||||
% Stores New Best Values and Prints New Best Scores
|
||||
if current < best
|
||||
best = current;
|
||||
bestGenome = Pop(currentGenome,:); % Uses that index to find best value
|
||||
|
||||
fprintf('Gen: %d | Fitness: %d | ',Gen, best); % Formatted printing of generation and fitness
|
||||
disp(char(bestGenome)); % Best genome so far
|
||||
elseif best == 0
|
||||
break % Stops program when we are done
|
||||
end
|
||||
|
||||
%% Selection
|
||||
|
||||
% TOURNAMENT
|
||||
if selection == 0
|
||||
T = round(rand(2*popSize,S)*(popSize-1)+1); % Tournaments
|
||||
[~,idx] = min(F(T),[],2); % Index to Determine Winners
|
||||
W = T(sub2ind(size(T),(1:2*popSize)',idx)); % Winners
|
||||
|
||||
% 50% TRUNCATION
|
||||
elseif selection == 1
|
||||
[~,V] = sort(F,'descend'); % Sort Fitness in Ascending Order
|
||||
V = V(popSize/2+1:end); % Winner Pool
|
||||
W = V(round(rand(2*popSize,1)*(popSize/2-1)+1))'; % Winners
|
||||
end
|
||||
|
||||
%% Crossover
|
||||
|
||||
% UNIFORM CROSSOVER
|
||||
if crossover == 0
|
||||
idx = logical(round(rand(size(Pop)))); % Index of Genome from Winner 2
|
||||
Pop2 = Pop(W(1:2:end),:); % Set Pop2 = Pop Winners 1
|
||||
P2A = Pop(W(2:2:end),:); % Assemble Pop2 Winners 2
|
||||
Pop2(idx) = P2A(idx); % Combine Winners 1 and 2
|
||||
|
||||
% 1-POINT CROSSOVER
|
||||
elseif crossover == 1
|
||||
Pop2 = Pop(W(1:2:end),:); % New Population From Pop 1 Winners
|
||||
P2A = Pop(W(2:2:end),:); % Assemble the New Population
|
||||
Ref = ones(popSize,1)*(1:genome); % The Reference Matrix
|
||||
idx = (round(rand(popSize,1)*(genome-1)+1)*ones(1,genome))>Ref; % Logical Indexing
|
||||
Pop2(idx) = P2A(idx); % Recombine Both Parts of Winners
|
||||
|
||||
% 2-POINT CROSSOVER
|
||||
elseif crossover == 2
|
||||
Pop2 = Pop(W(1:2:end),:); % New Pop is Winners of old Pop
|
||||
P2A = Pop(W(2:2:end),:); % Assemble Pop2 Winners 2
|
||||
Ref = ones(popSize,1)*(1:genome); % Ones Matrix
|
||||
CP = sort(round(rand(popSize,2)*(genome-1)+1),2); % Crossover Points
|
||||
idx = CP(:,1)*ones(1,genome)<Ref&CP(:,2)*ones(1,genome)>Ref; % Index
|
||||
Pop2(idx)=P2A(idx); % Recombine Winners
|
||||
end
|
||||
%% Mutation
|
||||
idx = rand(size(Pop2))<mutRate; % Index of Mutations
|
||||
Pop2(idx) = round(rand([1,sum(sum(idx))])*(MaxVal-1)+1); % Mutated Value
|
||||
|
||||
%% Reset Poplulations
|
||||
Pop = Pop2;
|
||||
|
||||
end
|
||||
|
||||
toc % Ends timer and prints elapsed time
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
Gen: 1 | Fitness: 465 | C<EFBFBD>I1%G+<%?R<EFBFBD>8>9<EFBFBD>JU#(E<EFBFBD>UO<EFBFBD>PHI
|
||||
Gen: 2 | Fitness: 429 | W=P6>D<EFBFBD>I)VU6$T 99,<EFBFBD> B<EFBFBD>BMP0JH
|
||||
Gen: 3 | Fitness: 366 | P<EFBFBD>;R08AS<EFBFBD>GJ<EFBFBD>IS&T38IE<EFBFBD>)SJERLJ
|
||||
Gen: 4 | Fitness: 322 | KI8M5LAS<EFBFBD>GJ<EFBFBD>IS<EFBFBD>SP<EFBFBD>@)D<EFBFBD>V@
|
||||
JCP
|
||||
Gen: 5 | Fitness: 295 | UAUR08AS<EFBFBD>GJ<EFBFBD>IS<EFBFBD>8HG*<EFBFBD>+<EFBFBD>=C?UB(
|
||||
Gen: 6 | Fitness: 259 | VCUQH35S<EFBFBD>HR4.L<EFBFBD>ISJQ%J<EFBFBD>OC*T=E
|
||||
Gen: 7 | Fitness: 226 | LFB8GPET(LODKQ<EFBFBD>KQ<K E*PEMA6I
|
||||
Gen: 8 | Fitness: 192 | EPKOLCIR<EFBFBD>QQ<EFBFBD>NF<EFBFBD>QG:B(D/U>BQGF
|
||||
Gen: 9 | Fitness: 159 | N8R7?SOU<EFBFBD>NO$OK O?K?!;<EFBFBD>MB?QHG
|
||||
Gen: 10 | Fitness: 146 | TGN@EQR4)PS%IS#TFJQ%A!U>BVLI
|
||||
Gen: 11 | Fitness: 120 | L?VMALJS%?R EK IILE<EFBFBD>6'RRERLJ
|
||||
Gen: 12 | Fitness: 102 | R@T9COMR<EFBFBD>NU CS*R?K?!; VD>LCL
|
||||
Gen: 13 | Fitness: 96 | NENMVOMR<EFBFBD>NU CS*R?K?!; VD>LCL
|
||||
Gen: 14 | Fitness: 82 | REJGNPMU<EFBFBD>KR CS JKI@+D<EFBFBD>UD?QHG
|
||||
Gen: 15 | Fitness: 75 | NETI=HPQ<EFBFBD>FT ID EFKE D"WD>QDQ
|
||||
Gen: 16 | Fitness: 70 | R@TKCOOT)@R$IS KKLE<EFBFBD>D"WC?UBJ
|
||||
Gen: 17 | Fitness: 61 | NESIKQRP<EFBFBD>NU CS<EFBFBD>MFKE ; SEETCP
|
||||
Gen: 18 | Fitness: 57 | LFSGLPTN<EFBFBD>NU GQ IIKE D"VD>LCL
|
||||
Gen: 19 | Fitness: 40 | NENKJLMS<EFBFBD>GS%IS#MFKE B UFATCL
|
||||
Gen: 21 | Fitness: 39 | NETIGPEU<EFBFBD>KR IS IIKD"? UFDQEK
|
||||
Gen: 22 | Fitness: 33 | NETGCOMT<EFBFBD>LU IS#MFKE B UFATCL
|
||||
Gen: 23 | Fitness: 32 | NETIKNPQ<EFBFBD>NU IS#IIKE B UFATCL
|
||||
Gen: 24 | Fitness: 27 | NETKJLMS<EFBFBD>LU IS MFKE B UFATCL
|
||||
Gen: 25 | Fitness: 23 | LETIKOMS LU IS IIKE D WEDQEK
|
||||
Gen: 26 | Fitness: 22 | NETIKMJS LU IS IIKE D WEDQEK
|
||||
Gen: 27 | Fitness: 20 | LETIKOMS LU IS KILE B"WFATCL
|
||||
Gen: 28 | Fitness: 19 | NESGJQJS<EFBFBD>GU IS KIKE B WFATEK
|
||||
Gen: 29 | Fitness: 16 | NETIHPMS KR IS KIKE B WFATEK
|
||||
Gen: 30 | Fitness: 15 | NESHLPKS KU IS KIKE B WFATEK
|
||||
Gen: 31 | Fitness: 13 | NETGGNKS KU IS KIKE C WFATEK
|
||||
Gen: 32 | Fitness: 12 | NETHGNJS IU IS JIKE B WFATCL
|
||||
Gen: 33 | Fitness: 11 | NETIJPKS IU IS KIKE B WFATEK
|
||||
Gen: 35 | Fitness: 8 | LEUIHNJS IT IS JIKE A WEATEL
|
||||
Gen: 37 | Fitness: 7 | NETIHNJS IS IS LIKE B WFASEL
|
||||
Gen: 38 | Fitness: 6 | NETHGNJS IT IS LIKE A WFASEK
|
||||
Gen: 39 | Fitness: 4 | METGHNKS IT IS LIKE B WEATEL
|
||||
Gen: 42 | Fitness: 3 | NETHINKS IT IS KIKE B WEASEL
|
||||
Gen: 43 | Fitness: 2 | NETHINKS IT IS LIKE A WFASEL
|
||||
Gen: 44 | Fitness: 1 | METHHNKS IT IS LIKE A WEASEL
|
||||
Gen: 46 | Fitness: 0 | METHINKS IT IS LIKE A WEASEL
|
||||
Elapsed time is 0.099618 seconds.
|
||||
108
Task/Evolutionary-algorithm/Pascal/evolutionary-algorithm.pascal
Normal file
108
Task/Evolutionary-algorithm/Pascal/evolutionary-algorithm.pascal
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
PROGRAM EVOLUTION (OUTPUT);
|
||||
|
||||
CONST
|
||||
TARGET = 'METHINKS IT IS LIKE A WEASEL';
|
||||
COPIES = 100; (* 100 children in each generation. *)
|
||||
RATE = 1000; (* About one character in 1000 will be a mutation. *)
|
||||
|
||||
TYPE
|
||||
STRLIST = ARRAY [1..COPIES] OF STRING;
|
||||
|
||||
FUNCTION RANDCHAR : CHAR;
|
||||
(* Generate a random letter or space. *)
|
||||
VAR RANDNUM : INTEGER;
|
||||
BEGIN
|
||||
RANDNUM := RANDOM(27);
|
||||
IF RANDNUM = 26 THEN
|
||||
RANDCHAR := ' '
|
||||
ELSE
|
||||
RANDCHAR := CHR(RANDNUM + ORD('A'))
|
||||
END;
|
||||
|
||||
FUNCTION RANDSTR (SIZE : INTEGER) : STRING;
|
||||
(* Generate a random string. *)
|
||||
VAR
|
||||
N : INTEGER;
|
||||
S : STRING;
|
||||
BEGIN
|
||||
S := '';
|
||||
FOR N := 1 TO SIZE DO
|
||||
INSERT(RANDCHAR, S, 1);
|
||||
RANDSTR := S
|
||||
END;
|
||||
|
||||
FUNCTION FITNESS (CANDIDATE, GOAL : STRING) : INTEGER;
|
||||
(* Count the number of correct letters in the correct places *)
|
||||
VAR N, MATCHES : INTEGER;
|
||||
BEGIN
|
||||
MATCHES := 0;
|
||||
FOR N := 1 TO LENGTH(GOAL) DO
|
||||
IF CANDIDATE[N] = GOAL[N] THEN
|
||||
MATCHES := MATCHES + 1;
|
||||
FITNESS := MATCHES
|
||||
END;
|
||||
|
||||
FUNCTION MUTATE (RATE : INTEGER; S : STRING) : STRING;
|
||||
(* Randomly alter a string. Characters change with probability 1/RATE. *)
|
||||
VAR
|
||||
N : INTEGER;
|
||||
CHANGE : BOOLEAN;
|
||||
BEGIN
|
||||
FOR N := 1 TO LENGTH(TARGET) DO
|
||||
BEGIN
|
||||
CHANGE := RANDOM(RATE) = 0;
|
||||
IF CHANGE THEN
|
||||
S[N] := RANDCHAR
|
||||
END;
|
||||
MUTATE := S
|
||||
END;
|
||||
|
||||
PROCEDURE REPRODUCE (RATE : INTEGER; PARENT : STRING; VAR CHILDREN : STRLIST);
|
||||
(* Generate children with random mutations. *)
|
||||
VAR N : INTEGER;
|
||||
BEGIN
|
||||
FOR N := 1 TO COPIES DO
|
||||
CHILDREN[N] := MUTATE(RATE, PARENT)
|
||||
END;
|
||||
|
||||
FUNCTION FITTEST(CHILDREN : STRLIST; GOAL : STRING) : STRING;
|
||||
(* Measure the fitness of each child and return the fittest. *)
|
||||
(* If multiple children equally match the target, then return the first. *)
|
||||
VAR
|
||||
MATCHES, MOST_MATCHES, BEST_INDEX, N : INTEGER;
|
||||
BEGIN
|
||||
MOST_MATCHES := 0;
|
||||
BEST_INDEX := 1;
|
||||
FOR N := 1 TO COPIES DO
|
||||
BEGIN
|
||||
MATCHES := FITNESS(CHILDREN[N], GOAL);
|
||||
IF MATCHES > MOST_MATCHES THEN
|
||||
BEGIN
|
||||
MOST_MATCHES := MATCHES;
|
||||
BEST_INDEX := N
|
||||
END
|
||||
END;
|
||||
FITTEST := CHILDREN[BEST_INDEX]
|
||||
END;
|
||||
|
||||
VAR
|
||||
PARENT, BEST_CHILD : STRING;
|
||||
CHILDREN : STRLIST;
|
||||
GENERATIONS : INTEGER;
|
||||
|
||||
BEGIN
|
||||
RANDOMIZE;
|
||||
GENERATIONS := 0;
|
||||
PARENT := RANDSTR(LENGTH(TARGET));
|
||||
WHILE NOT (PARENT = TARGET) DO
|
||||
BEGIN
|
||||
IF (GENERATIONS MOD 100) = 0 THEN WRITELN(PARENT);
|
||||
GENERATIONS := GENERATIONS + 1;
|
||||
REPRODUCE(RATE, PARENT, CHILDREN);
|
||||
BEST_CHILD := FITTEST(CHILDREN, TARGET);
|
||||
IF FITNESS(PARENT, TARGET) < FITNESS(BEST_CHILD, TARGET) THEN
|
||||
PARENT := BEST_CHILD
|
||||
END;
|
||||
WRITE('The string was matched in ');
|
||||
WRITELN(GENERATIONS, ' generations.')
|
||||
END.
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
constant target = "METHINKS IT IS LIKE A WEASEL";
|
||||
constant mutate_chance = .08;
|
||||
constant alphabet = 'A'..'Z',' ';
|
||||
constant @alphabet = flat 'A'..'Z',' ';
|
||||
constant C = 100;
|
||||
|
||||
sub mutate { $^string.comb.map({ rand < mutate_chance ?? alphabet.pick !! $_ }).join }
|
||||
sub mutate { $^string.subst(/./, { rand < mutate_chance ?? @alphabet.pick !! $/ }, :g) }
|
||||
sub fitness { [+] $^string.comb Zeq state @ = target.comb }
|
||||
|
||||
loop (
|
||||
my $parent = alphabet.roll(target.chars).join;
|
||||
my $parent = @alphabet.roll(target.chars).join;
|
||||
$parent ne target;
|
||||
$parent = max :by(&fitness), mutate($parent) xx C
|
||||
) { printf "%6d: '%s'\n", $++, $parent }
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
from string import ascii_uppercase
|
||||
from string import letters
|
||||
from random import choice, random
|
||||
|
||||
target = list("METHINKS IT IS LIKE A WEASEL")
|
||||
charset = ascii_uppercase + ' '
|
||||
charset = letters + ' '
|
||||
parent = [choice(charset) for _ in range(len(target))]
|
||||
minmutaterate = .09
|
||||
C = range(100)
|
||||
|
||||
perfectfitness = float(len(target))
|
||||
|
||||
def fitness(trial):
|
||||
'Sum of matching chars by position'
|
||||
return sum(t==h for t,h in zip(trial, target))
|
||||
|
|
@ -24,12 +25,23 @@ def que():
|
|||
print ("#%-4i, fitness: %4.1f%%, '%s'" %
|
||||
(iterations, fitness(parent)*100./perfectfitness, ''.join(parent)))
|
||||
|
||||
def mate(a, b):
|
||||
place = 0
|
||||
if choice(xrange(10)) < 7:
|
||||
place = choice(xrange(len(target)))
|
||||
else:
|
||||
return a, b
|
||||
|
||||
return a, b, a[:place] + b[place:], b[:place] + a[place:]
|
||||
|
||||
iterations = 0
|
||||
center = len(C)/2
|
||||
while parent != target:
|
||||
rate = mutaterate()
|
||||
rate = mutaterate()
|
||||
iterations += 1
|
||||
if iterations % 100 == 0: que()
|
||||
copies = [ mutate(parent, rate) for _ in C ] + [parent]
|
||||
parent = max(copies, key=fitness)
|
||||
print ()
|
||||
parent1 = max(copies[:center], key=fitness)
|
||||
parent2 = max(copies[center:], key=fitness)
|
||||
parent = max(mate(parent1, parent2), key=fitness)
|
||||
que()
|
||||
|
|
|
|||
|
|
@ -1,35 +1,34 @@
|
|||
/*REXX program demonstrates an evolutionary algorithm (using mutation).*/
|
||||
parse arg children MR seed . /*get options (maybe) from C.L. */
|
||||
if children=='' then children = 10 /*# of children produced each gen*/
|
||||
if MR =='' then MR = '4%' /*the char Mutation Rate each gen*/
|
||||
if right(MR,1)=='%' then MR=strip(MR,,'%')/100 /*expressed as %? Adjust*/
|
||||
if seed\=='' then call random ,,seed /*allow the runs to be repeatable*/
|
||||
abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' ; Labc=length(abc)
|
||||
target= 'METHINKS IT IS LIKE A WEASEL' ; Ltar=length(target)
|
||||
parent= mutate( left('',Ltar), 1) /*gen rand str,same length as tar*/
|
||||
say center('target string',Ltar,'─') "children" 'mutationRate'
|
||||
say target center(children,8) center((MR*100/1)'%',12) ; say
|
||||
say center('new string',Ltar,'─') "closeness" 'generation'
|
||||
/*REXX program demonstrates an evolutionary algorithm (by using mutation). */
|
||||
parse arg children MR seed . /*get optional arguments from the C.L. */
|
||||
if children=='' then children = 10 /*# children produced each generation. */
|
||||
if MR =='' then MR = '4%' /*the character Mutation Rate each gen.*/
|
||||
if right(MR,1)=='%' then MR=strip(MR,,'%')/100 /*expressed as %? Then adjust*/
|
||||
if seed\=='' then call random ,,seed /*SEED allow the runs to be repeatable.*/
|
||||
abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' ; Labc=length(abc)
|
||||
target= 'METHINKS IT IS LIKE A WEASEL' ; Ltar=length(target)
|
||||
parent= mutate( left('',Ltar), 1) /*gen rand string,same length as target*/
|
||||
say center('target string',Ltar,'─') "children" 'mutationRate'
|
||||
say target center(children,8) center((MR*100/1)'%',12); say
|
||||
say center('new string',Ltar,'─') "closeness" 'generation'
|
||||
|
||||
do gen=0 until parent==target; close=fitness(parent)
|
||||
do gen=0 until parent==target; close=fitness(parent)
|
||||
almost=parent
|
||||
do children; child=mutate(parent,MR)
|
||||
_=fitness(child); if _<=close then iterate
|
||||
close=_; almost=child
|
||||
say almost right(close,9) right(gen,10)
|
||||
do children; child=mutate(parent,MR)
|
||||
_=fitness(child); if _<=close then iterate
|
||||
close=_; almost=child
|
||||
say almost right(close,9) right(gen,10)
|
||||
end /*children*/
|
||||
parent=almost
|
||||
end /*gen*/
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*───────────────────────────────────FITNESS subroutine─────────────────*/
|
||||
fitness: parse arg x; hit=0; do k=1 for Ltar
|
||||
hit=hit+(substr(x,k,1)==substr(target,k,1))
|
||||
end /*k*/
|
||||
return hit
|
||||
/*───────────────────────────────────MUTATE subroutine──────────────────*/
|
||||
mutate: parse arg x,rate,? /*set ? to a null, x=string. */
|
||||
do j=1 for Ltar; r=random(1,100000)
|
||||
if .00001*r<=rate then ?=? || substr(abc,r//Labc+1,1)
|
||||
else ?=? || substr(x,j,1)
|
||||
end /*j*/
|
||||
return ?
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
fitness: parse arg x; $=0
|
||||
do k=1 for Ltar; $=$+(substr(x,k,1)==substr(target,k,1)); end /*k*/
|
||||
return $
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
mutate: parse arg x,rate $ /*set X to 1st argument, RATE to 2nd.*/
|
||||
$=; do j=1 for Ltar; r=random(1,100000) /*REXX's max.*/
|
||||
if .00001*r<=rate then $=$ || substr(abc,r//Labc+1,1)
|
||||
else $=$ || substr(x,j,1)
|
||||
end /*j*/
|
||||
return $
|
||||
|
|
|
|||
|
|
@ -1,45 +1,43 @@
|
|||
/*REXX program demonstrates an evolutionary algorithm (using mutation).*/
|
||||
parse arg children MR seed . /*get options (maybe) from C.L. */
|
||||
if children=='' then children = 10 /*# of children produced each gen*/
|
||||
if MR =='' then MR = "4%" /*the char Mutation Rate each gen*/
|
||||
if right(MR,1)=='%' then MR=strip(MR,,"%")/100 /*expressed as %? Adjust*/
|
||||
if seed\=='' then call random ,,seed /*allow the runs to be repeatable*/
|
||||
abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' ; Labc=length(abc)
|
||||
/*REXX program demonstrates an evolutionary algorithm (by using mutation). */
|
||||
parse arg children MR seed . /*get optional arguments from the C.L. */
|
||||
if children=='' then children = 10 /*# children produced each generation. */
|
||||
if MR =='' then MR = '4%' /*the character Mutation Rate each gen.*/
|
||||
if right(MR,1)=='%' then MR=strip(MR,,'%')/100 /*expressed as %? Then adjust*/
|
||||
if seed\=='' then call random ,,seed /*SEED allow the runs to be repeatable.*/
|
||||
abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '; Labc=length(abc)
|
||||
|
||||
do i=0 for Labc /*define array (faster compare), */
|
||||
A.i=substr(abc, i+1, 1) /* it's better than picking out a*/
|
||||
end /*i*/ /* byte from a character string. */
|
||||
do i=0 for Labc /*define array (for faster compare), */
|
||||
@.i=substr(abc,i+1,1) /* it's better than picking out a */
|
||||
end /*i*/ /* byte from a character string. */
|
||||
|
||||
target= 'METHINKS IT IS LIKE A WEASEL' ; Ltar=length(target)
|
||||
|
||||
do i=1 for Ltar /*define array (faster compare), */
|
||||
T.i=substr(target, i, 1) /*it's better than a byte-by-byte*/
|
||||
end /*i*/ /*compare using character strings*/
|
||||
do i=1 for Ltar /*define an array (for faster compare),*/
|
||||
T.i=substr(target,i,1) /* it's better than a byte-by-byte */
|
||||
end /*i*/ /* compare using character strings.*/
|
||||
|
||||
parent= mutate( left('', Ltar), 1) /*gen rand str,same length as tar*/
|
||||
say center('target string', Ltar, '─') "children" 'mutationRate'
|
||||
say target center(children, 8) center((MR*100/1)'%', 12) ; say
|
||||
say center('new string', Ltar, '─') "closeness" 'generation'
|
||||
parent= mutate( left('',Ltar), 1) /*gen rand string, same length as tar. */
|
||||
say center('target string',Ltar,'─') "children" 'mutationRate'
|
||||
say target center(children,8) center((MR*100/1)'%',12); say
|
||||
say center('new string',Ltar,'─') "closeness" 'generation'
|
||||
|
||||
do gen=0 until parent==target; close=fitness(parent)
|
||||
do gen=0 until parent==target; close=fitness(parent)
|
||||
almost=parent
|
||||
do children; child=mutate(parent, MR)
|
||||
_=fitness(child); if _<=close then iterate
|
||||
close=_; almost=child
|
||||
say almost right(close, 9) right(gen, 10)
|
||||
do children; child=mutate(parent,MR)
|
||||
_=fitness(child); if _<=close then iterate
|
||||
close=_; almost=child
|
||||
say almost right(close,9) right(gen,10)
|
||||
end /*children*/
|
||||
parent=almost
|
||||
end /*gen*/
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*───────────────────────────────────FITNESS subroutine─────────────────*/
|
||||
fitness: parse arg x; hit=0; do k=1 for Ltar
|
||||
hit=hit + (substr(x,k,1) == T.k)
|
||||
end /*k*/
|
||||
return hit
|
||||
/*───────────────────────────────────MUTATE subroutine──────────────────*/
|
||||
mutate: parse arg x,rate,? /*set ? to a null, x=string. */
|
||||
do j=1 for Ltar; r=random(1, 100000)
|
||||
if .00001*r<=rate then do; _=r//Labc; ?=? || A._; end
|
||||
else ?=? || substr(x,j,1)
|
||||
end /*j*/
|
||||
return ?
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
fitness: parse arg x; $=0; do k=1 for Ltar; $=$+(substr(x,k,1)==T.k); end
|
||||
return $
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
mutate: parse arg x,rate /*set X to 1st argument, RATE to 2nd.*/
|
||||
$=; do j=1 for Ltar; r=random(1,100000) /*REXX's max.*/
|
||||
if .00001*r<=rate then do; _=r//Labc; $=$ || @._; end
|
||||
else $=$ || substr(x,j,1)
|
||||
end /*j*/
|
||||
return $
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue