implement roulette selection for lower selection pressure
This commit is contained in:
@@ -5,14 +5,17 @@ import "core:container/bit_array"
|
||||
Chromosome :: ^bit_array.Bit_Array
|
||||
Population :: [POPULATION_SIZE]Chromosome
|
||||
|
||||
POPULATION_SIZE :: 100
|
||||
POPULATION_SIZE :: 1000
|
||||
GENERATIONS :: 100
|
||||
TOURNAMENT_SIZE :: 5
|
||||
CROSSOVER_RATE :: 0.8
|
||||
MUTATION_RATE :: 0.05
|
||||
POPULATION_SIZE :: 1000
|
||||
ELITISM_COUNT :: 10
|
||||
SKEW :: 0
|
||||
TOURNAMENT_SIZE :: 100
|
||||
CROSSOVER_RATE :: 0.7
|
||||
MUTATION_RATE :: 0.015
|
||||
RANDOM_SEED :: u64(42)
|
||||
OUTPUT_FILE :: "output/data.csv"
|
||||
ELITISM_COUNT :: 2
|
||||
ELITISM_COUNT :: 50
|
||||
|
||||
Problem :: struct {
|
||||
name: string,
|
||||
|
||||
44
src/ga.odin
44
src/ga.odin
@@ -102,6 +102,46 @@ tournament_selection :: proc(pop: ^Population, fitnesses: []f64, maximize: bool)
|
||||
return pop[best_idx]
|
||||
}
|
||||
|
||||
roulette_selection :: proc(pop: ^Population, fitnesses: []f64, maximize: bool) -> Chromosome {
|
||||
adjusted_fitnesses := make([]f64, len(fitnesses), context.temp_allocator)
|
||||
defer delete(adjusted_fitnesses, context.temp_allocator)
|
||||
|
||||
min_fitness := fitnesses[0]
|
||||
if !maximize {
|
||||
for f in fitnesses {
|
||||
min_fitness = min(min_fitness, f)
|
||||
}
|
||||
}
|
||||
|
||||
total_fitness: f64 = 0
|
||||
for i in 0..<len(fitnesses) {
|
||||
if maximize {
|
||||
adjusted_fitnesses[i] = max(fitnesses[i], 0)
|
||||
} else {
|
||||
// for minimization: invert so smaller values get higher probability
|
||||
adjusted_fitnesses[i] = max(min_fitness - fitnesses[i] + 1e-6, 0)
|
||||
}
|
||||
total_fitness += adjusted_fitnesses[i]
|
||||
}
|
||||
|
||||
if total_fitness <= 0 {
|
||||
return pop[rand.int_max(POPULATION_SIZE)]
|
||||
}
|
||||
|
||||
spin := rand.float64() * total_fitness
|
||||
cumulative: f64 = 0
|
||||
|
||||
for i in 0..<len(adjusted_fitnesses) {
|
||||
cumulative += adjusted_fitnesses[i]
|
||||
if cumulative >= spin {
|
||||
return pop[i]
|
||||
}
|
||||
}
|
||||
|
||||
return pop[len(pop) - 1]
|
||||
}
|
||||
|
||||
|
||||
two_point_crossover :: proc(parent1, parent2: Chromosome) -> (Chromosome, Chromosome) {
|
||||
size := bit_array.len(parent1)
|
||||
point1 := rand.int_max(size)
|
||||
@@ -172,8 +212,8 @@ create_offspring :: proc(pop: ^Population, fitnesses: []f64, maximize: bool) ->
|
||||
}
|
||||
|
||||
for i := ELITISM_COUNT; i < POPULATION_SIZE; i += 2 {
|
||||
parent1 := tournament_selection(pop, fitnesses, maximize)
|
||||
parent2 := tournament_selection(pop, fitnesses, maximize)
|
||||
parent1 := roulette_selection(pop, fitnesses, maximize)
|
||||
parent2 := roulette_selection(pop, fitnesses, maximize)
|
||||
|
||||
child1, child2 := uniform_crossover(parent1, parent2)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import "base:runtime"
|
||||
|
||||
main :: proc() {
|
||||
// Choose problem
|
||||
problem_type := "feature_selection" // or "knapsack"
|
||||
problem_type := "knapsack" // or "knapsack"
|
||||
|
||||
// state := rand.create(RANDOM_SEED)
|
||||
// context.random_generator = runtime.default_random_generator(&state)
|
||||
|
||||
Reference in New Issue
Block a user