From 50de368ae534f2bfaf03c573f675ef53a25f4001 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Wed, 20 Nov 2024 10:45:55 +0900 Subject: [PATCH 1/8] initial --- examples/gno.land/r/demo/games/ga/ga.gno | 163 +++++++++++++++++++++++ gnovm/tests/files/ga.gno | 163 +++++++++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 examples/gno.land/r/demo/games/ga/ga.gno create mode 100644 gnovm/tests/files/ga.gno diff --git a/examples/gno.land/r/demo/games/ga/ga.gno b/examples/gno.land/r/demo/games/ga/ga.gno new file mode 100644 index 00000000000..749d34f7940 --- /dev/null +++ b/examples/gno.land/r/demo/games/ga/ga.gno @@ -0,0 +1,163 @@ +package main + +import ( + "fmt" + "math/rand" + "time" +) + +// Individual represents a single solution in the population +type Individual struct { + Genome string + Fitness float64 +} + +// Target is the string we want to evolve +const Target = "HELLO, WORLD!" + +// MutationRate controls how often mutations occur +const MutationRate = 0.01 + +// PopulationSize defines the number of individuals in the population +const PopulationSize = 100 + +// Charset defines the possible characters in the genome +var Charset = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ, !") + +func main() { + rand.Seed(time.Now().UnixNano()) + + // Step 1: Initialize Population + population := initializePopulation(PopulationSize) + + generation := 0 + for { + // Step 2: Calculate Fitness + for i := range population { + population[i].Fitness = calculateFitness(population[i].Genome) + } + + // Step 3: Check for Solution + best := findBestIndividual(population) + fmt.Printf("Generation %d: %s (Fitness: %f)\n", generation, best.Genome, best.Fitness) + if best.Genome == Target { + fmt.Println("Target reached!") + break + } + + // Step 4: Generate Next Generation + population = generateNextGeneration(population) + + generation++ + } +} + +// initializePopulation creates a random population of individuals +func initializePopulation(size int) []Individual { + population := make([]Individual, size) + for i := 0; i < size; i++ { + population[i] = Individual{ + Genome: randomGenome(len(Target)), + } + } + return population +} + +// randomGenome generates a random string of the same length as the target +func randomGenome(length int) string { + genome := make([]rune, length) + for i := 0; i < length; i++ { + genome[i] = Charset[rand.Intn(len(Charset))] + } + return string(genome) +} + +// calculateFitness computes how close an individual is to the target string +func calculateFitness(genome string) float64 { + matches := 0 + for i, char := range genome { + if char == rune(Target[i]) { + matches++ + } + } + return float64(matches) / float64(len(Target)) +} + +// findBestIndividual finds the individual with the highest fitness in the population +func findBestIndividual(population []Individual) Individual { + best := population[0] + for _, individual := range population { + if individual.Fitness > best.Fitness { + best = individual + } + } + return best +} + +// generateNextGeneration produces the next generation using selection, crossover, and mutation +func generateNextGeneration(population []Individual) []Individual { + nextGeneration := make([]Individual, len(population)) + + for i := 0; i < len(population); i++ { + // Selection: Pick two parents + parent1 := selectIndividual(population) + parent2 := selectIndividual(population) + + // Crossover: Create a child + childGenome := crossover(parent1.Genome, parent2.Genome) + + // Mutation: Introduce random changes + childGenome = mutate(childGenome) + + // Add child to the next generation + nextGeneration[i] = Individual{ + Genome: childGenome, + } + } + + return nextGeneration +} + +// selectIndividual selects an individual from the population based on fitness (roulette wheel selection) +func selectIndividual(population []Individual) Individual { + totalFitness := 0.0 + for _, individual := range population { + totalFitness += individual.Fitness + } + + r := rand.Float64() * totalFitness + cumulative := 0.0 + for _, individual := range population { + cumulative += individual.Fitness + if cumulative >= r { + return individual + } + } + + return population[len(population)-1] +} + +// crossover combines two parent genomes to produce a child genome +func crossover(parent1, parent2 string) string { + child := make([]rune, len(parent1)) + cutPoint := rand.Intn(len(parent1)) + for i := 0; i < len(parent1); i++ { + if i < cutPoint { + child[i] = rune(parent1[i]) + } else { + child[i] = rune(parent2[i]) + } + } + return string(child) +} + +// mutate introduces random changes to a genome based on the mutation rate +func mutate(genome string) string { + mutated := []rune(genome) + for i := 0; i < len(mutated); i++ { + if rand.Float64() < MutationRate { + mutated[i] = Charset[rand.Intn(len(Charset))] + } + } + return string(mutated) +} diff --git a/gnovm/tests/files/ga.gno b/gnovm/tests/files/ga.gno new file mode 100644 index 00000000000..d47d03b32f9 --- /dev/null +++ b/gnovm/tests/files/ga.gno @@ -0,0 +1,163 @@ +package main + +import ( + "fmt" + "math/rand" + "time" +) + +// Individual represents a single solution in the population +type Individual struct { + Genome string + Fitness float64 +} + +// Target is the string we want to evolve +const Target = "HELLO, WORLD!" + +// MutationRate controls how often mutations occur +const MutationRate = 0.01 + +// PopulationSize defines the number of individuals in the population +const PopulationSize = 100 + +// Charset defines the possible characters in the genome +var Charset = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ, !") + +func main() { + //rand.Seed(time.Now().UnixNano()) + + // Step 1: Initialize Population + population := initializePopulation(PopulationSize) + + generation := 0 + for { + // Step 2: Calculate Fitness + for i := range population { + population[i].Fitness = calculateFitness(population[i].Genome) + } + + // Step 3: Check for Solution + best := findBestIndividual(population) + fmt.Printf("Generation %d: %s (Fitness: %f)\n", generation, best.Genome, best.Fitness) + if best.Genome == Target { + fmt.Println("Target reached!") + break + } + + // Step 4: Generate Next Generation + population = generateNextGeneration(population) + + generation++ + } +} + +// initializePopulation creates a random population of individuals +func initializePopulation(size int) []Individual { + population := make([]Individual, size) + for i := 0; i < size; i++ { + population[i] = Individual{ + Genome: randomGenome(len(Target)), + } + } + return population +} + +// randomGenome generates a random string of the same length as the target +func randomGenome(length int) string { + genome := make([]rune, length) + for i := 0; i < length; i++ { + genome[i] = Charset[rand.Intn(len(Charset))] + } + return string(genome) +} + +// calculateFitness computes how close an individual is to the target string +func calculateFitness(genome string) float64 { + matches := 0 + for i, char := range genome { + if char == rune(Target[i]) { + matches++ + } + } + return float64(matches) / float64(len(Target)) +} + +// findBestIndividual finds the individual with the highest fitness in the population +func findBestIndividual(population []Individual) Individual { + best := population[0] + for _, individual := range population { + if individual.Fitness > best.Fitness { + best = individual + } + } + return best +} + +// generateNextGeneration produces the next generation using selection, crossover, and mutation +func generateNextGeneration(population []Individual) []Individual { + nextGeneration := make([]Individual, len(population)) + + for i := 0; i < len(population); i++ { + // Selection: Pick two parents + parent1 := selectIndividual(population) + parent2 := selectIndividual(population) + + // Crossover: Create a child + childGenome := crossover(parent1.Genome, parent2.Genome) + + // Mutation: Introduce random changes + childGenome = mutate(childGenome) + + // Add child to the next generation + nextGeneration[i] = Individual{ + Genome: childGenome, + } + } + + return nextGeneration +} + +// selectIndividual selects an individual from the population based on fitness (roulette wheel selection) +func selectIndividual(population []Individual) Individual { + totalFitness := 0.0 + for _, individual := range population { + totalFitness += individual.Fitness + } + + r := rand.Float64() * totalFitness + cumulative := 0.0 + for _, individual := range population { + cumulative += individual.Fitness + if cumulative >= r { + return individual + } + } + + return population[len(population)-1] +} + +// crossover combines two parent genomes to produce a child genome +func crossover(parent1, parent2 string) string { + child := make([]rune, len(parent1)) + cutPoint := rand.Intn(len(parent1)) + for i := 0; i < len(parent1); i++ { + if i < cutPoint { + child[i] = rune(parent1[i]) + } else { + child[i] = rune(parent2[i]) + } + } + return string(child) +} + +// mutate introduces random changes to a genome based on the mutation rate +func mutate(genome string) string { + mutated := []rune(genome) + for i := 0; i < len(mutated); i++ { + if rand.Float64() < MutationRate { + mutated[i] = Charset[rand.Intn(len(Charset))] + } + } + return string(mutated) +} From b1f8b0025d81a44b6f8bf89af0d06f1f5489adff Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Mon, 25 Nov 2024 23:02:37 +0900 Subject: [PATCH 2/8] save --- examples/gno.land/r/demo/games/ga/ga.gno | 5 +- gnovm/1.gno | 166 +++++++++++++++++++++++ 2 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 gnovm/1.gno diff --git a/examples/gno.land/r/demo/games/ga/ga.gno b/examples/gno.land/r/demo/games/ga/ga.gno index 749d34f7940..977b2dc3084 100644 --- a/examples/gno.land/r/demo/games/ga/ga.gno +++ b/examples/gno.land/r/demo/games/ga/ga.gno @@ -2,6 +2,7 @@ package main import ( "fmt" + "gno.land/p/demo/entropy" "math/rand" "time" ) @@ -25,7 +26,9 @@ const PopulationSize = 100 var Charset = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ, !") func main() { - rand.Seed(time.Now().UnixNano()) + //rand.Seed(time.Now().UnixNano()) + //seed := uint64(entropy.New().Value()) + rand.Seed(int64(entropy.New().Value())) // Step 1: Initialize Population population := initializePopulation(PopulationSize) diff --git a/gnovm/1.gno b/gnovm/1.gno new file mode 100644 index 00000000000..60b976ea09d --- /dev/null +++ b/gnovm/1.gno @@ -0,0 +1,166 @@ +package main + +import ( + "fmt" + "gno.land/p/demo/entropy" + "math/rand" +) + +// Individual represents a single solution in the population +type Individual struct { + Genome string + Fitness float64 +} + +// Target is the string we want to evolve +const Target = "HELLO, WORLD!" + +// MutationRate controls how often mutations occur +const MutationRate = 0.01 + +// PopulationSize defines the number of individuals in the population +const PopulationSize = 100 + +// Charset defines the possible characters in the genome +var Charset = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ, !") + +func main() { + //rand.Seed(time.Now().UnixNano()) + //seed := uint64(entropy.New().Value()) + //rand.Seed(int64(entropy.New().Value())) + + // Step 1: Initialize Population + population := initializePopulation(PopulationSize) + + generation := 0 + for { + // Step 2: Calculate Fitness + for i := range population { + population[i].Fitness = calculateFitness(population[i].Genome) + } + + // Step 3: Check for Solution + best := findBestIndividual(population) + fmt.Printf("Generation %d: %s (Fitness: %f)\n", generation, best.Genome, best.Fitness) + if best.Genome == Target { + fmt.Println("Target reached!") + break + } + + // Step 4: Generate Next Generation + population = generateNextGeneration(population) + + generation++ + } +} + +// initializePopulation creates a random population of individuals +func initializePopulation(size int) []Individual { + population := make([]Individual, size) + for i := 0; i < size; i++ { + population[i] = Individual{ + Genome: randomGenome(len(Target)), + } + } + return population +} + +// randomGenome generates a random string of the same length as the target +func randomGenome(length int) string { + genome := make([]rune, length) + for i := 0; i < length; i++ { + //genome[i] = Charset[rand.Intn(len(Charset))] + genome[i] = Charset[entropy.New().Value()] + } + return string(genome) +} + +// calculateFitness computes how close an individual is to the target string +func calculateFitness(genome string) float64 { + matches := 0 + for i, char := range genome { + if char == rune(Target[i]) { + matches++ + } + } + return float64(matches) / float64(len(Target)) +} + +// findBestIndividual finds the individual with the highest fitness in the population +func findBestIndividual(population []Individual) Individual { + best := population[0] + for _, individual := range population { + if individual.Fitness > best.Fitness { + best = individual + } + } + return best +} + +// generateNextGeneration produces the next generation using selection, crossover, and mutation +func generateNextGeneration(population []Individual) []Individual { + nextGeneration := make([]Individual, len(population)) + + for i := 0; i < len(population); i++ { + // Selection: Pick two parents + parent1 := selectIndividual(population) + parent2 := selectIndividual(population) + + // Crossover: Create a child + childGenome := crossover(parent1.Genome, parent2.Genome) + + // Mutation: Introduce random changes + childGenome = mutate(childGenome) + + // Add child to the next generation + nextGeneration[i] = Individual{ + Genome: childGenome, + } + } + + return nextGeneration +} + +// selectIndividual selects an individual from the population based on fitness (roulette wheel selection) +func selectIndividual(population []Individual) Individual { + totalFitness := 0.0 + for _, individual := range population { + totalFitness += individual.Fitness + } + + r := rand.Float64() * totalFitness + cumulative := 0.0 + for _, individual := range population { + cumulative += individual.Fitness + if cumulative >= r { + return individual + } + } + + return population[len(population)-1] +} + +// crossover combines two parent genomes to produce a child genome +func crossover(parent1, parent2 string) string { + child := make([]rune, len(parent1)) + cutPoint := rand.Intn(len(parent1)) + for i := 0; i < len(parent1); i++ { + if i < cutPoint { + child[i] = rune(parent1[i]) + } else { + child[i] = rune(parent2[i]) + } + } + return string(child) +} + +// mutate introduces random changes to a genome based on the mutation rate +func mutate(genome string) string { + mutated := []rune(genome) + for i := 0; i < len(mutated); i++ { + if rand.Float64() < MutationRate { + mutated[i] = Charset[rand.Intn(len(Charset))] + } + } + return string(mutated) +} From 960d38c23e74770b44f5039d49493bde8345019e Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 26 Nov 2024 22:27:54 +0900 Subject: [PATCH 3/8] fixup --- examples/gno.land/r/demo/games/ga/ga.gno | 85 ++++++++++++------- .../gno.land/r/demo/games/ga/z0_filetest.gno | 20 +++++ 2 files changed, 74 insertions(+), 31 deletions(-) create mode 100644 examples/gno.land/r/demo/games/ga/z0_filetest.gno diff --git a/examples/gno.land/r/demo/games/ga/ga.gno b/examples/gno.land/r/demo/games/ga/ga.gno index 977b2dc3084..58f709fd90a 100644 --- a/examples/gno.land/r/demo/games/ga/ga.gno +++ b/examples/gno.land/r/demo/games/ga/ga.gno @@ -1,10 +1,9 @@ -package main +package ga import ( "fmt" "gno.land/p/demo/entropy" - "math/rand" - "time" + "math" ) // Individual represents a single solution in the population @@ -14,7 +13,9 @@ type Individual struct { } // Target is the string we want to evolve -const Target = "HELLO, WORLD!" +const Target = "HEY" + +//const Target = "HIH" // MutationRate controls how often mutations occur const MutationRate = 0.01 @@ -25,16 +26,16 @@ const PopulationSize = 100 // Charset defines the possible characters in the genome var Charset = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ, !") -func main() { - //rand.Seed(time.Now().UnixNano()) - //seed := uint64(entropy.New().Value()) - rand.Seed(int64(entropy.New().Value())) +//var Charset = []rune("ABCDEFGHIJK") + +func Start(ei *entropy.Instance) (int, string) { + //println("---start") + var generation = 0 // Step 1: Initialize Population - population := initializePopulation(PopulationSize) + population := initializePopulation(PopulationSize, ei) - generation := 0 - for { + for generation < 200 { // Step 2: Calculate Fitness for i := range population { population[i].Fitness = calculateFitness(population[i].Genome) @@ -42,36 +43,40 @@ func main() { // Step 3: Check for Solution best := findBestIndividual(population) - fmt.Printf("Generation %d: %s (Fitness: %f)\n", generation, best.Genome, best.Fitness) + //fmt.Printf("Generation %d: %s (Fitness: %f)\n", generation, best.Genome, best.Fitness) if best.Genome == Target { - fmt.Println("Target reached!") - break + println("Target reached!") + return generation, string(best.Genome) } // Step 4: Generate Next Generation - population = generateNextGeneration(population) + population = generateNextGeneration(population, ei) generation++ } + return generation, "" } // initializePopulation creates a random population of individuals -func initializePopulation(size int) []Individual { +func initializePopulation(size int, ei *entropy.Instance) []Individual { population := make([]Individual, size) for i := 0; i < size; i++ { population[i] = Individual{ - Genome: randomGenome(len(Target)), + Genome: randomGenome(len(Target), ei), // new random each loop } } return population } // randomGenome generates a random string of the same length as the target -func randomGenome(length int) string { +func randomGenome(length int, ei *entropy.Instance) string { genome := make([]rune, length) for i := 0; i < length; i++ { - genome[i] = Charset[rand.Intn(len(Charset))] + index := ei.Value() % uint32(len(Charset)) + //fmt.Println("---index: ", index) + genome[i] = Charset[index] } + //fmt.Println("---genome: ", string(genome)) return string(genome) } @@ -98,19 +103,24 @@ func findBestIndividual(population []Individual) Individual { } // generateNextGeneration produces the next generation using selection, crossover, and mutation -func generateNextGeneration(population []Individual) []Individual { +func generateNextGeneration(population []Individual, ei *entropy.Instance) []Individual { + //println("---generate next generation") nextGeneration := make([]Individual, len(population)) for i := 0; i < len(population); i++ { // Selection: Pick two parents - parent1 := selectIndividual(population) - parent2 := selectIndividual(population) + parent1 := selectIndividual(population, ei) + //fmt.Println("---parent1: ", parent1) + parent2 := selectIndividual(population, ei) + //fmt.Println("---parent2: ", parent1) // Crossover: Create a child - childGenome := crossover(parent1.Genome, parent2.Genome) + childGenome := crossover(parent1.Genome, parent2.Genome, ei) + //fmt.Println("---1, childGenome: ", childGenome) // Mutation: Introduce random changes - childGenome = mutate(childGenome) + childGenome = mutate(childGenome, ei) + //fmt.Println("---2, childGenome: ", childGenome) // Add child to the next generation nextGeneration[i] = Individual{ @@ -122,17 +132,25 @@ func generateNextGeneration(population []Individual) []Individual { } // selectIndividual selects an individual from the population based on fitness (roulette wheel selection) -func selectIndividual(population []Individual) Individual { +func selectIndividual(population []Individual, ei *entropy.Instance) Individual { + //fmt.Println("---selectIndividual") totalFitness := 0.0 for _, individual := range population { totalFitness += individual.Fitness } + //rv := ei.Value() + //fmt.Println("---rv: ", rv) + //r := float64(rv) * totalFitness + //r := (float64(rv) * totalFitness) / (float64(math.MaxUint32) * totalFitness) + + r := (float64(ei.Value()) / float64(math.MaxUint32)) * totalFitness + //fmt.Println("---r: ", r) - r := rand.Float64() * totalFitness cumulative := 0.0 for _, individual := range population { cumulative += individual.Fitness if cumulative >= r { + //fmt.Println("---individual: ", individual) return individual } } @@ -141,9 +159,12 @@ func selectIndividual(population []Individual) Individual { } // crossover combines two parent genomes to produce a child genome -func crossover(parent1, parent2 string) string { +func crossover(parent1, parent2 string, ei *entropy.Instance) string { child := make([]rune, len(parent1)) - cutPoint := rand.Intn(len(parent1)) + + cutPoint := int(ei.Value()) % len(parent1) + //fmt.Println("---cutPoint:", cutPoint) + for i := 0; i < len(parent1); i++ { if i < cutPoint { child[i] = rune(parent1[i]) @@ -155,11 +176,13 @@ func crossover(parent1, parent2 string) string { } // mutate introduces random changes to a genome based on the mutation rate -func mutate(genome string) string { +func mutate(genome string, ei *entropy.Instance) string { mutated := []rune(genome) for i := 0; i < len(mutated); i++ { - if rand.Float64() < MutationRate { - mutated[i] = Charset[rand.Intn(len(Charset))] + rv := ei.Value() + if float64(rv) < MutationRate { + index := rv % uint32(len(Charset)) + mutated[i] = Charset[index] } } return string(mutated) diff --git a/examples/gno.land/r/demo/games/ga/z0_filetest.gno b/examples/gno.land/r/demo/games/ga/z0_filetest.gno new file mode 100644 index 00000000000..2db27190877 --- /dev/null +++ b/examples/gno.land/r/demo/games/ga/z0_filetest.gno @@ -0,0 +1,20 @@ +package main + +import ( + "std" + + "gno.land/p/demo/entropy" + "gno.land/r/demo/games/ga" + "strconv" +) + +func main() { + + r := entropy.New() + + gen, target := ga.Start(r) + //println("found " + target + " in " + strconv.Itoa(gen) + " generation") +} + +// Output: +// Target reached! From 7c22bba903b1586073d194b2bca0b19c5a595e7d Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 26 Nov 2024 22:32:12 +0900 Subject: [PATCH 4/8] fixup --- examples/gno.land/r/demo/games/ga/ga.gno | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/examples/gno.land/r/demo/games/ga/ga.gno b/examples/gno.land/r/demo/games/ga/ga.gno index 58f709fd90a..74c04540240 100644 --- a/examples/gno.land/r/demo/games/ga/ga.gno +++ b/examples/gno.land/r/demo/games/ga/ga.gno @@ -73,10 +73,8 @@ func randomGenome(length int, ei *entropy.Instance) string { genome := make([]rune, length) for i := 0; i < length; i++ { index := ei.Value() % uint32(len(Charset)) - //fmt.Println("---index: ", index) genome[i] = Charset[index] } - //fmt.Println("---genome: ", string(genome)) return string(genome) } @@ -110,17 +108,13 @@ func generateNextGeneration(population []Individual, ei *entropy.Instance) []Ind for i := 0; i < len(population); i++ { // Selection: Pick two parents parent1 := selectIndividual(population, ei) - //fmt.Println("---parent1: ", parent1) parent2 := selectIndividual(population, ei) - //fmt.Println("---parent2: ", parent1) // Crossover: Create a child childGenome := crossover(parent1.Genome, parent2.Genome, ei) - //fmt.Println("---1, childGenome: ", childGenome) // Mutation: Introduce random changes childGenome = mutate(childGenome, ei) - //fmt.Println("---2, childGenome: ", childGenome) // Add child to the next generation nextGeneration[i] = Individual{ @@ -133,24 +127,16 @@ func generateNextGeneration(population []Individual, ei *entropy.Instance) []Ind // selectIndividual selects an individual from the population based on fitness (roulette wheel selection) func selectIndividual(population []Individual, ei *entropy.Instance) Individual { - //fmt.Println("---selectIndividual") totalFitness := 0.0 for _, individual := range population { totalFitness += individual.Fitness } - //rv := ei.Value() - //fmt.Println("---rv: ", rv) - //r := float64(rv) * totalFitness - //r := (float64(rv) * totalFitness) / (float64(math.MaxUint32) * totalFitness) - r := (float64(ei.Value()) / float64(math.MaxUint32)) * totalFitness - //fmt.Println("---r: ", r) cumulative := 0.0 for _, individual := range population { cumulative += individual.Fitness if cumulative >= r { - //fmt.Println("---individual: ", individual) return individual } } @@ -163,7 +149,6 @@ func crossover(parent1, parent2 string, ei *entropy.Instance) string { child := make([]rune, len(parent1)) cutPoint := int(ei.Value()) % len(parent1) - //fmt.Println("---cutPoint:", cutPoint) for i := 0; i < len(parent1); i++ { if i < cutPoint { From ebee50b27495d8c7e3445860198d69417868ee26 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 26 Nov 2024 22:33:46 +0900 Subject: [PATCH 5/8] fixup --- examples/gno.land/r/demo/games/ga/ga.gno | 6 - gnovm/1.gno | 166 ----------------------- 2 files changed, 172 deletions(-) delete mode 100644 gnovm/1.gno diff --git a/examples/gno.land/r/demo/games/ga/ga.gno b/examples/gno.land/r/demo/games/ga/ga.gno index 74c04540240..fdd3f81a091 100644 --- a/examples/gno.land/r/demo/games/ga/ga.gno +++ b/examples/gno.land/r/demo/games/ga/ga.gno @@ -15,8 +15,6 @@ type Individual struct { // Target is the string we want to evolve const Target = "HEY" -//const Target = "HIH" - // MutationRate controls how often mutations occur const MutationRate = 0.01 @@ -26,11 +24,7 @@ const PopulationSize = 100 // Charset defines the possible characters in the genome var Charset = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ, !") -//var Charset = []rune("ABCDEFGHIJK") - func Start(ei *entropy.Instance) (int, string) { - //println("---start") - var generation = 0 // Step 1: Initialize Population population := initializePopulation(PopulationSize, ei) diff --git a/gnovm/1.gno b/gnovm/1.gno deleted file mode 100644 index 60b976ea09d..00000000000 --- a/gnovm/1.gno +++ /dev/null @@ -1,166 +0,0 @@ -package main - -import ( - "fmt" - "gno.land/p/demo/entropy" - "math/rand" -) - -// Individual represents a single solution in the population -type Individual struct { - Genome string - Fitness float64 -} - -// Target is the string we want to evolve -const Target = "HELLO, WORLD!" - -// MutationRate controls how often mutations occur -const MutationRate = 0.01 - -// PopulationSize defines the number of individuals in the population -const PopulationSize = 100 - -// Charset defines the possible characters in the genome -var Charset = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ, !") - -func main() { - //rand.Seed(time.Now().UnixNano()) - //seed := uint64(entropy.New().Value()) - //rand.Seed(int64(entropy.New().Value())) - - // Step 1: Initialize Population - population := initializePopulation(PopulationSize) - - generation := 0 - for { - // Step 2: Calculate Fitness - for i := range population { - population[i].Fitness = calculateFitness(population[i].Genome) - } - - // Step 3: Check for Solution - best := findBestIndividual(population) - fmt.Printf("Generation %d: %s (Fitness: %f)\n", generation, best.Genome, best.Fitness) - if best.Genome == Target { - fmt.Println("Target reached!") - break - } - - // Step 4: Generate Next Generation - population = generateNextGeneration(population) - - generation++ - } -} - -// initializePopulation creates a random population of individuals -func initializePopulation(size int) []Individual { - population := make([]Individual, size) - for i := 0; i < size; i++ { - population[i] = Individual{ - Genome: randomGenome(len(Target)), - } - } - return population -} - -// randomGenome generates a random string of the same length as the target -func randomGenome(length int) string { - genome := make([]rune, length) - for i := 0; i < length; i++ { - //genome[i] = Charset[rand.Intn(len(Charset))] - genome[i] = Charset[entropy.New().Value()] - } - return string(genome) -} - -// calculateFitness computes how close an individual is to the target string -func calculateFitness(genome string) float64 { - matches := 0 - for i, char := range genome { - if char == rune(Target[i]) { - matches++ - } - } - return float64(matches) / float64(len(Target)) -} - -// findBestIndividual finds the individual with the highest fitness in the population -func findBestIndividual(population []Individual) Individual { - best := population[0] - for _, individual := range population { - if individual.Fitness > best.Fitness { - best = individual - } - } - return best -} - -// generateNextGeneration produces the next generation using selection, crossover, and mutation -func generateNextGeneration(population []Individual) []Individual { - nextGeneration := make([]Individual, len(population)) - - for i := 0; i < len(population); i++ { - // Selection: Pick two parents - parent1 := selectIndividual(population) - parent2 := selectIndividual(population) - - // Crossover: Create a child - childGenome := crossover(parent1.Genome, parent2.Genome) - - // Mutation: Introduce random changes - childGenome = mutate(childGenome) - - // Add child to the next generation - nextGeneration[i] = Individual{ - Genome: childGenome, - } - } - - return nextGeneration -} - -// selectIndividual selects an individual from the population based on fitness (roulette wheel selection) -func selectIndividual(population []Individual) Individual { - totalFitness := 0.0 - for _, individual := range population { - totalFitness += individual.Fitness - } - - r := rand.Float64() * totalFitness - cumulative := 0.0 - for _, individual := range population { - cumulative += individual.Fitness - if cumulative >= r { - return individual - } - } - - return population[len(population)-1] -} - -// crossover combines two parent genomes to produce a child genome -func crossover(parent1, parent2 string) string { - child := make([]rune, len(parent1)) - cutPoint := rand.Intn(len(parent1)) - for i := 0; i < len(parent1); i++ { - if i < cutPoint { - child[i] = rune(parent1[i]) - } else { - child[i] = rune(parent2[i]) - } - } - return string(child) -} - -// mutate introduces random changes to a genome based on the mutation rate -func mutate(genome string) string { - mutated := []rune(genome) - for i := 0; i < len(mutated); i++ { - if rand.Float64() < MutationRate { - mutated[i] = Charset[rand.Intn(len(Charset))] - } - } - return string(mutated) -} From a42e6853f746ad50eb395c535c501e4943479b17 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 26 Nov 2024 22:34:12 +0900 Subject: [PATCH 6/8] fixup --- examples/gno.land/r/demo/games/ga/ga.gno | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/gno.land/r/demo/games/ga/ga.gno b/examples/gno.land/r/demo/games/ga/ga.gno index fdd3f81a091..123d9b10c44 100644 --- a/examples/gno.land/r/demo/games/ga/ga.gno +++ b/examples/gno.land/r/demo/games/ga/ga.gno @@ -1,7 +1,6 @@ package ga import ( - "fmt" "gno.land/p/demo/entropy" "math" ) From e1a9bd42869a519ce799f56c7160da078971165a Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 26 Nov 2024 22:38:09 +0900 Subject: [PATCH 7/8] fixup --- gnovm/tests/files/ga.gno | 163 --------------------------------------- 1 file changed, 163 deletions(-) delete mode 100644 gnovm/tests/files/ga.gno diff --git a/gnovm/tests/files/ga.gno b/gnovm/tests/files/ga.gno deleted file mode 100644 index d47d03b32f9..00000000000 --- a/gnovm/tests/files/ga.gno +++ /dev/null @@ -1,163 +0,0 @@ -package main - -import ( - "fmt" - "math/rand" - "time" -) - -// Individual represents a single solution in the population -type Individual struct { - Genome string - Fitness float64 -} - -// Target is the string we want to evolve -const Target = "HELLO, WORLD!" - -// MutationRate controls how often mutations occur -const MutationRate = 0.01 - -// PopulationSize defines the number of individuals in the population -const PopulationSize = 100 - -// Charset defines the possible characters in the genome -var Charset = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ, !") - -func main() { - //rand.Seed(time.Now().UnixNano()) - - // Step 1: Initialize Population - population := initializePopulation(PopulationSize) - - generation := 0 - for { - // Step 2: Calculate Fitness - for i := range population { - population[i].Fitness = calculateFitness(population[i].Genome) - } - - // Step 3: Check for Solution - best := findBestIndividual(population) - fmt.Printf("Generation %d: %s (Fitness: %f)\n", generation, best.Genome, best.Fitness) - if best.Genome == Target { - fmt.Println("Target reached!") - break - } - - // Step 4: Generate Next Generation - population = generateNextGeneration(population) - - generation++ - } -} - -// initializePopulation creates a random population of individuals -func initializePopulation(size int) []Individual { - population := make([]Individual, size) - for i := 0; i < size; i++ { - population[i] = Individual{ - Genome: randomGenome(len(Target)), - } - } - return population -} - -// randomGenome generates a random string of the same length as the target -func randomGenome(length int) string { - genome := make([]rune, length) - for i := 0; i < length; i++ { - genome[i] = Charset[rand.Intn(len(Charset))] - } - return string(genome) -} - -// calculateFitness computes how close an individual is to the target string -func calculateFitness(genome string) float64 { - matches := 0 - for i, char := range genome { - if char == rune(Target[i]) { - matches++ - } - } - return float64(matches) / float64(len(Target)) -} - -// findBestIndividual finds the individual with the highest fitness in the population -func findBestIndividual(population []Individual) Individual { - best := population[0] - for _, individual := range population { - if individual.Fitness > best.Fitness { - best = individual - } - } - return best -} - -// generateNextGeneration produces the next generation using selection, crossover, and mutation -func generateNextGeneration(population []Individual) []Individual { - nextGeneration := make([]Individual, len(population)) - - for i := 0; i < len(population); i++ { - // Selection: Pick two parents - parent1 := selectIndividual(population) - parent2 := selectIndividual(population) - - // Crossover: Create a child - childGenome := crossover(parent1.Genome, parent2.Genome) - - // Mutation: Introduce random changes - childGenome = mutate(childGenome) - - // Add child to the next generation - nextGeneration[i] = Individual{ - Genome: childGenome, - } - } - - return nextGeneration -} - -// selectIndividual selects an individual from the population based on fitness (roulette wheel selection) -func selectIndividual(population []Individual) Individual { - totalFitness := 0.0 - for _, individual := range population { - totalFitness += individual.Fitness - } - - r := rand.Float64() * totalFitness - cumulative := 0.0 - for _, individual := range population { - cumulative += individual.Fitness - if cumulative >= r { - return individual - } - } - - return population[len(population)-1] -} - -// crossover combines two parent genomes to produce a child genome -func crossover(parent1, parent2 string) string { - child := make([]rune, len(parent1)) - cutPoint := rand.Intn(len(parent1)) - for i := 0; i < len(parent1); i++ { - if i < cutPoint { - child[i] = rune(parent1[i]) - } else { - child[i] = rune(parent2[i]) - } - } - return string(child) -} - -// mutate introduces random changes to a genome based on the mutation rate -func mutate(genome string) string { - mutated := []rune(genome) - for i := 0; i < len(mutated); i++ { - if rand.Float64() < MutationRate { - mutated[i] = Charset[rand.Intn(len(Charset))] - } - } - return string(mutated) -} From 199afea8630813d104f129abe96b1a9db1500639 Mon Sep 17 00:00:00 2001 From: ltzMaxwell Date: Tue, 26 Nov 2024 22:40:34 +0900 Subject: [PATCH 8/8] fixup --- examples/gno.land/r/demo/games/ga/ga.gno | 3 ++- examples/gno.land/r/demo/games/ga/z0_filetest.gno | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/r/demo/games/ga/ga.gno b/examples/gno.land/r/demo/games/ga/ga.gno index 123d9b10c44..ed2476827bc 100644 --- a/examples/gno.land/r/demo/games/ga/ga.gno +++ b/examples/gno.land/r/demo/games/ga/ga.gno @@ -1,8 +1,9 @@ package ga import ( - "gno.land/p/demo/entropy" "math" + + "gno.land/p/demo/entropy" ) // Individual represents a single solution in the population diff --git a/examples/gno.land/r/demo/games/ga/z0_filetest.gno b/examples/gno.land/r/demo/games/ga/z0_filetest.gno index 2db27190877..fb21f9ab8f0 100644 --- a/examples/gno.land/r/demo/games/ga/z0_filetest.gno +++ b/examples/gno.land/r/demo/games/ga/z0_filetest.gno @@ -1,11 +1,8 @@ package main import ( - "std" - "gno.land/p/demo/entropy" "gno.land/r/demo/games/ga" - "strconv" ) func main() { @@ -13,7 +10,6 @@ func main() { r := entropy.New() gen, target := ga.Start(r) - //println("found " + target + " in " + strconv.Itoa(gen) + " generation") } // Output: