def setUp(self):
        """
        Sets up some configurations.
        """

        Test.maxDiff = None

        self.chromosome_size = 100

        self.default_brkga_params = BrkgaParams()
        self.default_brkga_params.population_size = 10
        self.default_brkga_params.elite_percentage = 0.3
        self.default_brkga_params.mutants_percentage = 0.1
        self.default_brkga_params.num_elite_parents = 1
        self.default_brkga_params.total_parents = 2
        self.default_brkga_params.bias_type = BiasFunctionType.LOGINVERSE
        self.default_brkga_params.num_independent_populations = 3
        self.default_brkga_params.pr_number_pairs = 0
        self.default_brkga_params.pr_minimum_distance = 0.0
        self.default_brkga_params.pr_type = PathRelinkingType.DIRECT
        self.default_brkga_params.pr_selection = PathRelinkingSelection.BESTSOLUTION
        self.default_brkga_params.alpha_block_size = 1.0
        self.default_brkga_params.pr_percentage = 1.0

        self.instance = Instance(self.chromosome_size)
        self.sum_decoder = SumDecode(self.instance)
        self.rank_decoder = RankDecode(self.instance)

        self.default_param_values = {
            "decoder": self.sum_decoder,
            "sense": Sense.MAXIMIZE,
            "seed": 98747382473209,
            "chromosome_size": self.chromosome_size,
            "params": self.default_brkga_params,
            "evolutionary_mechanism_on": True,
            "chrmosome_type": BaseChromosome
        }
