def test_fitness(self):
        """Test fitness computation."""
        family_size = 126
        n_days = 11
        df_families = get_df_families(n_days, family_size)
        df_families.iloc[0]['n_people'] += 1
        families = np.array([i for i in range(1, n_days + 1)])
        days = {i: family_size for i in range(n_days)}
        days[0] += 1

        expected_fitness = 50 * 2 + 100 + 200 * 2 + 300 * 2 + 400 + 500 * 2
        expected_fitness += (9 * 3 + 18 * 2 + 36 * 4 + 199 + 398) * family_size
        expected_fitness += 1 / 400. * family_size ** (1 / 2.) * (n_days - 1)
        expected_fitness += 2 / 400. * (family_size + 1) ** (1 / 2. + 1 / 50.)

        antibody = Antibody(families=families, days=days)
        antibody.fitness(df_families)

        self.assertAlmostEqual(
            antibody.fitness_value,
            expected_fitness,
            places=7,
            msg=f'Fitness of antibody is `{antibody.fitness_value}`, expected '
                f'`{expected_fitness}`.'
        )
    def test_generate_solution(self):
        """Test random solution generating."""
        expected_min_day_size = 125
        expected_max_day_size = 300
        real_data_path = 'data/family_data.csv'

        dfs = [get_df_families(1000, 20)]
        if os.path.isfile(real_data_path):
            dfs.append(pd.read_csv(real_data_path))

        for df_families in dfs:
            antibody = Antibody()
            antibody.generate_solution(df_families)

            day_sizes = {}
            for i, day in enumerate(antibody.families):
                value = day_sizes.get(day, 0)
                day_sizes[day] = value + df_families.iloc[i]['n_people']

            for key, size in antibody.days.items():
                expected_day_size = day_sizes[key]
                self.assertTrue(
                    expected_min_day_size <= size <= expected_max_day_size,
                    msg=f'Number of people scheduled for `{key + 1}th` day is '
                        f'`{size}`, expected to be '
                        f'in `<{expected_min_day_size}, '
                        f'{expected_max_day_size}>`.'
                )
                self.assertEqual(
                    size,
                    expected_day_size,
                    msg=f'Number of people scheduled for `{key + 1}th` day is '
                        f'{size}, expected `{expected_day_size}`.'
                )
Пример #3
0
    def test_basic_mutate_solutions(self):
        """
        Test whether created `Antibody` was mutated by `BasicMutator`
        class.
        """
        fitness_value = 125
        n_mutations = 5
        n_performed_mutations = 0
        n_families, family_size = 1000, 20
        df_families = get_df_families(n_families, family_size)

        antibody = Antibody()
        antibody.generate_solution(df_families)
        antibody.fitness_value = fitness_value

        basic_mutator = BasicMutator()
        mutated_antibody = basic_mutator.mutate([[copy.deepcopy(antibody)]],
                                                df_families=df_families)[0][0]

        for i in range(n_families):
            if antibody.families[i] != mutated_antibody.families[i]:
                n_performed_mutations += 1

        self.assertEqual(
            n_mutations,
            n_performed_mutations,
            msg=f'Number of mutations was `{n_performed_mutations}`, expected '
            f'`{n_mutations}`.')
Пример #4
0
    def test_basic_clone_solutions(self):
        """
        Test number of clones created by clone method of `BasicClonator`
        class.
        """
        antibodies = []

        # Pairs of antibody fitness and expected number of clones
        fitness_clones_pair = [[128, 7], [64, 8], [256, 1], [127, 7], [254, 1]]

        for fitness, _ in fitness_clones_pair:
            antibody = Antibody()
            antibody.fitness_value = fitness
            antibodies.append(antibody)

        basic_clonator = BasicClonator()
        clones_lists = basic_clonator.clone(antibodies)

        self.assertEqual(
            len(clones_lists),
            len(fitness_clones_pair),
            msg=f'Number of lists of clones is `{len(clones_lists)}`, '
            f'expected `{len(fitness_clones_pair)}`.')

        for ((_, n_clones), clones) in zip(fitness_clones_pair, clones_lists):
            self.assertEqual(
                len(clones),
                n_clones,
                msg=f'Number of created clones is `{len(clones)}`, '
                f'expected `{n_clones}`.')
Пример #5
0
    def test_preference_mutate_solutions(self):
        """
        Test whether created `Antibody` was mutated by
        `PreferenceMutator` and `AdvancedPreferenceMutator` classes.
        """
        fitness_value = 125
        n_mutations = 5
        n_performed_mutations, n_advanced_performed_mutations = 0, 0
        n_families, family_size = 1000, 20
        df_families = get_df_families(n_families, family_size)

        antibody = Antibody()
        antibody.generate_solution(df_families)
        antibody.fitness_value = fitness_value

        preference_mutator = PreferenceMutator()
        mutated_antibody = preference_mutator.mutate(
            [[copy.deepcopy(antibody)]], df_families=df_families)[0][0]

        advanced_preference_mutator = AdvancedPreferenceMutator()
        advanced_mutated_antibody = advanced_preference_mutator.mutate(
            [[copy.deepcopy(antibody)]], df_families=df_families)[0][0]

        families_choices = df_families[[f'choice_{i}' for i in range(10)]] \
            .values
        for i in range(n_families):
            if antibody.families[i] != mutated_antibody.families[i]:
                n_performed_mutations += 1
                self.assertTrue(
                    mutated_antibody.families[i] in families_choices[i],
                    msg=f'Day mutated family is going to workshop is '
                    f'{mutated_antibody.families[i]}, expected one of '
                    f'{families_choices[i]}.')
            if antibody.families[i] != advanced_mutated_antibody.families[i]:
                n_advanced_performed_mutations += 1
                self.assertTrue(
                    advanced_mutated_antibody.families[i]
                    in families_choices[i],
                    msg=f'Day advanced mutated family is going to workshop is '
                    f'{advanced_mutated_antibody.families[i]}, expected '
                    f'one of {families_choices[i]}.')

        self.assertEqual(
            n_mutations,
            n_performed_mutations,
            msg=f'Number of mutations was `{n_performed_mutations}`, expected '
            f'`{n_mutations}`.')

        self.assertEqual(n_mutations,
                         n_advanced_performed_mutations,
                         msg=f'Number of advanced mutations was '
                         f'`{n_advanced_performed_mutations}`, expected '
                         f'`{n_mutations}`.')
Пример #6
0
    def test_affinity(self):
        """Test affinity computation."""
        population = (
            Antibody(families=np.array([10, 20, 13, 15])),
            Antibody(families=np.array([10, 22, 13, 15])),
            Antibody(families=np.array([11, 20, 14, 1])),
        )
        expected_affinities = [4, 3, 1]
        ArtificialImmuneSystem.affinity(population)
        affinities = [a.affinity_value for a in population]

        self.assertEqual(
            affinities,
            expected_affinities,
            msg=f'Affinities values are `{affinities}`, expected '
                f'`{expected_affinities}`.'
        )
