September Morn Update
This commit is contained in:
parent
4e2d22a71d
commit
aac6731f2c
6856 changed files with 141342 additions and 21127 deletions
1
Task/Evolutionary-algorithm/00META.yaml
Normal file
1
Task/Evolutionary-algorithm/00META.yaml
Normal file
|
|
@ -0,0 +1 @@
|
|||
--- {}
|
||||
|
|
@ -1,68 +1,76 @@
|
|||
import system'routines.
|
||||
import extensions.
|
||||
import system'routines;
|
||||
import extensions;
|
||||
import extensions'text;
|
||||
|
||||
const Target = "METHINKS IT IS LIKE A WEASEL".
|
||||
const AllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ".
|
||||
const string Target = "METHINKS IT IS LIKE A WEASEL";
|
||||
const string AllowedCharacters = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
const C = 100.
|
||||
const P = 0.05r.
|
||||
const int C = 100;
|
||||
const real P = 0.05r;
|
||||
|
||||
rnd = randomGenerator.
|
||||
rnd = randomGenerator;
|
||||
|
||||
randomChar
|
||||
= AllowedCharacters[rnd nextInt(AllowedCharacters length)].
|
||||
= AllowedCharacters[rnd.nextInt(AllowedCharacters.Length)];
|
||||
|
||||
extension evoHelper
|
||||
{
|
||||
randomString
|
||||
= 0 till:self repeat(:x)( randomChar ); summarize:(String new); literal.
|
||||
randomString()
|
||||
= 0.repeatTill(self).selectBy:(x => randomChar).summarize(new StringWriter());
|
||||
|
||||
fitnessOf:s
|
||||
= self zip:s by(:a:b)( (a == b)iif(1,0) ); summarize(Integer new); int.
|
||||
fitnessOf(s)
|
||||
= self.zipBy(s, (a,b => a==b ? 1 : 0)).summarize(new Integer()).toInt();
|
||||
|
||||
mutate : p
|
||||
= self selectBy(:ch)( (rnd nextReal <= p) iif(randomChar,ch) ); summarize(String new); literal.
|
||||
mutate(p)
|
||||
= self.selectBy:(ch => rnd.nextReal() <= p ? randomChar : ch).summarize(new StringWriter());
|
||||
}
|
||||
|
||||
class EvoAlgorithm :: Enumerator
|
||||
class EvoAlgorithm : Enumerator
|
||||
{
|
||||
object theTarget.
|
||||
object theCurrent.
|
||||
object theVariantCount.
|
||||
object theTarget;
|
||||
object theCurrent;
|
||||
object theVariantCount;
|
||||
|
||||
constructor new : s of:count
|
||||
[
|
||||
theTarget := s.
|
||||
theVariantCount := count int.
|
||||
]
|
||||
constructor new:of(s,count)
|
||||
{
|
||||
theTarget := s;
|
||||
theVariantCount := count.toInt();
|
||||
}
|
||||
|
||||
get = theCurrent.
|
||||
get() = theCurrent;
|
||||
|
||||
next
|
||||
[
|
||||
if ($nil == theCurrent)
|
||||
[ theCurrent := theTarget length; randomString. ^ true ].
|
||||
bool next()
|
||||
{
|
||||
if (nil == theCurrent)
|
||||
{ theCurrent := theTarget.Length.randomString(); ^ true };
|
||||
|
||||
if (theTarget == theCurrent)
|
||||
[ ^ false ].
|
||||
{ ^ false };
|
||||
|
||||
var variants := Array new:theVariantCount; populate(:x)( theCurrent mutate:P ).
|
||||
auto variants := Array.allocate(theVariantCount).populate:(x => theCurrent.mutate:P );
|
||||
|
||||
theCurrent := variants array; sort(:a:b)( a fitnessOf:Target > b fitnessOf:Target ); getAt:0.
|
||||
theCurrent := variants.sort:(a,b => a.fitnessOf:Target > b.fitnessOf:Target ).at:0;
|
||||
|
||||
^ true.
|
||||
]
|
||||
^ true
|
||||
}
|
||||
|
||||
reset()
|
||||
{
|
||||
theCurrent := nil
|
||||
}
|
||||
|
||||
enumerable() => theTarget;
|
||||
}
|
||||
|
||||
program =
|
||||
[
|
||||
var attempt := Integer new.
|
||||
EvoAlgorithm new:Target of:C; forEach(:current)
|
||||
[
|
||||
public program()
|
||||
{
|
||||
var attempt := new Integer();
|
||||
EvoAlgorithm.new:Target of:C.forEach:(current)
|
||||
{
|
||||
console
|
||||
printPaddingLeft(10,"#",attempt append:1);
|
||||
printLine(" ",current," fitness: ",current fitnessOf:Target).
|
||||
].
|
||||
.printPaddingLeft(10,"#",attempt.append(1))
|
||||
.printLine(" ",current," fitness: ",current.fitnessOf(Target))
|
||||
};
|
||||
|
||||
console readChar.
|
||||
].
|
||||
console.readChar()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ constant @alphabet = flat 'A'..'Z',' ';
|
|||
constant C = 100;
|
||||
|
||||
sub mutate { [~] (rand < mutate_chance ?? @alphabet.pick !! $_ for $^string.comb) }
|
||||
sub fitness { [+] $^string.comb Zeq state @ = target.comb }
|
||||
sub fitness { [+] $^string.comb Zeq target.comb }
|
||||
|
||||
loop (
|
||||
my $parent = @alphabet.roll(target.chars).join;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
func evolve(
|
||||
to target: String,
|
||||
parent: inout String,
|
||||
mutationRate: Int,
|
||||
copies: Int
|
||||
) {
|
||||
var parentFitness: Int {
|
||||
return fitness(target: target, sentence: parent)
|
||||
}
|
||||
|
||||
var generation = 0
|
||||
|
||||
while parent != target {
|
||||
generation += 1
|
||||
|
||||
let bestOfGeneration =
|
||||
(0..<copies)
|
||||
.map({_ in mutate(sentence: parent, rate: mutationRate) })
|
||||
.map({ (fitness(target: target, sentence: $0), $0) })
|
||||
.sorted(by: { $0.0 < $1.0 })
|
||||
.first!
|
||||
|
||||
if bestOfGeneration.0 < parentFitness {
|
||||
print("Gen \(generation) produced better fit. \(bestOfGeneration.1) with fitness \(bestOfGeneration.0)")
|
||||
parent = bestOfGeneration.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fitness(target: String, sentence: String) -> Int {
|
||||
return zip(target, sentence).filter(!=).count
|
||||
}
|
||||
|
||||
func mutate(sentence: String, rate: Int) -> String {
|
||||
return String(
|
||||
sentence.map({char in
|
||||
if Int.random(in: 1...100) - rate <= 0 {
|
||||
return "ABCDEFGHIJKLMNOPQRSTUVWXYZ ".randomElement()!
|
||||
} else {
|
||||
return char
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
let target = "METHINKS IT IS LIKE A WEASEL"
|
||||
let copies = 100
|
||||
let mutationRate = 20
|
||||
|
||||
var start = mutate(sentence: target, rate: 100)
|
||||
|
||||
print("target: \(target)")
|
||||
print("Gen 0: \(start) with fitness \(fitness(target: target, sentence: start))")
|
||||
|
||||
evolve(to: target, parent: &start, mutationRate: mutationRate, copies: 100)
|
||||
Loading…
Add table
Add a link
Reference in a new issue