class Test(unittest.TestCase):
    """
    Test units for types.
    """

    ###########################################################################

    def setUp(self):
        """
        Sets up some configurations.
        """

        Test.maxDiff = None

        self.chromosome_size = 100

        self.default_brkga_params = BrkgaParams()
        self.default_brkga_params.population_size = 10
        self.default_brkga_params.elite_percentage = 0.3
        self.default_brkga_params.mutants_percentage = 0.1
        self.default_brkga_params.num_elite_parents = 1
        self.default_brkga_params.total_parents = 2
        self.default_brkga_params.bias_type = BiasFunctionType.LOGINVERSE
        self.default_brkga_params.num_independent_populations = 3
        self.default_brkga_params.pr_number_pairs = 0
        self.default_brkga_params.pr_minimum_distance = 0.0
        self.default_brkga_params.pr_type = PathRelinkingType.DIRECT
        self.default_brkga_params.pr_selection = PathRelinkingSelection.BESTSOLUTION
        self.default_brkga_params.alpha_block_size = 1.0
        self.default_brkga_params.pr_percentage = 1.0

        self.instance = Instance(self.chromosome_size)
        self.sum_decoder = SumDecode(self.instance)
        self.rank_decoder = RankDecode(self.instance)

        self.default_param_values = {
            "decoder": self.sum_decoder,
            "sense": Sense.MAXIMIZE,
            "seed": 98747382473209,
            "chromosome_size": self.chromosome_size,
            "params": self.default_brkga_params,
            "evolutionary_mechanism_on": True,
            "chrmosome_type": BaseChromosome
        }

    ###########################################################################

    def test_get_best_fitness(self):
        """
        Tests get_best_fitness() method.
        """

        param_values = deepcopy(self.default_param_values)
        param_values["sense"] = Sense.MAXIMIZE
        param_values["seed"] = 12323
        param_values["chromosome_size"] = self.chromosome_size
        param_values["params"].population_size = 500
        param_values["params"].num_independent_populations = 3

        params = param_values["params"]
        brkga = BrkgaMpIpr(**param_values)

        # Not initialized
        with self.assertRaises(RuntimeError) as context:
            brkga.get_best_fitness()
        self.assertEqual(str(context.exception).strip(),
                         "The algorithm hasn't been initialized. "
                         "Call 'initialize()' before 'get_best_fitness()'")

        brkga.initialize()

        ########################
        # Test for maximization
        ########################

        local_rng = Random(param_values["seed"])
        for _ in range(1000):
            local_rng.random()

        num_individuals = params.population_size * \
                          params.num_independent_populations

        best_value = -math.inf
        for _ in range(num_individuals):
            local_chr = BaseChromosome([
                local_rng.random() for _ in range(param_values["chromosome_size"])
            ])
            best_value = max(
                best_value, self.sum_decoder.decode(local_chr, True)
            )

        # Assert the both generators are in the same state.
        self.assertEqual(brkga._rng.getstate(), local_rng.getstate())

        # Test the actual value.
        self.assertAlmostEqual(brkga.get_best_fitness(), best_value)

        ########################
        # Test for minimization
        ########################

        param_values["sense"] = Sense.MINIMIZE
        brkga = BrkgaMpIpr(**param_values)
        brkga.initialize()

        local_rng = Random(param_values["seed"])
        for _ in range(1000):
            local_rng.random()

        num_individuals = params.population_size * \
                          params.num_independent_populations

        best_value = math.inf
        for _ in range(num_individuals):
            local_chr = BaseChromosome([
                local_rng.random() for _ in range(param_values["chromosome_size"])
            ])
            best_value = min(
                best_value, self.sum_decoder.decode(local_chr, True)
            )

        # Assert the both generators are in the same state.
        self.assertEqual(brkga._rng.getstate(), local_rng.getstate())

        # Test the actual value.
        self.assertAlmostEqual(brkga.get_best_fitness(), best_value)

    ###########################################################################

    def test_get_best_chromosome(self):
        """
        Tests get_best_chromosome() method.
        """

        param_values = deepcopy(self.default_param_values)
        param_values["sense"] = Sense.MAXIMIZE
        param_values["seed"] = 12323
        param_values["chromosome_size"] = self.chromosome_size
        param_values["params"].population_size = 500
        param_values["params"].num_independent_populations = 3

        params = param_values["params"]
        brkga = BrkgaMpIpr(**param_values)

        # Not initialized
        with self.assertRaises(RuntimeError) as context:
            brkga.get_best_chromosome()
        self.assertEqual(str(context.exception).strip(),
                         "The algorithm hasn't been initialized. "
                         "Call 'initialize()' before 'get_best_chromosome()'")

        brkga.initialize()

        ########################
        # Test for maximization
        ########################

        local_rng = Random(param_values["seed"])
        for _ in range(1000):
            local_rng.random()

        num_individuals = params.population_size * \
                          params.num_independent_populations

        best_value = -math.inf
        best_chr = None
        for _ in range(num_individuals):
            local_chr = BaseChromosome([
                local_rng.random() for _ in range(param_values["chromosome_size"])
            ])
            value = self.sum_decoder.decode(local_chr, True)
            if best_value < value:
                best_value = value
                best_chr = local_chr
        # end for

        # Assert the both generators are in the same state.
        self.assertEqual(brkga._rng.getstate(), local_rng.getstate())

        # Test the actual value.
        self.assertEqual(brkga.get_best_chromosome(), best_chr)

        ########################
        # Test for minimization
        ########################

        param_values["sense"] = Sense.MINIMIZE
        brkga = BrkgaMpIpr(**param_values)
        brkga.initialize()

        local_rng = Random(param_values["seed"])
        for _ in range(1000):
            local_rng.random()

        num_individuals = params.population_size * \
                          params.num_independent_populations

        best_value = math.inf
        best_chr = None
        for _ in range(num_individuals):
            local_chr = BaseChromosome([
                local_rng.random() for _ in range(param_values["chromosome_size"])
            ])
            value = self.sum_decoder.decode(local_chr, True)
            if best_value > value:
                best_value = value
                best_chr = local_chr
        # end for

        # Assert the both generators are in the same state.
        self.assertEqual(brkga._rng.getstate(), local_rng.getstate())

        # Test the actual value.
        self.assertEqual(brkga.get_best_chromosome(), best_chr)

    ###########################################################################

    def test_get_chromosome(self):
        """
        Tests get_chromosome() method.
        """

        param_values = deepcopy(self.default_param_values)
        param_values["params"].num_independent_populations = 3
        params = param_values["params"]
        brkga = BrkgaMpIpr(**param_values)

        # Not initialized
        with self.assertRaises(RuntimeError) as context:
            brkga.get_chromosome(0, 0)
        self.assertEqual(str(context.exception).strip(),
                         "The algorithm hasn't been initialized. "
                         "Call 'initialize()' before 'get_chromosome()'")

        brkga.initialize()

        # Test invalid population indices.
        population_index = -1
        position = 0
        with self.assertRaises(ValueError) as context:
            brkga.get_chromosome(population_index, position)
        self.assertEqual(str(context.exception).strip(),
                         "Population must be in [0, 2]: -1")

        population_index = brkga.params.num_independent_populations
        position = 0
        with self.assertRaises(ValueError) as context:
            brkga.get_chromosome(population_index, position)
        self.assertEqual(str(context.exception).strip(),
                         "Population must be in [0, 2]: 3")

        # Test invalid chrmosome indices.
        population_index = 0
        position = -1
        with self.assertRaises(ValueError) as context:
            brkga.get_chromosome(population_index, position)
        self.assertEqual(str(context.exception).strip(),
                         "Chromosome position must be in [0, 9]: -1")

        population_index = 0
        position = brkga.params.population_size
        with self.assertRaises(ValueError) as context:
            brkga.get_chromosome(population_index, position)
        self.assertEqual(str(context.exception).strip(),
                         "Chromosome position must be in [0, 9]: 10")

        # Test if the chromosome matches.

        # Create a local RNG and advance it until the same state as the
        # internal BRKGA RNG after initialization.
        local_rng = Random(param_values["seed"])
        skip = 1000
        for _ in range(skip):
            local_rng.random()

        # Now, we create the populations, decode them, and sort the
        # individuals according to their fitness, reproducing initialize()
        # basically.
        local_populations = []
        for _ in range(brkga.params.num_independent_populations):
            population = []
            for _ in range(brkga.params.population_size):
                local_chr = BaseChromosome([
                    local_rng.random() for _ in range(param_values["chromosome_size"])
                ])

                fitness = brkga._decoder.decode(local_chr, True)
                population.append((fitness, local_chr))
            # end for
            population.sort(reverse=(brkga.opt_sense == Sense.MAXIMIZE))
            local_populations.append(population)
        # end for

        # Assert the both generators are in the same state.
        self.assertEqual(brkga._rng.getstate(), local_rng.getstate())

        population_index = 0
        position = 0
        copy_chr = brkga.get_chromosome(population_index, position)
        self.assertEqual(copy_chr, local_populations[population_index][position][1])
        self.assertIsNot(copy_chr, local_populations[population_index][position][1])

        population_index = 1
        position = 1
        copy_chr = brkga.get_chromosome(population_index, position)
        self.assertEqual(copy_chr, local_populations[population_index][position][1])
        self.assertIsNot(copy_chr, local_populations[population_index][position][1])

        population_index = brkga.params.num_independent_populations - 1
        position = brkga.params.population_size - 1
        copy_chr = brkga.get_chromosome(population_index, position)
        self.assertEqual(copy_chr, local_populations[population_index][position][1])
        self.assertIsNot(copy_chr, local_populations[population_index][position][1])

    ###########################################################################

    def test_get_current_population(self):
        """
        Tests get_current_population() method.
        """

        param_values = deepcopy(self.default_param_values)
        param_values["params"].num_independent_populations = 3
        params = param_values["params"]
        brkga = BrkgaMpIpr(**param_values)

        # Not initialized
        with self.assertRaises(RuntimeError) as context:
            brkga.get_current_population()
        self.assertEqual(str(context.exception).strip(),
                         "The algorithm hasn't been initialized. "
                         "Call 'initialize()' before 'get_current_population()'")

        brkga.initialize()

         # Test invalid population indices.
        population_index = -1
        with self.assertRaises(ValueError) as context:
            brkga.get_current_population(population_index)
        self.assertEqual(str(context.exception).strip(),
                         "Population must be in [0, 2]: -1")

        population_index = brkga.params.num_independent_populations
        with self.assertRaises(ValueError) as context:
            brkga.get_current_population(population_index)
        self.assertEqual(str(context.exception).strip(),
                         "Population must be in [0, 2]: 3")

        # Test if it is returning the right population.
        for i in range(params.num_independent_populations):
            self.assertIs(brkga.get_current_population(i),
                          brkga._current_populations[i])