Пример #7
0
    def test_percentile_affinity_select_solutions(self):
        """
        Test whether selected `Antibody` objects were selected according
        to `PercentileAffinitySelector` rules.
        """
        antibodies = []
        affinities = [15, 20, 25, 30, 35, 40, 45, 50, 55, 60]
        negative_filtered_affinities = [[15, 20, 25, 30, 35], [15, 20, 25],
                                        [15, 20], [15]]

        positive_filtered_affinities = [[40, 45, 50, 55, 60], [50, 55, 60],
                                        [55, 60], [60]]

        for affinity in affinities:
            antibody = Antibody()
            antibody.affinity_value = affinity
            antibodies.append(antibody)

        negative_percentile_selector = PercentileAffinitySelector(
            affinity_threshold=50, select_type='negative')
        filtered_antibodies = copy.deepcopy(antibodies)
        for affinities_list in negative_filtered_affinities:
            filtered_antibodies = negative_percentile_selector.select(
                filtered_antibodies)

            for i, antibody in enumerate(filtered_antibodies):
                self.assertEqual(antibody.affinity_value,
                                 affinities_list[i],
                                 msg=f'Antibody had affinity value '
                                 f'`{antibody.affinity_value}`, expected '
                                 f'`{affinities_list[i]}`.')

        positive_percentile_selector = PercentileAffinitySelector(
            affinity_threshold=50, select_type='positive')
        filtered_antibodies = copy.deepcopy(antibodies)
        for affinities_list in positive_filtered_affinities:
            filtered_antibodies = positive_percentile_selector.select(
                filtered_antibodies)

            for i, antibody in enumerate(filtered_antibodies):
                self.assertEqual(antibody.affinity_value,
                                 affinities_list[i],
                                 msg=f'Antibody had affinity value '
                                 f'`{antibody.affinity_value}`, expected '
                                 f'`{affinities_list[i]}`.')
    def test_affinity(self):
        """Test affinity computation."""
        combinations = (
            (np.array([10, 20, 13, 15]), np.array([10, 20, 13, 15]), 4),
            (np.array([10, 20, 13, 15]), np.array([11, 20, 14, 1]), 1),
            (np.array([10, 22, 13, 15]), np.array([11, 20, 14, 1]), 0)
        )

        for families1, families2, expected_affinity in combinations:
            a1 = Antibody(families=families1)
            a2 = Antibody(families=families2)
            affinity = a1.affinity(a2)
            self.assertEqual(
                affinity,
                expected_affinity,
                msg=f'Affinity value between families `{families1}` and '
                    f'`{families2}` is `{a1.affinity_value}`, expected '
                    f'`{expected_affinity}`.'
            )
Пример #9
0
    def test_select_best(self):
        """
        Test selecting of best antibodies from population and clones.
        """
        ais = ArtificialImmuneSystem(
            df_families=None, clonator=None, mutator=None,
            selector=None, population_size=0, n_generations=0
        )
        population_fitness = [25, 15, 5, 38]
        clones_fitness = [[20, 20], [16, 16], [20, 15], [10, 40]]
        min_fitnesses = [20, 15, 5, 10]
        population, clones = [], []

        for fitness in population_fitness:
            antibody = Antibody()
            antibody.fitness_value = fitness
            population.append(antibody)

        for list_of_fitnesses in clones_fitness:
            clones_list = []
            for fitness in list_of_fitnesses:
                antibody = Antibody()
                antibody.fitness_value = fitness
                clones_list.append(antibody)
            clones.append(clones_list)

        new_population = ais.select_best(population, clones)
        for antibody, expected_fitness in zip(new_population, min_fitnesses):
            self.assertEqual(
                antibody.fitness_value,
                expected_fitness,
                msg=f'Fitness of antibody is `{antibody.fitness_value}`, '
                    f'expected `{expected_fitness}`.'
            )
Пример #10
0
    def test_basic_select_solutions(self):
        """
        Test whether selected `Antibody` objects were selected according
        to `BasicSelector` rules.
        """
        antibodies = []
        affinity_threshold = 30
        affinities = [15, 20, 25, 30, 35, 40, 45, 50, 55, 60]
        negative_filtered_affinities = [15, 20, 25, 30]
        positive_filtered_affinities = [30, 35, 40, 45, 50, 55, 60]

        for affinity in affinities:
            antibody = Antibody()
            antibody.affinity_value = affinity
            antibodies.append(antibody)

        negative_basic_selector = BasicSelector(
            affinity_threshold=affinity_threshold, select_type='negative')
        selected_antibodies = negative_basic_selector.select(antibodies)

        for antibody in selected_antibodies:
            self.assertTrue(
                antibody.affinity_value in negative_filtered_affinities,
                msg=f'Antibody had affinity value '
                f'`{antibody.affinity_value}`, expected value smaller or '
                f'equal to `{affinity_threshold}`.')

        positive_basic_selector = BasicSelector(
            affinity_threshold=affinity_threshold, select_type='positive')
        selected_antibodies = positive_basic_selector.select(antibodies)

        for antibody in selected_antibodies:
            self.assertTrue(
                antibody.affinity_value in positive_filtered_affinities,
                msg=f'Antibody had affinity value '
                f'`{antibody.affinity_value}`, expected value greater or '
                f'equal to `{affinity_threshold}`.')
