You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遗传算法优化中出现IndexError索引越界问题的解决咨询

Fixing IndexError in Genetic Algorithm Implementation

Hey there! Let's break down why you're hitting this IndexError and fix it step by step.

What's Causing the Error?

The root issue is that your fitness_array function hardcodes the loop to run population_size times (which is 5), but as your algorithm runs, the new_population array can end up smaller than 5 elements.

Here's the breakdown: In your generation loop, when return_crossovered_child returns 0 (which happens when the random number is >= crossover_rate), you use continue and don't add anything to last_population. Over time, this can lead to new_population having fewer than 5 rows, but fitness_array still tries to access indices 0-4 regardless. When new_population only has 4 elements, accessing index 4 triggers the error you see.

Fix Steps

Let's address this with three key fixes:

  1. Make fitness_array use the actual population size instead of the constant
    Replace the hardcoded population_size in the loop with population.shape[0] (the actual number of rows in the population array). This ensures you only iterate over existing elements.

    Modified fitness_array function:

    def fitness_array(population):
        fitness_array = []
        # Use the actual length of the population, not the constant
        for i in range(population.shape[0]):
            fitness_array.append(summation(population[i,0], population[i,1]))
        return np.array(fitness_array)
    
  2. Ensure last_population always reaches the desired population size
    Right now, if some crossover attempts return 0, you're missing elements in last_population. We need to keep generating children until we have exactly population_size elements.

    Update the generation loop's inner part:

    for i in range(generation):
        mate_pool = return_ranked_selected_population(new_population)
        last_population = []
        # Keep adding children until we reach the desired population size
        while len(last_population) < population_size:
            crossed_child = return_crossovered_child(mate_pool)
            if crossed_child != 0:
                mutated_child = return_mutated_child(crossed_child)
                last_population.append(mutated_child)
        new_population = np.array(last_population)
        a, b = return_best_worst_population(new_population)
        print('generation', i, "best", a, "fitness", b)
    
  3. Clean up return_best_worst_population for robustness
    The original sorting logic works, but we can make it more readable and ensure it handles variable population sizes correctly:

    def return_best_worst_population(population):
        fitness_array1 = fitness_array(population)
        new_population = np.zeros(population.shape)
        new_fitness_array = np.zeros(fitness_array1.shape)
        # Sort indices from worst to best, then reverse for best to worst order
        best_indices = np.argsort(fitness_array1)[::-1]
        for row_counter, idx in enumerate(best_indices):
            new_population[row_counter, :] = population[idx, :]
            new_fitness_array[row_counter] = fitness_array1[idx]
        return new_population[0], new_fitness_array[0]
    

Why These Fixes Work

  • The first fix ensures your fitness calculation never tries to access indices that don't exist, since it uses the actual current population size.
  • The second fix guarantees that new_population always has exactly population_size elements, so you never end up with a smaller array that causes index issues.
  • The third fix cleans up the sorting logic to be more maintainable while keeping its original purpose of returning the best individual.

Full Modified Code (Key Sections Updated)

Here's the full code with all fixes applied:

import numpy as np
import itertools
import random

population_size = 5
chromosome_size = 2
geneset1 = [7,9,19,23,25,27,31]
geneset2 = [2,78,46,68,34,24,12]
mutation_rate = 0.1
crossover_rate = 0.95
generation = 24

def summation(a,b):
    return a+b

# Fixed fitness function using actual population size
def fitness_array(population):
    fitness_array = []
    for i in range(population.shape[0]):
        fitness_array.append(summation(population[i,0], population[i,1]))
    return np.array(fitness_array)

def return_random_population(geneset1, geneset2, population_size):
    population = random.sample(set(itertools.product(geneset1, geneset2)), population_size)
    return np.array(population)

# Cleaned up best/worst sorting
def return_best_worst_population(population):
    fitness_array1 = fitness_array(population)
    new_population = np.zeros(population.shape)
    new_fitness_array = np.zeros(fitness_array1.shape)
    best_indices = np.argsort(fitness_array1)[::-1]
    for row_counter, idx in enumerate(best_indices):
        new_population[row_counter, :] = population[idx, :]
        new_fitness_array[row_counter] = fitness_array1[idx]
    return new_population[0], new_fitness_array[0]

def return_ranked_selected_population(population):
    ranked_population = []
    fitness_of_given_population = fitness_array(population)
    sort = np.argsort(fitness_of_given_population)
    rank_population = np.zeros(fitness_of_given_population.shape)
    x = 1
    for i in sort:
        rank_population[i] = x
        x += 1
    fitness_score = [(x/sum(rank_population)) for x in rank_population]
    for i in range(len(fitness_score)):
        n = int(fitness_score[i]*100)
        for j in range(n):
            ranked_population.append(population[i])
    return ranked_population

def return_crossovered_child(ranked_selected_population):
    if np.random.random() < crossover_rate:
        a = np.random.randint(0, len(ranked_selected_population))
        b = np.random.randint(0, len(ranked_selected_population))
        parent1 = ranked_selected_population[a]
        parent2 = ranked_selected_population[b]
        slicing_point = np.random.randint(0, chromosome_size)
        child = list(parent1[:slicing_point]) + list(parent2[slicing_point:])
        return child
    return 0

def return_mutated_child(crossovered_child):
    for i in range(chromosome_size):
        if np.random.random() < mutation_rate:
            if i == 0:
                crossovered_child[i] = np.random.choice(geneset1)
            else:
                crossovered_child[i] = np.random.choice(geneset2)
    return crossovered_child

# Initial population setup
new_population = return_random_population(geneset1, geneset2, population_size)
a, b = return_best_worst_population(new_population)
print("best", a, "fitness", b)

# Fixed generation loop ensuring population size stays consistent
for i in range(generation):
    mate_pool = return_ranked_selected_population(new_population)
    last_population = []
    while len(last_population) < population_size:
        crossed_child = return_crossovered_child(mate_pool)
        if crossed_child != 0:
            mutated_child = return_mutated_child(crossed_child)
            last_population.append(mutated_child)
    new_population = np.array(last_population)
    a, b = return_best_worst_population(new_population)
    print('generation', i, "best", a, "fitness", b)

Give this a run, and you should no longer hit that IndexError. The algorithm will maintain a consistent population size through all generations, and the fitness calculation will always work with the actual number of individuals present.

内容的提问来源于stack exchange,提问作者rafe zayed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:24:00