def gen_conf5():
    param_values = deepcopy(default_param_values)
    brkga_params = param_values["params"]

    chromosome_size = 100
    instance = Instance(chromosome_size)

    brkga_params.population_size = 100
    brkga_params.elite_percentage = 0.30
    brkga_params.mutants_percentage = 0.20
    brkga_params.num_elite_parents = 2
    brkga_params.total_parents = 3
    brkga_params.bias_type = BiasFunctionType.LOGINVERSE
    brkga_params.num_independent_populations = 3
    brkga_params.pr_number_pairs = 0
    brkga_params.pr_minimum_distance = 0.0
    brkga_params.pr_type = PathRelinkingType.DIRECT
    brkga_params.pr_selection = PathRelinkingSelection.BESTSOLUTION
    brkga_params.alpha_block_size = 1.0
    brkga_params.pr_percentage = 1.0

    param_values["decoder"] = SumDecode(instance)
    param_values["sense"] = Sense.MINIMIZE
    param_values["seed"] = 4659930950303
    param_values["chromosome_size"] = chromosome_size
    param_values["evolutionary_mechanism_on"] = True

    print("\n> Building configuration 5")
    brkga = BrkgaMpIpr(**param_values)
    brkga.initialize()

    print("> Writing configuration 5")
    with open(os.path.join(STATE_DIR, "state5.pickle"), "wb") as hd:
        pickle.dump(brkga, hd)

    print("> Evolving one generation...")
    brkga.evolve()
    fitness1 = brkga.get_best_fitness()
    chromosome1 = brkga.get_best_chromosome()

    print("> Evolving 10 generations...")
    brkga.evolve(10)
    fitness10 = brkga.get_best_fitness()
    chromosome10 = brkga.get_best_chromosome()

    print("> Evolving 100 generations...")
    brkga.evolve(100)
    fitness100 = brkga.get_best_fitness()
    chromosome100 = brkga.get_best_chromosome()

    with open(os.path.join(SOLUTION_DIR, "best_solution5.pickle"), "wb") as hd:
        pickle.dump(
            {
                "fitness1": fitness1,
                "chromosome1": chromosome1,
                "fitness10": fitness10,
                "chromosome10": chromosome10,
                "fitness100": fitness100,
                "chromosome100": chromosome100
            },
            hd
        )

    print("fitness", fitness1)
    print("fitness", fitness10)
    print("fitness", fitness100)