Пример #11
0
    def test_fitness(self):
        """Test fitness computation."""
        n_families, family_size = 3, 125
        df_families = get_df_families(n_families, family_size)
        days = {i: family_size for i in range(n_families)}
        population = (
            Antibody(families=np.array([1, 2, 3]), days=days),
            Antibody(families=np.array([3, 3, 3]), days=days),
            Antibody(families=np.array([1, 1, 2]), days=days),
        )
        fitnesses = (
            50 * 2 + 9 * family_size, (50 + 9 * family_size) * n_families, 50
        )
        expected_fitness_min = np.min(fitnesses)
        expected_fitness_avg = np.mean(fitnesses)

        ais = ArtificialImmuneSystem(
            df_families=df_families, clonator=None, mutator=None,
            selector=None, population_size=0, n_generations=0, n_cpu=7
        )
        _, best_antibody, fitness_avg = ais.fitness(population)
        fitness_min = best_antibody.fitness_value

        self.assertAlmostEqual(
            fitness_min,
            expected_fitness_min,
            places=7,
            msg=f'Minimum fitness is `{fitness_min}`, expected '
                f'`{expected_fitness_min}`.'
        )
        self.assertAlmostEqual(
            fitness_avg,
            expected_fitness_avg,
            places=7,
            msg=f'Average fitness is `{fitness_avg}`, expected '
                f'`{expected_fitness_avg}`.'
        )
Пример #12
0
    def fitness(self, population):
        """
        Compute fitness of each antibody in `population`.

        :param population: list, list of `Antibody` objects.
        :return:
            list, list of antibodies with calculated fitness values.
            Antibody, antibody with minimum fitness value.
            float, average fitness value.
        """
        sum_fitness = 0
        best_antibody = Antibody()
        best_antibody.fitness_value = 999999999999

        with multiprocessing.Pool(self.n_cpu) as pool:
            fn = partial(self._fitness, df_families=self.df_families)
            population = pool.map(fn, population)

        for antibody in population:
            sum_fitness += antibody.fitness_value
            if antibody.fitness_value < best_antibody.fitness_value:
                best_antibody = antibody

        return population, best_antibody, sum_fitness / len(population)
 def test_lower_than(self):
     """Test less than comparison between two antibodies."""
     fitnesses = ((0, 1), (5, 10))
     for f1, f2 in fitnesses:
         a1 = Antibody()
         a1.fitness_value = f1
         a2 = Antibody()
         a2.fitness_value = f2
         self.assertLess(
             a1,
             a2,
             msg=f'Antibody `{a1}` should be less than `{a2}`.'
         )
 def test_equal(self):
     """Test equal comparison between two antibodies."""
     fitnesses = (0, 5, 10)
     for fitness in fitnesses:
         a1 = Antibody()
         a1.fitness_value = fitness
         a2 = Antibody()
         a2.fitness_value = fitness
         self.assertEqual(
             a1,
             a2,
             msg=f'Antibody `{a1}` should equal to `{a2}`.'
         )
Пример #15
0
    def generate_population(self, n=None):
        """
        Generate random population of antibodies of size
        `self.population_size`.

        :param n: int (default: None), size of population to be
            generated. If `None` then population of size
            `self.population_size` will be generated.
        :return: list, list of `Antibody` object.
        """
        n = self.population_size if n is None else n
        population = []
        with multiprocessing.Pool(self.n_cpu) as pool:
            for _ in range(n):
                pool.apply_async(
                    Antibody().generate_solution,
                    args=[self.df_families],
                    callback=lambda x: population.append(x)
                )
            pool.close()
            pool.join()

        return population