Changeset 1308 for framspy/evolalg/base


Ignore:
Timestamp:
06/05/24 22:35:50 (3 months ago)
Author:
Maciej Komosinski
Message:

Added the ability to select a dissimilarity measure for crowding distance (for NSGA2 and NSLC) independently from the main dissimilarity measure

File:
1 edited

Legend:

Unmodified
Added
Removed
  • framspy/evolalg/base/experiment_niching_abc.py

    r1306 r1308  
    2525    archive_size: int = None
    2626
    27     def __init__(self, fit, normalize, popsize, hof_size, save_only_best, knn_niching, knn_nslc, archive_size) -> None:
     27    def __init__(self, fit, normalize, popsize, hof_size, save_only_best, knn_niching, knn_nslc, archive_size, crowding_dissim = None) -> None:
    2828        ExperimentABC.__init__(self,popsize=popsize, hof_size=hof_size, save_only_best=save_only_best)
    2929        self.fit = fit
     
    3232        self.knn_nslc = knn_nslc
    3333        self.archive_size=archive_size
     34        self.crowding_dissim = crowding_dissim
    3435
    3536        # np.argpartition requires these parameters to be at most popsize-2; popsize is decreased by 1 because we remove_diagonal()
     
    6869
    6970        if Individual.fitness_set_negative_to_zero is False and ("niching" in self.fit or "novelty" in self.fit):
    70                 raise ValueError("Negative fitness values not tested in combination with niching or novelty. When using these techniques, verify formulas or consider using the flag -fitness_set_negative_to_zero") # once the formulas are verified/improved, the command-line flag and this conditional check can be removed.
     71            raise ValueError("Negative fitness values not tested in combination with niching or novelty. When using these techniques, verify formulas or consider using the flag -fitness_set_negative_to_zero") # once the formulas are verified/improved, the command-line flag and this conditional check can be removed.
    7172
    7273        if "niching" in self.fit:
     
    104105        population_structures.update_archive(dissim_matrix, population_archive)
    105106
     107    def assignCrowdingDistFramspy(self, individuals):
     108        """Assign a crowding distance to each individual's fitness. The
     109        crowding distance can be retrieved via the :attr:`crowding_dist`
     110        attribute of each individual's fitness.
     111        """
     112        if len(individuals) == 0:
     113            return
     114       
     115        if self.crowding_dissim is DissimMethod.FITNESS: # if crowding dissim was not specified (DissimMethod.FITNESS is our default) or was set to fitness, use the default DEAP implementation that relies on fitness
     116            return assignCrowdingDist(individuals)
     117       
     118        dissim_matrix = self.crowding_distance_dissimilarity(individuals)
     119        assert len(dissim_matrix) == len(individuals), f'Dissimilarity matrix does not match the size of the population {len(dissim_matrix)}:{len(individuals)}'
     120       
     121        for i in range(len(individuals)):
     122            individuals[i].fitness.crowding_dist = np.mean(dissim_matrix[i])
     123
     124
    106125    def make_new_population_nsga2(self, population_structures, prob_mut, prob_xov):
    107126        expected_mut = int(self.popsize * prob_mut)
    108127        expected_xov = int(self.popsize * prob_xov)
    109128        assert expected_mut + expected_xov <= self.popsize, "If probabilities of mutation (%g) and crossover (%g) added together exceed 1.0, then the population would grow every generation..." % (prob_mut, prob_xov)
    110         assignCrowdingDist(population_structures.population)
     129        self.assignCrowdingDistFramspy(population_structures.population)
    111130        offspring = tools.selTournamentDCD(population_structures.population, self.popsize)
    112131
     
    192211        parser.add_argument("-dissim", type = lambda arg: DissimMethod[arg], choices = DissimMethod,
    193212                   default=DissimMethod.PHENE_STRUCT_OPTIM,
    194                    help="Dissimilarity measure type. Available: " + str(DissimMethod._member_names_))
     213                   help="The type of the dissimilarity measure to be used in novelty and niching diversity control. Available: " + str(DissimMethod._member_names_))
     214
     215        parser.add_argument("-crowding_dissim", type = lambda arg: DissimMethod[arg], choices = DissimMethod,
     216                   default=DissimMethod.FITNESS,
     217                   help="The type of the dissimilarity measure to be used as NSGA2 and NSLC crowding distance. Available: " + str(DissimMethod._member_names_))
    195218        parser.add_argument("-fit",type= str, default="raw",
    196219                        help="Fitness type, availible types: niching, novelty, knn_niching (local), knn_novelty (local), nsga2, nslc and raw (default)")
     
    206229    @abstractmethod
    207230    def dissimilarity(self, population: list):
     231        """
     232            Used for calculating dissimilarity in novelty and niching methods
     233        """
    208234        pass
     235
     236    @abstractmethod
     237    def crowding_distance_dissimilarity(self, population: list):
     238        """
     239            Used for calculating dissimilarity for nsga2 crowding distance,
     240            currently used in NSGA2 and NSLC
     241        """
     242        pass
Note: See TracChangeset for help on using the changeset viewer.