Changeset 1306


Ignore:
Timestamp:
05/13/24 03:59:10 (3 months ago)
Author:
Maciej Komosinski
Message:

Introduced symbolic names for dissimilarity estimation methods

Location:
framspy
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • framspy/FramsticksLib.py

    r1295 r1306  
    11from typing import List  # to be able to specify a type hint of list(something)
     2from enum import Enum, auto, unique
    23import json
    34import sys, os
     
    56import numpy as np
    67import frams
     8
     9
     10@unique
     11class DissimMethod(Enum):  # values assigned to fields are irrelevant, hence auto()
     12        GENE_LEVENSHTEIN = auto()  # genetic Levenshtein distance
     13        PHENE_STRUCT_GREEDY = auto()  # phenetic, graph structure, fast but approximate
     14        PHENE_STRUCT_OPTIM = auto()  # phenetic, graph structure, slower for complex creatures but optimal
     15        PHENE_DESCRIPTORS = auto()  # phenetic, shape descriptors
     16        PHENE_DENSITY_COUNT = auto()  # phenetic, density distribution, count of samples
     17        PHENE_DENSITY_FREQ = auto()  # phenetic, density distribution, frequency of count of samples
     18        FITNESS = auto()  # fitness value
     19
    720
    821
     
    6780                for simfile in self.EVALUATION_SETTINGS_FILE:
    6881                        ec = frams.MessageCatcher.new()  # catch potential errors, warnings, messages - just to detect if there are ERRORs
    69                         ec.store = 2;  # store all, because they are caught by MessageCatcher and will not appear in output (which we want)
     82                        ec.store = 2  # store all, because they are caught by MessageCatcher and will not appear in output (which we want)
    7083                        frams.Simulator.ximport(simfile, 4 + 8 + 16)
    7184                        ec.close()
     
    7588
    7689
    77         def getSimplest(self, genetic_format) -> str:
     90        def getSimplest(self, genetic_format: str) -> str:
    7891                return frams.GenMan.getSimplest(genetic_format).genotype._string()
    7992
     
    134147                if not self.PRINT_FRAMSTICKS_OUTPUT:
    135148                        ec = frams.MessageCatcher.new()  # mute potential errors, warnings, messages
    136                         ec.store = 2;  # store all, because they are caught by MessageCatcher and will not appear in output
     149                        ec.store = 2  # store all, because they are caught by MessageCatcher and will not appear in output
    137150
    138151                frams.GenePools[0].clear()
     
    192205
    193206
    194         def dissimilarity(self, genotype_list: List[str], method: int) -> np.ndarray:
    195                 """
    196                         :param method: -1 = genetic Levenshtein distance; 0, 1, 2 = phenetic dissimilarity (SimilMeasureGreedy, SimilMeasureHungarian, SimilMeasureDistribution); -2, -3 = phenetic density distribution (count, frequency).
     207        def dissimilarity(self, genotype_list: List[str], method: DissimMethod) -> np.ndarray:
     208                """
     209                        :param method, see DissimMethod.
    197210                        :return: A square array with dissimilarities of each pair of genotypes.
    198211                """
     
    206219                square_matrix = np.zeros((n, n))
    207220
    208                 if method in (0, 1, 2):  # Framsticks phenetic dissimilarity methods
    209                         frams.SimilMeasure.simil_type = method
     221                if method in (DissimMethod.PHENE_STRUCT_GREEDY, DissimMethod.PHENE_STRUCT_OPTIM, DissimMethod.PHENE_DESCRIPTORS):  # Framsticks phenetic dissimilarity methods
     222                        frams.SimilMeasure.simil_type = 0 if method == DissimMethod.PHENE_STRUCT_GREEDY else 1 if method == DissimMethod.PHENE_STRUCT_OPTIM else 2
    210223                        genos = []  # prepare an array of Geno objects so that we don't need to convert raw strings to Geno objects all the time in loops
    211224                        for g in genotype_list:
     
    215228                                for j in range(n):  # maybe calculate only one triangle if you really need a 2x speedup
    216229                                        square_matrix[i][j] = frams_evaluateDistance(genos[i], genos[j])._double()
    217                 elif method == -1:
     230                elif method == DissimMethod.GENE_LEVENSHTEIN:
    218231                        import Levenshtein
    219232                        for i in range(n):
    220233                                for j in range(n):  # maybe calculate only one triangle if you really need a 2x speedup
    221234                                        square_matrix[i][j] = Levenshtein.distance(genotype_list[i], genotype_list[j])
    222                 elif method in (-2, -3):
     235                elif method in (DissimMethod.PHENE_DENSITY_COUNT, DissimMethod.PHENE_DENSITY_FREQ):
    223236                        if self.dissim_measure_density_distribution is None:
    224237                                from dissimilarity.density_distribution import DensityDistribution
    225238                                self.dissim_measure_density_distribution = DensityDistribution(frams)
    226                         self.dissim_measure_density_distribution.frequency = (method == -3)
     239                        self.dissim_measure_density_distribution.frequency = (method == DissimMethod.PHENE_DENSITY_FREQ)
    227240                        square_matrix = self.dissim_measure_density_distribution.getDissimilarityMatrix(genotype_list)
    228241                else:
    229                         raise ValueError("Don't know what to do with dissimilarity method = %d" % method)
     242                        raise ValueError("Don't know what to do with dissimilarity method = %s" % method)
    230243
    231244                for i in range(n):
     
    381394        offspring = framsLib.crossOver(parent1, parent2)
    382395        print("\tCrossover (Offspring):", offspring)
    383         print('\tDissimilarity of Parent1 and Offspring:', framsLib.dissimilarity([parent1, offspring], 1)[0, 1])
     396        print('\tDissimilarity of Parent1 and Offspring:', framsLib.dissimilarity([parent1, offspring], DissimMethod.PHENE_STRUCT_OPTIM)[0, 1])
    384397        print('\tPerformance of Offspring:', framsLib.evaluate([offspring]))
    385398        print('\tValidity (genetic) of Parent1, Parent 2, and Offspring:', framsLib.isValid([parent1, parent2, offspring]))
  • framspy/evolalg/base/experiment_niching_abc.py

    r1304 r1306  
    1010from .experiment_abc import ExperimentABC
    1111from .remove_diagonal import remove_diagonal
     12from FramsticksLib import DissimMethod  # since the descendant ExperimentFramsNiching class does not introduce any Framsticks-specific dissimilarity methods, all of them must be known here (in ExperimentNiching)
    1213
    1314
     
    189190    def get_args_for_parser():
    190191        parser = ExperimentABC.get_args_for_parser()
    191         parser.add_argument("-dissim",type= int, default=1,
    192                    help="Dissimilarity measure type. Available: -3:freq, -2:dens, -1:Leven, 1:frams-struct (default}, 2:frams-descr")
     192        parser.add_argument("-dissim", type = lambda arg: DissimMethod[arg], choices = DissimMethod,
     193                   default=DissimMethod.PHENE_STRUCT_OPTIM,
     194                   help="Dissimilarity measure type. Available: " + str(DissimMethod._member_names_))
    193195        parser.add_argument("-fit",type= str, default="raw",
    194196                        help="Fitness type, availible types: niching, novelty, knn_niching (local), knn_novelty (local), nsga2, nslc and raw (default)")
  • framspy/evolalg/tests/test_diferent_settings.py

    r1296 r1306  
    33import numpy as np
    44
    5 from FramsticksLib import FramsticksLib
     5from FramsticksLib import FramsticksLib, DissimMethod
    66
    77from ..frams_base.experiment_frams_niching import ExperimentFramsNiching
     
    1414
    1515
    16 GENERATIONS = 10 
     16GENERATIONS = 10
    1717
    1818SETTINGS_TO_TEST_NUMERIC = {
     
    4747    'hof_size': [0, 10],
    4848    'normalize': ['none', 'max', 'sum'],
    49     'dissim': [-2, -1, 1, 2],
     49    'dissim': [DissimMethod.GENE_LEVENSHTEIN, DissimMethod.PHENE_STRUCT_OPTIM, DissimMethod.PHENE_DESCRIPTORS, DissimMethod.PHENE_DENSITY_FREQ],
    5050    'fit': ['niching', 'novelty', 'nsga2', 'nslc', 'raw'],
    5151    'genformat': ['1'],
  • framspy/run-evolalg-examples.cmd

    r1289 r1306  
    99
    1010rem evolution with niching
    11 python -m evolalg.run_frams_niching  -path %DIR_WITH_FRAMS_LIBRARY%  -sim "eval-allcriteria.sim;deterministic.sim;sample-period-longest.sim" -opt velocity -genformat 0 -dissim 1 -fit knn_niching -archive 50 -fitness_set_negative_to_zero  -max_numparts 15 -max_numneurons 15 -max_numjoints 30 -max_numconnections 30  -max_numgenochars 10000 -popsize 50 -generations 10 -normalize none -hof_savefile HoF-niching.gen
     11python -m evolalg.run_frams_niching  -path %DIR_WITH_FRAMS_LIBRARY%  -sim "eval-allcriteria.sim;deterministic.sim;sample-period-longest.sim" -opt velocity -genformat 0 -dissim PHENE_STRUCT_OPTIM -fit knn_niching -archive 50 -fitness_set_negative_to_zero  -max_numparts 15 -max_numneurons 15 -max_numjoints 30 -max_numconnections 30  -max_numgenochars 10000 -popsize 50 -generations 10 -normalize none -hof_savefile HoF-niching.gen
    1212
    1313rem a generic island model example
Note: See TracChangeset for help on using the changeset viewer.