Changeset 1289 for framspy/evolalg/base


Ignore:
Timestamp:
01/15/24 05:43:37 (4 months ago)
Author:
Maciej Komosinski
Message:

fitness_set_negative_to_zero boolean (a.k.a. "only positive fitness", needed for novelty and niching diversity control) becomes a command-line flag instead of a hardcoded value

Location:
framspy/evolalg/base
Files:
2 edited

Legend:

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

    r1283 r1289  
    2323    current_generation = 0
    2424    time_elapsed = 0
    25    
    26 
    27     def __init__(self, popsize, hof_size, save_only_best=True) -> None:
     25
     26
     27    def __init__(self, popsize, hof_size, save_only_best) -> None:
    2828        self.hof = HallOfFame(hof_size)
    2929        self.popsize = popsize
     
    126126        # instead of single best, could add all individuals in population here, but then the outcome would depend on the order of adding
    127127        self.hof.add(best)
    128         self.stats.append(
    129             best.rawfitness if self.save_only_best else best)
    130         print("%d\t%d\t%g\t%g" % (generation, len(
    131             all_individuals), worst.rawfitness, best.rawfitness))
     128        self.stats.append(best.rawfitness if self.save_only_best else best)
     129        print("%d\t%d\t%g\t%g" % (generation, len(all_individuals), worst.rawfitness, best.rawfitness))
    132130
    133131    def initialize_evolution(self, initialgenotype):
     
    149147            # saved generation has been completed, start with the next one
    150148            self.current_generation += 1
    151             print("...Resuming from saved state: population size = %d, hof size = %d, stats size = %d, archive size = %d, generation = %d/%d" % (len(self.population_structures.population), len(self.hof),
    152                                                                                                                                                  len(self.stats),  (len(self.population_structures.archive)), self.current_generation, generations))  # self.current_generation (and g) are 0-based, parsed_args.generations is 1-based
    153 
     149            print("...Resuming from saved state: population size = %d, hof size = %d, stats size = %d, archive size = %d, generation = %d/%d" % (len(self.population_structures.population), len(self.hof), len(self.stats), (len(self.population_structures.archive)), self.current_generation, generations))  # self.current_generation (and g) are 0-based, parsed_args.generations is 1-based
    154150        else:
    155151            self.initialize_evolution(initialgenotype)
     
    192188    def get_args_for_parser():
    193189        parser = argparse.ArgumentParser()
    194         parser.add_argument('-popsize',type= int, default= 50,
     190        parser.add_argument('-popsize', type=int, default=50,
    195191                            help="Population size, default: 50.")
    196         parser.add_argument('-generations',type= int, default= 5,
     192        parser.add_argument('-generations', type=int, default=5,
    197193                                help="Number of generations, default: 5.")
    198         parser.add_argument('-tournament',type= int, default= 5,
     194        parser.add_argument('-tournament', type=int, default=5,
    199195                            help="Tournament size, default: 5.")
    200         parser.add_argument('-pmut',type= float, default= 0.7,
     196        parser.add_argument('-pmut', type=float, default=0.7,
    201197                        help="Probability of mutation, default: 0.7")
    202         parser.add_argument('-pxov',type= float, default= 0.2,
     198        parser.add_argument('-pxov', type=float, default=0.2,
    203199                        help="Probability of crossover, default: 0.2")
    204         parser.add_argument('-hof_size',type= int, default= 10,
     200        parser.add_argument('-hof_size', type=int, default=10,
    205201                            help="Number of genotypes in Hall of Fame. Default: 10.")
    206         parser.add_argument('-hof_savefile',type= str, required= False,
     202        parser.add_argument('-hof_savefile', type=str, required=False,
    207203                                help= 'If set, Hall of Fame will be saved in Framsticks file format (recommended extension *.gen. This also activates saving state (checpoint} file and auto-resuming from the saved state, if this file exists.')
    208         parser.add_argument('-save_only_best',type= bool, default= True, required= False,
     204        parser.add_argument('-save_only_best', type=bool, default=True, required=False,
    209205                            help="")
     206        parser.add_argument('-fitness_set_negative_to_zero', action='store_true',
     207                            help="This flag forces fitness to become max(0,fitness), so it is always made non-negative. Using niching or novelty techniques without this flag (thus allowing negative fitness values) requires verifying/improving fitness diversification formulas to work as intended for both positive and negative fitness values.")
    210208       
    211209        return parser
  • framspy/evolalg/base/experiment_niching_abc.py

    r1272 r1289  
    2424    archive_size: int = None
    2525
    26     def __init__(self, fit, normalize, popsize, hof_size, save_only_best=True, knn_niching=5, knn_nslc=10, archive_size=0) -> None:
     26    def __init__(self, fit, normalize, popsize, hof_size, save_only_best, knn_niching, knn_nslc, archive_size) -> None:
    2727        ExperimentABC.__init__(self,popsize=popsize, hof_size=hof_size, save_only_best=save_only_best)
    2828        self.fit = fit
     
    5151            divide_by = np.sum(dissim_matrix)
    5252        else:
    53             raise Exception(f"Wrong normalization method,", self.normalize)
     53            raise ValueError("Wrong normalization method: '%s'" % self.normalize)
    5454        if divide_by != 0:
    5555            return dissim_matrix/divide_by
     
    6565            dissim_list = np.mean(np.partition(
    6666                self.normalize_dissim(dissim_matrix), self.knn_niching)[:, :self.knn_niching], axis=1)
     67
     68        if Individual.fitness_set_negative_to_zero is False and ("niching" in self.fit or "novelty" in self.fit):
     69                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.
    6770
    6871        if "niching" in self.fit:
     
    7376                i.fitness = d
    7477        else:
    75             raise Exception("Wrong fit type: ", self.fit,
    76                             f" choose the correct one or implement a new behavior.")
     78            raise ValueError("Unsupported fit type: '%s'. Use the correct type or implement a new behavior." % self.fit)
    7779        population_structures.update_archive(dissim_matrix, population_archive)
    7880
Note: See TracChangeset for help on using the changeset viewer.