Evolutionary algorithm: Difference between revisions

Added Easylang
m (BBC BASIC moved to the BASIC section.)
(Added Easylang)
 
(18 intermediate revisions by 11 users not shown)
Line 685:
380: METHINKS ITBIS LIKE A WEASEL, fitness: 27
Final ( 384): METHINKS IT IS LIKE A WEASEL, fitness: 28</pre>
 
=={{header|ABC}}==
<syntaxhighlight lang="ABC">PUT "ABCDEFGHIJKLMNOPQRSTUVWXYZ " IN alphabet
 
HOW TO RETURN initial.state target:
SHARE alphabet
PUT "" IN state
FOR c IN target: PUT state^choice alphabet IN state
RETURN state
 
HOW TO RETURN state fitness target:
PUT #target IN score
FOR i IN {1..#target}:
IF state item i = target item i: PUT score-1 IN score
RETURN score
 
HOW TO RETURN chance mutate state:
SHARE alphabet
PUT "" IN mutated
FOR i IN {1..#state}:
SELECT:
random < chance: PUT choice alphabet IN next
ELSE: PUT state item i IN next
PUT mutated^next IN mutated
RETURN mutated
 
HOW TO EVOLVE TOWARD target:
PUT 0.1 IN mutation.rate
PUT 100 IN generation.size
PUT initial.state target IN state
WHILE state fitness target > 0:
WRITE (state fitness target)>>2, ": ", state/
PUT {} IN next.generation
FOR i IN {1..generation.size}:
PUT mutation.rate mutate state IN child
PUT child fitness target IN score
PUT child IN next.generation[score]
PUT next.generation[min keys next.generation] IN state
WRITE (state fitness target)>>2, ": ", state/
 
EVOLVE TOWARD "METHINKS IT IS LIKE A WEASEL"</syntaxhighlight>
{{out}}
<pre>27: CYPPYRQHMACPLQIZLPETRJVVPYLI
26: CYPPYRQHMICPLQIZLPEDRJVVPILI
25: CYKPYRQH ICPLWIZLPEDRJVJPILI
24: CWKPWWQH ICPLSIZLPEDRJVJPILI
23: CWKPWWQH ICPLSIZLPEDR BJPILI
21: CWKPWWQH ICPLSIZLSEDA BJA LI
20: JWKPWWKH ICPLSIZLSEDA BJA LK
19: WWKPIWKG ICPLSIZLSEDA BJA LK
18: WWKPIWKG ICPLSILLSEDA BJA LK
17: WWKPIWKG ICPLSILISEDA BJA LK
17: IWMPIWKG ICPLSILISEDA BJA LK
16: IWMPIWKG ICPLSILISEDA WJA LK
15: IWMPIWKG ICPLSILISEDA WEA LK
...
1: METHINKS IT IS LIKE A WEAS L
1: METHINKS IT IS LIKE A WEAS L
1: METHINKS IT IS LIKE A WEAS L
0: METHINKS IT IS LIKE A WEASEL</pre>
 
=={{header|Aime}}==
Line 788 ⟶ 848:
 
=={{header|ALGOL 68}}==
{{trans|C|but using a fixed mutation rate}} Note: This specimen retains the original [[#C|C]] coding style.
{{works with|ALGOL 68|Revision 1 - no extensions to language used.}}
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny].}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
<syntaxhighlight lang="algol68">STRING target := "METHINKS IT IS LIKE A WEASEL";
STRING target := "METHINKS IT IS LIKE A WEASEL";
PROC fitness = (STRING tstrg)REAL:
Line 828 ⟶ 889:
INT iters := 0;
kid[LWB kid] := LOC[UPB target]CHAR;
REAL mutate rate = 0.05;
# initialize #
Line 836 ⟶ 897:
 
fits := fitness(parent);
WHILE fits < 100.0 DO
INT j;
REAL kf;
mutate rate := 1.0 - exp(- (100.0 - fits)/400.0);
FOR j FROM LWB kid TO UPB kid DO
mutate(kid[j], parent, mutate rate)
Line 850 ⟶ 910:
FI
OD;
IFfits iters MOD< 100 = .0 THEN
DO
kewe( parent, iters, fits, mutate rate )
kewe( parent, iters, fits, mutate rate );
FI;
iters+:=1
OD;
Line 861 ⟶ 921:
(
evolve
)
)</syntaxhighlight>
</syntaxhighlight>
Sample output:
<pre>
#0000 fitness: 0.00% 0.22120500 'JUQBKWCHNPJQBDVGDQUELSIJULMHYUGD LO LFDKHDJJNQIFQMPYMUX'
#01000001 fitness: 50.5000% 0.21040500 'NGVGIOJV IT JS MGLD CQBJQGDQUELSIJULMHYOGD VEAWCIMPYMUP'
#02000002 fitness: 22 0.3100% 0.17650500 'MGTGIOJS IU JS MGKDQBJQGDQUELSIJP CMHYOGD VEARELMPYMUQ'
#03000003 fitness: 60 0.6500% 0.09370500 'METHIOKS IU ISQBJQGFQUELSIJP LIKEMHYO BD VFASELMPYMUQ'
#03540004 fitness: 100 0.00% 0.02350500 'METHINKS ITQBJQGFQU ISLSIJP LIKEMHOO AD WEASELMPYMUQ'
#0005 fitness: 0.00% 0.0500 'QBJQGSQU LSIJP MHOO D MPYMFN'
#0006 fitness: 0.00% 0.0500 'QBJQGSQU LSIJP MHOO D MPCMFN'
#0007 fitness: 0.00% 0.0500 'QBRQGSQU LSIJP MHOO D MPCMFN'
#0008 fitness: 0.00% 0.0500 'QBRQGLQU LSIJP MHOE D MPCMFN'
...
#0097 fitness: 90.48% 0.0500 'METHIOKS IT IS LIKE A WEASEL'
#0098 fitness: 90.48% 0.0500 'METHIOKS IT IS LIKE A WEASEL'
#0099 fitness: 90.48% 0.0500 'METHIOKS IT IS LIKE A WEASEL'
#0100 fitness: 90.48% 0.0500 'METHIOKS IT IS LIKE A WEASEL'
#0101 fitness: 90.48% 0.0500 'METHIOKS IT IS LIKE A WEASEL'
#0102 fitness: 90.48% 0.0500 'METHIOKS IT IS LIKE A WEASEL'
#0103 fitness: 90.48% 0.0500 'METHIOKS IT IS LIKE A WEASEL'
#0104 fitness: 100.00% 0.0500 'METHINKS IT IS LIKE A WEASEL'
</pre>
 
Line 1,186 ⟶ 1,260:
#
</pre>
 
=={{header|BASIC}}==
==={{header|BBC BASIC}}===
<syntaxhighlight lang="bbcbasic"> target$ = "METHINKS IT IS LIKE A WEASEL"
parent$ = "IU RFSGJABGOLYWF XSMFXNIABKT"
mutation_rate = 0.5
children% = 10
DIM child$(children%)
REPEAT
bestfitness = 0
bestindex% = 0
FOR index% = 1 TO children%
child$(index%) = FNmutate(parent$, mutation_rate)
fitness = FNfitness(target$, child$(index%))
IF fitness > bestfitness THEN
bestfitness = fitness
bestindex% = index%
ENDIF
NEXT index%
parent$ = child$(bestindex%)
PRINT parent$
UNTIL parent$ = target$
END
DEF FNfitness(text$, ref$)
LOCAL I%, F%
FOR I% = 1 TO LEN(text$)
IF MID$(text$, I%, 1) = MID$(ref$, I%, 1) THEN F% += 1
NEXT
= F% / LEN(text$)
DEF FNmutate(text$, rate)
LOCAL C%
IF rate > RND(1) THEN
C% = 63+RND(27)
IF C% = 64 C% = 32
MID$(text$, RND(LEN(text$)), 1) = CHR$(C%)
ENDIF
= text$</syntaxhighlight>
 
=={{header|Batch File}}==
Line 1,311 ⟶ 1,427:
Done.
</pre>
 
=={{header|BASIC}}==
==={{header|BBC BASIC}}===
<syntaxhighlight lang="bbcbasic"> target$ = "METHINKS IT IS LIKE A WEASEL"
parent$ = "IU RFSGJABGOLYWF XSMFXNIABKT"
mutation_rate = 0.5
children% = 10
DIM child$(children%)
REPEAT
bestfitness = 0
bestindex% = 0
FOR index% = 1 TO children%
child$(index%) = FNmutate(parent$, mutation_rate)
fitness = FNfitness(target$, child$(index%))
IF fitness > bestfitness THEN
bestfitness = fitness
bestindex% = index%
ENDIF
NEXT index%
parent$ = child$(bestindex%)
PRINT parent$
UNTIL parent$ = target$
END
DEF FNfitness(text$, ref$)
LOCAL I%, F%
FOR I% = 1 TO LEN(text$)
IF MID$(text$, I%, 1) = MID$(ref$, I%, 1) THEN F% += 1
NEXT
= F% / LEN(text$)
DEF FNmutate(text$, rate)
LOCAL C%
IF rate > RND(1) THEN
C% = 63+RND(27)
IF C% = 64 C% = 32
MID$(text$, RND(LEN(text$)), 1) = CHR$(C%)
ENDIF
= text$</syntaxhighlight>
 
=={{header|C}}==
Line 2,507 ⟶ 2,581:
Generation 23, dist= 1: METHINKS IT IS LIKE A WEASEW
Generation 24, dist= 0: METHINKS IT IS LIKE A WEASEL</pre>
 
=={{header|Dart}}==
{{trans|Java}}
<syntaxhighlight lang="Dart">
import 'dart:math';
 
class EvoAlgo {
static final String target = "METHINKS IT IS LIKE A WEASEL";
static final List<String> possibilities = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ".split('');
static int c = 100; // Number of spawn per generation
static double minMutateRate = 0.09;
static int perfectFitness = target.length;
static String parent = '';
static Random rand = Random();
 
static int fitness(String trial) {
int retVal = 0;
for (int i = 0; i < trial.length; i++) {
if (trial[i] == target[i]) retVal++;
}
return retVal;
}
 
static double newMutateRate() {
return (((perfectFitness - fitness(parent)) / perfectFitness) * (1 - minMutateRate));
}
 
static String mutate(String parent, double rate) {
String retVal = '';
for (int i = 0; i < parent.length; i++) {
retVal += (rand.nextDouble() <= rate)
? possibilities[rand.nextInt(possibilities.length)]
: parent[i];
}
return retVal;
}
 
static void main() {
parent = mutate(target, 1);
int iter = 0;
while (parent != target) {
double rate = newMutateRate();
iter++;
if (iter % 100 == 0) {
print('$iter: $parent, fitness: ${fitness(parent)}, rate: $rate');
}
String bestSpawn;
int bestFit = 0;
for (int i = 0; i < c; i++) {
String spawn = mutate(parent, rate);
int fit = fitness(spawn);
if (fit > bestFit) {
bestSpawn = spawn;
bestFit = fit;
}
}
if (bestFit > fitness(parent)) {
parent = bestSpawn;
}
}
print('$parent, $iter');
}
}
 
void main() {
EvoAlgo.main();
}
</syntaxhighlight>
{{out}}
<pre>
100: MFTHINFU IR N WLEKWKA WQZKYM, fitness: 13, rate: 0.4875
200: MXTHINPJ HR NNTLEKF A WDZHEH, fitness: 14, rate: 0.455
300: YNTHINPJ IK IS LEKNNA ADZHEL, fitness: 16, rate: 0.39
400: XETHI PS IKXIS LBKNDA QEUSEL, fitness: 18, rate: 0.325
500: NETHINPS I IS IBKLNA WEASEL, fitness: 21, rate: 0.2275
METHINKS IT IS LIKE A WEASEL, 551
 
</pre>
 
=={{header|Delphi}}==
See [https://rosettacode.org/wiki/Evolutionary_algorithm#Pascal Pascal].
Line 2,555 ⟶ 2,708:
 
weasel()</syntaxhighlight>
 
=={{header|EasyLang}}==
<syntaxhighlight>
target$ = "METHINKS IT IS LIKE A WEASEL"
abc$[] = strchars " ABCDEFGHIJLKLMNOPQRSTUVWXYZ"
P = 0.05
C = 100
func fitness trial$ .
for i to len trial$
res += if substr trial$ i 1 <> substr target$ i 1
.
return res
.
func$ mutate parent$ .
for c$ in strchars parent$
if randomf < P
res$ &= abc$[randint len abc$[]]
else
res$ &= c$
.
.
return res$
.
for i to len target$
parent$ &= abc$[randint len abc$[]]
.
while fitness parent$ > 0
copies$[] = [ ]
for i to C
copies$[] &= mutate parent$
.
parent$ = copies$[1]
for s$ in copies$[]
if fitness s$ < fitness parent$
parent$ = s$
.
.
step += 1
print step & " " & parent$
.
</syntaxhighlight>
 
=={{header|EchoLisp}}==
Line 2,632 ⟶ 2,826:
 
=={{header|Elena}}==
ELENA 56.0x :
<syntaxhighlight lang="elena">import system'routines;
import extensions;
Line 2,651 ⟶ 2,845:
{
randomString()
= 0.repeatTill(self).selectBy::(x => randomChar).summarize(new StringWriter());
fitnessOf(s)
Line 2,657 ⟶ 2,851:
mutate(p)
= self.selectBy::(ch => rnd.nextReal() <= p ? randomChar : ch).summarize(new StringWriter());
}
 
class EvoAlgorithm : Enumerator
{
object theTarget_target;
object theCurrent_current;
object theVariantCount_variantCount;
 
constructor new(s,count)
{
theTarget_target := s;
theVariantCount_variantCount := count.toInt();
}
 
get Value() = theCurrent_current;
 
bool next()
{
if (nil == theCurrent_current)
{ theCurrent_current := theTarget_target.Length.randomString(); ^ true };
if (theTarget_target == theCurrent_current)
{ ^ false };
auto variants := Array.allocate(theVariantCount_variantCount).populate::(x => theCurrent_current.mutate:(P) );
theCurrent_current := variants.sort::(a,b => a.fitnessOf:(Target) > b.fitnessOf:(Target) ).at:(0);
^ true
Line 2,691 ⟶ 2,885:
reset()
{
theCurrent_current := nil
}
enumerable() => theTarget_target;
}
 
Line 2,700 ⟶ 2,894:
{
var attempt := new Integer();
EvoAlgorithm.new(Target,C).forEach::(current)
{
console
Line 3,566 ⟶ 3,760:
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/Weasel_program}}
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation &mdash;i.e. XML, JSON&mdash; they are intended for storage and transfer purposes more than visualization and edition.
 
'''Solution'''
Programs in Fōrmulæ are created/edited online in its [https://formulae.org website], However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.
 
[[File:Fōrmulæ - Evolutionary algorithm 01.png]]
In '''[https://formulae.org/?example=Weasel_program this]''' page you can see the program(s) related to this task and their results.
 
'''Test case'''
 
[[File:Fōrmulæ - Evolutionary algorithm 02.png]]
 
[[File:Fōrmulæ - Evolutionary algorithm 03.png]]
 
'''A graph of the fitness function'''
 
[[File:Fōrmulæ - Evolutionary algorithm 04.png]]
 
[[File:Fōrmulæ - Evolutionary algorithm 05.png]]
 
=={{header|Go}}==
Line 3,830 ⟶ 4,036:
end
</syntaxhighlight>
 
=={{Header|Insitux}}==
 
{{Trans|Clojure}}
 
Define the evolution parameters (values here per Wikipedia article), with a couple of problem constants.
 
<syntaxhighlight lang="insitux">
(var c 100) ;number of children in each generation
(var p 0.05) ;mutation probability
 
(var target "METHINKS IT IS LIKE A WEASEL")
(var tsize (len target))
 
(var alphabet (to-vec " ABCDEFGHIJLKLMNOPQRSTUVWXYZ"))
 
</syntaxhighlight>
 
Now the major functions. <code>fitness</code> simply counts the number of characters matching the target.
 
<syntaxhighlight lang="insitux">
(var fitness (comp @(map = target) (count val)))
(var perfect-fit? (comp fitness (= tsize)))
 
(var rand-char #(rand-pick alphabet))
(var mutate (map #(if (< (rand) p) (rand-char) %)))
</syntaxhighlight>
 
Finally evolve. At each generation, print the generation number, the parent, and the parent's fitness.
 
<syntaxhighlight lang="insitux">
(function evolve generation parent
 
(print (pad-left " " 3 generation) " " (... str parent) " " (fitness parent))
 
(return-when (perfect-fit? parent))
 
(let children (times c #(mutate parent))
fittest (max-by fitness (... vec parent children)))
 
(recur (inc generation) fittest))
 
(evolve 1 (times tsize rand-char))
</syntaxhighlight>
 
{{out}}
 
<pre>
1 LUUDSLXITIQ JREKRDIQFXBPJMBA 2
2 LUUDSLXITIQ LREKRDIQFXBPHMEA 3
...
10 LUFRSLKSTIQ CFHLIGANB WPHMEL 10
11 LUFRSLKSTIQ CF LIGANB WPHMEL 11
...
20 MUTRINKSAIT GF LITENB WPDSEL 18
21 METRINKSAIT NY LITENB WPDSEL 19
...
30 METWINKS IT N LITE B WEASEL 23
31 METWINKS IT N LITE B WEASEL 23
...
40 METHINKS IT IS LITE A WEASEL 27
41 METHINKS IT IS LITE A WEASEL 27
...
50 METHINKS IT IS LITE A WEASEL 27
51 METHINKS IT IS LIKE A WEASEL 28
</pre>
 
=={{header|J}}==
Line 4,208 ⟶ 4,480:
Generation: 50, Best: METHINKS IT IS LIKEZA WEASEL, fitness:1
Generation: 52, Best: METHINKS IT IS LIKE A WEASEL, fitness:0
</pre>
 
 
An attempt using ES6
by A.K.Bateman 2023
<syntaxhighlight lang="javascript">
"use strict"
const TARGET = "METHINKS IT IS LIKE A WEASEL";
const GENE_POOL = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ';
const C = 100;
const MUTATION_RATE = 0.3;
 
function randomIdGenerator(length) {
return Math.floor(Math.random() * length);
}
function getGene() {
return GENE_POOL[randomIdGenerator(GENE_POOL.length)];
}
 
class Parent {
_arrayLength;
_genePool;
_geneGenerator;
 
constructor(arrayLength, genePool, geneGenerator) {
if (typeof arrayLength === 'number' && arrayLength > 0) {
this._arrayLength = arrayLength;
}
 
if (typeof genePool === 'string' && genePool.length > 0) {
this._genePool = [...genePool];
}
 
if (typeof geneGenerator === 'function') {
this._geneGenerator = geneGenerator;
}
}
generate() {
const letters = [];
 
while (letters.length < this._arrayLength) {
letters.push(this._geneGenerator());
}
 
return letters.join('');
}
}
 
function fitness(needle, target) {
if (needle.length !== target.length) return 0;
 
const needleArray = [...needle];
let count = 0;
 
[...target].forEach((item, index) => {
if (item === needleArray[index]) count++;
});
 
return count;
}
 
function mutate({ source, mutationRate }) {
if (typeof source !== 'string' || source.length === 0) return '';
const sourceLength = source.length;
const iterations = Math.floor(sourceLength * mutationRate);
const stringArray = [...source];
 
for(let i = 0; i < iterations; i++) {
const shouldReplace = Boolean(Math.floor(Math.random() * 2));
 
if(shouldReplace) {
const id = randomIdGenerator(sourceLength);
stringArray[id] = getGene();
}
}
 
return stringArray.join('');
}
 
function createMutants(parent, mutantNumber) {
const mutantArray = [];
 
for (let i = 0; i < mutantNumber; i++) {
const mutant = mutate({source: parent, mutationRate: MUTATION_RATE});
 
mutantArray.push(
{
mutant,
fitness: fitness(mutant, TARGET),
},
);
}
 
return mutantArray;
}
 
function helperInit(parentString, parentFitness) {
const mutant = createMutants(parentString, C)
.sort( (a,b) => a.fitness - b.fitness ).pop();
 
if (mutant.fitness >= parentFitness) {
return {
string: mutant.mutant,
fitness: mutant.fitness,
};
}
 
return {
string: parentString,
fitness: parentFitness,
};
}
 
function run() {
const parent = new Parent(TARGET.length, GENE_POOL, getGene);
let parentString = parent.generate();
let parentFitness = fitness(parentString, TARGET);
let genCount = 0;
 
while(parentString !== TARGET) {
const init = helperInit(parentString, parentFitness);
parentString = init.string;
parentFitness = init.fitness;
console.log(init.string);
genCount++;
}
 
console.log(`Ended in ${genCount} generations`);
}
 
run();
</syntaxhighlight>
example output:
<pre>
METHYNKS IT IS LIKE A WEASEL
METHYNKS IT IS LIKE A WEASEL
METHYNKS IT IS LIKE A WEASEL
METHYNKS IT IS LIKE A WEASEL
METHYNKS IT IS LIKE A WEASEL
METHINKS IT IS LIKE A WEASEL
Ended in 240 generations
</pre>
 
=={{header|jq}}==
{{Works with|jq}}
 
'''Works with gojq, the Go implementation of jq(*)'''
 
'''Works with jaq, the Rust implementation of jq(*)'''
 
In this entry, the "fitness" score is based on codepoint differences;
this has the effect of preserving correctly located spaces.
Notice also how the algorithm quickly achieves an approximate
solution but takes a while to arrive at the destination.
 
Since jq currently does not have a PRNG, the following assumes the availability
of /dev/random as a source of entropy. The output shown below was generated by
invoking jq in the pipeline:
<pre>
< /dev/random tr -cd '0-9' | fold -w 3 | $JQ -cnr -f evolutionary-algorithm.jq
</pre>
 
(*) For gojq and jaq, leading 0s must be stripped from the input, e.g. by
`sed -e '/^0./s/0//' -e '/^0./s/0//'`.
 
<syntaxhighlight lang="jq">
# Assumption: input consists of random three-digit numbers i.e. 000 to 999
def rand: input;
 
def set: "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
 
def abs:
if . < 0 then -. else . end;
 
def ichar:
if type == "number" then . else explode[0] end;
 
# Output: a pseudo-random character from set.
# $n should be a random number drawn from range(0; N) inclusive where N > set|length
# Input: an admissible character from `set` (ignored in this implementation)
def shift($n):
($n % (set|length)) as $i
| set[$i:$i+1];
 
# fitness: 0 indicates a perfect fit; greater numbers indicate worse fit.
def fitness($gold):
def diff($c; $d): ($c|ichar) - ($d|ichar) | abs;
. as $in
| reduce range(0;length) as $i (0; . + diff($in[$i:$i+1]; $gold[$i:$i+1]));
 
# Input: a string
# Output: a mutation of . such that each character is mutated with probability $r
def mutate($r):
# Output: a pseudo-random character from set
# $n should be a random number drawn from range(0; N) inclusive where N > set|length
def letter($n):
($n % (set|length)) as $i
| set[$i:$i+1];
 
. as $p
| reduce range(0;length) as $i ("";
rand as $rand
| if ($rand/1000) < $r then . + letter($rand)
else . + $p[$i:$i+1]
end );
 
# An array of $n children of the parent provided as input; $r is the mutation probability
def children($n; $r):
[range(0;$n) as $i | mutate($r)];
 
# Input: a "parent"
# Output: a single string
def next_generation($gold; $r):
([.] + children(100; $r))
| min_by( fitness($gold) );
 
# Evolve towards the target string provided as input, using $r as the mutation rate;
# `recurse` is used in order to show progress conveniently.
def evolve($r):
. as $gold
| (set|length) as $s
| (reduce range(0; $n) as $i (""; (rand % $s) as $j | . + set[$j:$j+1])) as $string
| {count: 0, $string }
| recurse (
if .string | fitness($gold) == 0 then empty
else .string |= next_generation($gold; $r)
| .count += 1
end);
 
"METHINKS IT IS LIKE A WEASEL" | evolve(0.05)
</syntaxhighlight>
{{output}}
<pre>
{"count":0,"string":"OIRSP AVNMTSSKOEIRBGDXZUBIQL"}
{"count":1,"string":"OIRSP AV MTSSKOEIRBGDXZUBIQL"}
{"count":2,"string":"OIRSP AV MTSAKOEIRBGD ZUBIQL"}
{"count":3,"string":"OIRSPCAV MTSAWOEIRBGD ZUBIQL"}
{"count":4,"string":"OIRJACAV MTEAWOEIRBGD ZUBIQL"}
{"count":5,"string":"OIRJACTV MTEAWOEIRBGD ZGBIQL"}
{"count":6,"string":"OIRJBCTV MTEAWAEIRBGD ZGBIJL"}
{"count":7,"string":"OIRJBCTV MTEAWAEIRBGD ZGBTJL"}
{"count":8,"string":"UIRJBCTV MT AWFEIRBGG ZGBTJL"}
{"count":9,"string":"UIRJBMTV MT AWFEIRBGG ZGBTJL"}
{"count":10,"string":"JIRJEMTV MT AWFEIKGGG ZGBTJL"}
{"count":11,"string":"JIRJEMKV MT AWFEIKGGG XGBTJL"}
{"count":12,"string":"JIRJEMKV MT AWFEIKGGG XGBTAL"}
{"count":13,"string":"JIRJEMKV MT KWFEIKGGG XGBTAL"}
{"count":14,"string":"JFRJEMKP MT KWFEIKGGG XGBTAL"}
{"count":15,"string":"JFRJEMKP MT KWFJIKGGG XGBTAL"}
{"count":16,"string":"JFRJEMKT MT KQFJIKGGG XGBTAL"}
{"count":17,"string":"JFRJEMKT MT HQFJIKGGG XGBTAL"}
{"count":18,"string":"JFRJEMKT MT HQFJIKGGC XGBTAL"}
{"count":19,"string":"LFRJEMKT MT HQFJIIGGC XGATFL"}
{"count":20,"string":"LFRJIMKT MT HQFJIIGGC XGATFL"}
...
{"count":61,"string":"MFTHINKS JT IR LIKE A WEAREL"}
{"count":62,"string":"MFTHINKS JT IR LIKE A WEAREL"}
{"count":63,"string":"MFTHINKS JT IR LIKE A WEAREL"}
{"count":64,"string":"MFTHINKS JT IR LIKE A WEAREL"}
{"count":65,"string":"MFTHINKS JT IR LIKE A WEAREL"}
{"count":66,"string":"MFTHINKS JT IR LIKE A WEAREL"}
{"count":67,"string":"MFTHINKS JT IR LIKE A WEAREL"}
{"count":68,"string":"MFTHINKS JT IR LIKE A WEAREL"}
{"count":69,"string":"MFTHINKS IT IR LIKE A WEAREL"}
{"count":70,"string":"MFTHINKS IT IR LIKE A WEAREL"}
{"count":71,"string":"MFTHINKS IT IS LIKE A WEAREL"}
{"count":72,"string":"MFTHINKS IT IS LIKE A WEAREL"}
{"count":73,"string":"MFTHINKS IT IS LIKE A WEAREL"}
{"count":74,"string":"MFTHINKS IT IS LIKE A WEAREL"}
{"count":75,"string":"MFTHINKS IT IS LIKE A WEAREL"}
{"count":76,"string":"METHINKS IT IS LIKE A WEAREL"}
{"count":77,"string":"METHINKS IT IS LIKE A WEAREL"}
{"count":78,"string":"METHINKS IT IS LIKE A WEAREL"}
{"count":79,"string":"METHINKS IT IS LIKE A WEAREL"}
{"count":80,"string":"METHINKS IT IS LIKE A WEAREL"}
{"count":81,"string":"METHINKS IT IS LIKE A WEAREL"}
{"count":82,"string":"METHINKS IT IS LIKE A WEASEL"}
</pre>
 
Line 6,926 ⟶ 7,475:
@alphabet.roll(target.chars).join,
{ max :by(&fitness), mutate($_, .001) xx C } ... target;
print "\n";
</syntaxhighlight>
 
Line 7,700 ⟶ 8,250:
until best = 0;
end func;</syntaxhighlight>
 
=={{header|SETL}}==
<syntaxhighlight lang="setl">program weasel;
setrandom(0);
target := "METHINKS IT IS LIKE A WEASEL";
charset := {c : c in " ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
mutation_rate := 0.1;
generation_size := 100;
loop init
current := +/[random charset : c in target];
doing
print(lpad(str fitness(current, target), 3), current);
while current /= target do
current := next_generation(
current, target, mutation_rate, generation_size, charset);
end loop;
proc fitness(candidate, target);
return #[i : i in [1..#target] | candidate(i) /= target(i)];
end proc;
proc mutate(candidate, mutation_rate, charset);
return +/[
if random 1.0 < mutation_rate
then random charset
else c
end
: c in candidate
];
end proc;
proc next_generation(
parent, target, mutation_rate, generation_size, charset);
children := {
[fitness(c:=mutate(parent, mutation_rate, charset), target), c]
: i in [1..generation_size]
};
return random children{min/domain children};
end proc;
end program;</syntaxhighlight>
{{out}}
<pre> 25 DSBHHVDSLFJFYAXRTZEAXBRDPATW
24 DSBHHMDSLFJ YAXRTZEAXBRDPATW
23 DSBHHMDSLFT YAXRTZEAXBRDJATW
20 DSBHHMDSLFT YJXRTZEAX WDJSTW
...
1 METHINKS IT IS LPKE A WEASEL
1 METHINKS IT IS LQKE A WEASEL
0 METHINKS IT IS LIKE A WEASEL</pre>
 
=={{header|SequenceL}}==
Line 8,893 ⟶ 9,494:
=={{header|Wren}}==
{{trans|Go}}
<syntaxhighlight lang="ecmascriptwren">import "random" for Random
 
var target = "METHINKS IT IS LIKE A WEASEL"
1,983

edits