def gen_conf4():
    param_values = deepcopy(default_param_values)
    brkga_params = param_values["params"]

    chromosome_size = 500
    instance = Instance(chromosome_size)

    brkga_params.population_size = 100
    brkga_params.elite_percentage = 0.35
    brkga_params.mutants_percentage = 0.15
    brkga_params.num_elite_parents = 1
    brkga_params.total_parents = 2
    brkga_params.bias_type = BiasFunctionType.EXPONENTIAL
    brkga_params.num_independent_populations = 3
    brkga_params.pr_number_pairs = 0
    brkga_params.pr_minimum_distance = 0.0
    brkga_params.pr_type = PathRelinkingType.DIRECT
    brkga_params.pr_selection = PathRelinkingSelection.BESTSOLUTION
    brkga_params.alpha_block_size = 1.0
    brkga_params.pr_percentage = 1.0

    param_values["decoder"] = SumDecode(instance)
    param_values["sense"] = Sense.MINIMIZE
    param_values["seed"] = 2947804214761
    param_values["chromosome_size"] = chromosome_size
    param_values["evolutionary_mechanism_on"] = True

    print("\n> Building configuration 4")
    brkga = BrkgaMpIpr(**param_values)
    brkga.initialize()

    rho = 0.75
    brkga.set_bias_custom_function(lambda x: rho if x == 1 else 1.0 - rho)

    print("> Writing configuration 4")
    with open(os.path.join(STATE_DIR, "state4.pickle"), "wb") as hd:
        pickle.dump(brkga, hd)

    print("> Evolving population 0...")
    brkga.evolve_population(0)
    fitness1 = brkga.get_best_fitness()
    chromosome1 = brkga.get_best_chromosome()

    print("> Evolving population 1...")
    brkga.evolve_population(1)
    fitness2 = brkga.get_best_fitness()
    chromosome2 = brkga.get_best_chromosome()

    print("> Evolving population 2...")
    brkga.evolve_population(2)
    fitness3 = brkga.get_best_fitness()
    chromosome3 = brkga.get_best_chromosome()

    print("> Evolving both populations for 100 generations...")
    for _ in range(100):
        start_time = time()
        brkga.evolve_population(0)
        brkga.evolve_population(1)
        brkga.evolve_population(2)
        print(f"Elapsed time: {time() - start_time :.2f}")

    fitness103 = brkga.get_best_fitness()
    chromosome103 = brkga.get_best_chromosome()

    with open(os.path.join(SOLUTION_DIR, "best_solution4.pickle"), "wb") as hd:
        pickle.dump(
            {
                "fitness1": fitness1,
                "chromosome1": chromosome1,
                "fitness2": fitness2,
                "chromosome2": chromosome2,
                "fitness3": fitness2,
                "chromosome3": chromosome2,
                "fitness103": fitness103,
                "chromosome103": chromosome103,
            },
            hd
        )
