ceandrade / brkga_mp_ipr_python

The Multi-Parent Biased Random-Key Genetic Algorithm with Implict Path Relink - Python version
Other
19 stars 6 forks source link

get_best_chromosome() returns incorrect result #4

Open AlexanderTreml opened 1 month ago

AlexanderTreml commented 1 month ago

The fitness of the chromosome returned from get_best_chromosome() sometimes does not match the fitness returned by get_best_fitness(). This is because the index structure is not maintained in the lines 680-683 of "algorithm.py". Elite chromosomes are copied to the top of the chromosomes list. But the indices of the elite chromosomes in the fitness data structure are not updated.

The following code should reproduce the issue, when executed with the config file given below:

from brkga_mp_ipr.types import BaseChromosome
from brkga_mp_ipr.enums import Sense
from brkga_mp_ipr.types_io import load_configuration
from brkga_mp_ipr.algorithm import BrkgaMpIpr

"""
    This showcases a bug in the brkga_mp_ipr framework,
    where get_best_fitness() does not correspond to get_best_chromosome().
"""

class Decoder:

    def decode(self, chromosome: BaseChromosome, rewrite: bool) -> float:
        return sum(chromosome)

seed = 0
configuration_file = "config.conf"
num_generations = 20
decoder = Decoder()
brkga_params, _ = load_configuration(configuration_file)

brkga = BrkgaMpIpr(
    decoder=decoder,
    sense=Sense.MINIMIZE,
    seed=seed,
    chromosome_size=3,
    params=brkga_params
)

brkga.initialize()

brkga.evolve(num_generations)

best_cost = brkga.get_best_fitness()
best_sol = brkga.get_best_chromosome()
best_sol_cost = decoder.decode(best_sol, False)

print(f"Best cost: {best_cost}")
print(f"Best solution: {best_sol}")
print(f"Best solution cost: {best_sol_cost}")
print("Best cost does not match the cost of the best solution!")
print("")
print("The fitness structure is built incorrectly:")
for c in brkga._current_populations[0].fitness:
    print(c)
###############################################################################
# config.conf: example of a configuration file for BRKGA-MP-IPR frameworks.
#
# (c) Copyright 2019, Carlos Eduardo de Andrade. All Rights Reserved.
#
# This code is released under LICENSE.md.
#
# Created on:  Dec 28, 2018 by ceandrade
# Last update: Jan 09, 2019 by ceandrade
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###############################################################################

# Population size
population_size 10

# Elite percentage
elite_percentage 0.30

# Mutants percentage
mutants_percentage 0.15

# Number of elite parents to mate
num_elite_parents 2

# Total number of parents to mate
total_parents 3

# Bias function to be used to rank the parents
bias_type LOGINVERSE

# Number of independent populations
num_independent_populations 1

# Number of pairs of chromosomes to be tested to path relinking.
pr_number_pairs 0

# Mininum distance between chromosomes to path-relink
pr_minimum_distance 0.15

# Path relink type
pr_type PERMUTATION

# Individual selection to path-relink
pr_selection BESTSOLUTION

# Defines the block size based on the size of the population
alpha_block_size 1.0

# Percentage/path size
pr_percentage 1.0

# Interval at which elite chromosomes are exchanged (0 means no exchange)
exchange_interval 200

# Number of elite chromosomes exchanged from each population
num_exchange_indivuduals 2

# Interval at which the populations are reset (0 means no reset)
reset_interval 600
ceandrade commented 1 month ago

Thanks for reporting @AlexanderTreml. Indeed, the Python version of BRKGA-IPR is not well-tested and lags behind the C++ version, so it is nice when these bugs come around.

However, I do not intend to fix this any time soon. Please feel free to submit a patch via PR request. I will be glad to add you as a collaborator in this project.

AlexanderTreml commented 1 month ago

Actually, I noticed that the code was already fixed with #1. It's just the version installed by pip that still uses the erroneous code.