Ignore:
Timestamp:
07/07/21 14:38:57 (3 years ago)
Author:
Maciej Komosinski
Message:

Added niching and novelty search with limited (i.e., local) competition ("nearest neighbors" according to dissimilarity measure)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • framspy/evolalg/examples/niching_novelty.py

    r1140 r1145  
    2323from evolalg.statistics.statistics_deap import StatisticsDeap
    2424from evolalg.base.union_step import UnionStep
    25 from evolalg.utils.name_propagation import propagate_names
    2625from evolalg.utils.population_save import PopulationSave
    27 import time
    2826
    2927
     
    4745    niching = "niching"
    4846    novelty = "novelty"
     47    knn_niching = "knn_niching"
     48    knn_novelty = "knn_novelty"
    4949
    5050    def __str__(self):
     
    5858    parser.add_argument('-path', type=ensureDir, required=True, help='Path to the Framsticks library without trailing slash.')
    5959    parser.add_argument('-opt', required=True,
    60                         help='optimization criteria : vertpos, velocity, distance, vertvel, lifespan, numjoints, numparts, numneurons, numconnections (or other as long as it is provided by the .sim file and its .expdef). Single or multiple criteria.')
     60                        help='optimization criteria: vertpos, velocity, distance, vertvel, lifespan, numjoints, numparts, numneurons, numconnections (or other as long as it is provided by the .sim file and its .expdef). For multiple criteria optimization, see multicriteria.py.')
    6161    parser.add_argument('-lib', required=False, help="Filename of .so or .dll with the Framsticks library")
    6262
     
    6868    parser.add_argument('-dissim', required=False, type=Dissim, default=Dissim.frams,
    6969                        help='Dissimilarity measure, default: frams', choices=list(Dissim))
     70    parser.add_argument('-knn', type=int, help="'k' value for knn-based fitness criteria (knn-niching and knn-novelty).")
    7071    parser.add_argument('-popsize', type=int, default=50, help="Population size, default: 50.")
    7172    parser.add_argument('-generations', type=int, default=5, help="Number of generations, default: 5.")
     
    8182    parser.add_argument('-checkpoint_path', required=False, default=None, help="Path to the checkpoint file")
    8283    parser.add_argument('-checkpoint_interval', required=False, type=int, default=100, help="Checkpoint interval")
    83     parser.add_argument('--debug', dest='debug', action='store_true', help="Prints names of steps as they are executed")
     84    parser.add_argument('-debug', dest='debug', action='store_true', help="Prints names of steps as they are executed")
    8485    parser.set_defaults(debug=False)
    8586    return parser.parse_args()
     
    129130    def remove(self, individual):
    130131        return individual.numconnections > self.max_number
     132
    131133
    132134class ReplaceWithHallOfFame(Step):
     
    138140        return list(self.hof.halloffame)
    139141
     142
    140143def func_niching(ind): setattr(ind, "fitness", ind.fitness_raw * (1 + ind.dissim))
    141144
     
    145148
    146149def func_novelty(ind): setattr(ind, "fitness", ind.dissim)
     150
     151
     152def func_knn_novelty(ind): setattr(ind, "fitness", ind.dissim)
     153
     154
     155def func_knn_niching(ind): setattr(ind, "fitness", ind.fitness_raw * (1 + ind.dissim))
    147156
    148157
     
    214223    # -------------------------------------------------
    215224    # Novelty or niching
     225    knn = parsed_args.knn
     226    if parsed_args.fit == Fitness.knn_novelty or parsed_args.fit == Fitness.knn_niching:
     227        reduction_method = "knn_mean"
     228        assert knn is not None, "'k' must be set for knn-based fitness."
     229        assert knn > 0, "'k' must be positive."
     230        assert knn < parsed_args.popsize, "'k' must be smaller than population size."
     231    else:
     232        reduction_method = "mean"
     233        assert knn is None, "'k' is irrelevant unless knn-based fitness is used."
     234
    216235    dissim = None
    217236    if parsed_args.dissim == Dissim.levenshtein:
    218         dissim = LevenshteinDissimilarity(reduction="mean", output_field="dissim")
     237        dissim = LevenshteinDissimilarity(reduction=reduction_method, knn=knn, output_field="dissim")
    219238    elif parsed_args.dissim == Dissim.frams:
    220         dissim = FramsDissimilarity(frams_lib, reduction="mean", output_field="dissim")
     239        dissim = FramsDissimilarity(frams_lib, reduction=reduction_method, knn=knn, output_field="dissim")
    221240
    222241    if parsed_args.fit == Fitness.raw:
     
    241260        init_stages.append(novelty)
    242261        generation_modifications.append(novelty)
     262   
     263    if parsed_args.fit == Fitness.knn_niching:
     264        knn_niching = UnionStep([
     265            dissim,
     266            LambdaStep(func_knn_niching)
     267        ])
     268        init_stages.append(knn_niching)
     269        generation_modifications.append(knn_niching)
     270   
     271    if parsed_args.fit == Fitness.knn_novelty:
     272        knn_novelty = UnionStep([
     273            dissim,
     274            LambdaStep(func_knn_novelty)
     275        ])
     276        init_stages.append(knn_novelty)
     277        generation_modifications.append(knn_novelty)
    243278
    244279    # -------------------------------------------------
Note: See TracChangeset for help on using the changeset viewer.