def gen_conf3():
    param_values = deepcopy(default_param_values)
    brkga_params = param_values["params"]

    chromosome_size = 500
    instance = Instance(chromosome_size)

    brkga_params.population_size = 100
    brkga_params.elite_percentage = 0.35
    brkga_params.mutants_percentage = 0.17
    brkga_params.num_elite_parents = 3
    brkga_params.total_parents = 5
    brkga_params.bias_type = BiasFunctionType.EXPONENTIAL
    brkga_params.num_independent_populations = 5
    brkga_params.pr_number_pairs = 0
    brkga_params.pr_minimum_distance = 0.0
    brkga_params.pr_type = PathRelinkingType.DIRECT
    brkga_params.pr_selection = PathRelinkingSelection.BESTSOLUTION
    brkga_params.alpha_block_size = 1.0
    brkga_params.pr_percentage = 1.0

    param_values["decoder"] = SumDecode(instance)
    param_values["sense"] = Sense.MINIMIZE
    param_values["seed"] = 253624607406
    param_values["chromosome_size"] = chromosome_size
    param_values["evolutionary_mechanism_on"] = True

    print("\n> Building configuration 3")
    brkga = BrkgaMpIpr(**param_values)
    brkga.initialize()

    print("> Writing configuration 3")
    with open(os.path.join(STATE_DIR, "state3.pickle"), "wb") as hd:
        pickle.dump(brkga, hd)

    print("> Evolving both populations for one generation...")
    for i in range(brkga_params.num_independent_populations):
        brkga.evolve_population(i)
    fitness1 = brkga.get_best_fitness()
    chromosome1 = brkga.get_best_chromosome()

    print("> Evolving both populations for another generation...")
    for i in range(brkga_params.num_independent_populations):
        brkga.evolve_population(i)
    brkga.evolve_population(1)
    fitness2 = brkga.get_best_fitness()
    chromosome2 = brkga.get_best_chromosome()

    print("> Evolving both populations for 100 generations...")
    for _ in range(100):
        start_time = time()
        for i in range(brkga_params.num_independent_populations):
            brkga.evolve_population(i)
        print(f"Elapsed time: {time() - start_time :.2f}")

    fitness102 = brkga.get_best_fitness()
    chromosome102 = brkga.get_best_chromosome()

    with open(os.path.join(SOLUTION_DIR, "best_solution3.pickle"), "wb") as hd:
        pickle.dump(
            {
                "fitness1": fitness1,
                "chromosome1": chromosome1,
                "fitness2": fitness2,
                "chromosome2": chromosome2,
                "fitness102": fitness102,
                "chromosome102": chromosome102,
            },
            hd
        )

    print("fitness", fitness1)
    # print("chromosome", chromosome1)

    print("fitness", fitness2)
    # print("chromosome", chromosome2)

    print("fitness", fitness102)
default_brkga_params.population_size = 10
default_brkga_params.elite_percentage = 0.3
default_brkga_params.mutants_percentage = 0.1
default_brkga_params.num_elite_parents = 1
default_brkga_params.total_parents = 2
default_brkga_params.bias_type = BiasFunctionType.LOGINVERSE
default_brkga_params.num_independent_populations = 3
default_brkga_params.pr_number_pairs = 0
default_brkga_params.pr_minimum_distance = 0.0
default_brkga_params.pr_type = PathRelinkingType.DIRECT
default_brkga_params.pr_selection = PathRelinkingSelection.BESTSOLUTION
default_brkga_params.alpha_block_size = 1.0
default_brkga_params.pr_percentage = 1.0

instance = Instance(chromosome_size)
sum_decoder = SumDecode(instance)
rank_decoder = RankDecode(instance)

default_param_values = {
    "decoder": sum_decoder,
    "sense": Sense.MAXIMIZE,
    "seed": 98747382473209,
    "chromosome_size": chromosome_size,
    "params": default_brkga_params,
    "evolutionary_mechanism_on": True,
    "chrmosome_type": BaseChromosome
}

###############################################################################
# Configuration 1
###############################################################################