Index: /framspy/evolalg/base/experiment_niching_abc.py
===================================================================
--- /framspy/evolalg/base/experiment_niching_abc.py	(revision 1307)
+++ /framspy/evolalg/base/experiment_niching_abc.py	(revision 1308)
@@ -25,5 +25,5 @@
     archive_size: int = None
 
-    def __init__(self, fit, normalize, popsize, hof_size, save_only_best, knn_niching, knn_nslc, archive_size) -> None:
+    def __init__(self, fit, normalize, popsize, hof_size, save_only_best, knn_niching, knn_nslc, archive_size, crowding_dissim = None) -> None:
         ExperimentABC.__init__(self,popsize=popsize, hof_size=hof_size, save_only_best=save_only_best)
         self.fit = fit
@@ -32,4 +32,5 @@
         self.knn_nslc = knn_nslc
         self.archive_size=archive_size
+        self.crowding_dissim = crowding_dissim
 
         # np.argpartition requires these parameters to be at most popsize-2; popsize is decreased by 1 because we remove_diagonal()
@@ -68,5 +69,5 @@
 
         if Individual.fitness_set_negative_to_zero is False and ("niching" in self.fit or "novelty" in self.fit):
-        	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.
+            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.
 
         if "niching" in self.fit:
@@ -104,9 +105,27 @@
         population_structures.update_archive(dissim_matrix, population_archive)
 
+    def assignCrowdingDistFramspy(self, individuals):
+        """Assign a crowding distance to each individual's fitness. The
+        crowding distance can be retrieved via the :attr:`crowding_dist`
+        attribute of each individual's fitness.
+        """
+        if len(individuals) == 0:
+            return
+        
+        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
+            return assignCrowdingDist(individuals)
+        
+        dissim_matrix = self.crowding_distance_dissimilarity(individuals)
+        assert len(dissim_matrix) == len(individuals), f'Dissimilarity matrix does not match the size of the population {len(dissim_matrix)}:{len(individuals)}' 
+        
+        for i in range(len(individuals)):
+            individuals[i].fitness.crowding_dist = np.mean(dissim_matrix[i])
+
+
     def make_new_population_nsga2(self, population_structures, prob_mut, prob_xov):
         expected_mut = int(self.popsize * prob_mut)
         expected_xov = int(self.popsize * prob_xov)
         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)
-        assignCrowdingDist(population_structures.population)
+        self.assignCrowdingDistFramspy(population_structures.population)
         offspring = tools.selTournamentDCD(population_structures.population, self.popsize)
 
@@ -192,5 +211,9 @@
         parser.add_argument("-dissim", type = lambda arg: DissimMethod[arg], choices = DissimMethod,
                    default=DissimMethod.PHENE_STRUCT_OPTIM,
-                   help="Dissimilarity measure type. Available: " + str(DissimMethod._member_names_))
+                   help="The type of the dissimilarity measure to be used in novelty and niching diversity control. Available: " + str(DissimMethod._member_names_))
+
+        parser.add_argument("-crowding_dissim", type = lambda arg: DissimMethod[arg], choices = DissimMethod,
+                   default=DissimMethod.FITNESS,
+                   help="The type of the dissimilarity measure to be used as NSGA2 and NSLC crowding distance. Available: " + str(DissimMethod._member_names_))
         parser.add_argument("-fit",type= str, default="raw",
                         help="Fitness type, availible types: niching, novelty, knn_niching (local), knn_novelty (local), nsga2, nslc and raw (default)")
@@ -206,3 +229,14 @@
     @abstractmethod
     def dissimilarity(self, population: list):
+        """
+            Used for calculating dissimilarity in novelty and niching methods 
+        """
         pass
+
+    @abstractmethod
+    def crowding_distance_dissimilarity(self, population: list):
+        """
+            Used for calculating dissimilarity for nsga2 crowding distance, 
+            currently used in NSGA2 and NSLC
+        """
+        pass
Index: /framspy/evolalg/frams_base/experiment_frams_niching.py
===================================================================
--- /framspy/evolalg/frams_base/experiment_frams_niching.py	(revision 1307)
+++ /framspy/evolalg/frams_base/experiment_frams_niching.py	(revision 1308)
@@ -7,5 +7,5 @@
 
 class ExperimentFramsNiching(ExperimentFrams, ExperimentNiching):
-    def __init__(self, frams_lib, optimization_criteria, hof_size, popsize, constraints, normalize, dissim, fit, genformat, archive_size, save_only_best, knn_niching, knn_nslc) -> None:
+    def __init__(self, frams_lib, optimization_criteria, hof_size, popsize, constraints, normalize, dissim, fit, genformat, archive_size, save_only_best, knn_niching, knn_nslc, crowding_dissim=None) -> None:
         ExperimentFrams.__init__(self, hof_size=hof_size,
                                  popsize=popsize,
@@ -23,5 +23,6 @@
                                    archive_size=archive_size,
                                    knn_niching=knn_niching,
-                                   knn_nslc=knn_nslc
+                                   knn_nslc=knn_nslc,
+                                   crowding_dissim=crowding_dissim
                                    )
         self.dissim = dissim
@@ -47,4 +48,7 @@
     def dissimilarity(self, population):
         return self.frams_lib.dissimilarity([i.genotype for i in population], self.dissim)
+    
+    def crowding_distance_dissimilarity(self, population):
+        return self.frams_lib.dissimilarity([i.genotype for i in population], self.crowding_dissim)
 
 
Index: /framspy/evolalg/run_frams_niching.py
===================================================================
--- /framspy/evolalg/run_frams_niching.py	(revision 1307)
+++ /framspy/evolalg/run_frams_niching.py	(revision 1308)
@@ -30,4 +30,5 @@
                                         normalize=parsed_args.normalize,
                                         dissim=parsed_args.dissim,
+                                        crowding_dissim=parsed_args.crowding_dissim,
                                         fit=parsed_args.fit,
                                         genformat=parsed_args.genformat,
Index: /framspy/evolalg/tests/test_diferent_settings.py
===================================================================
--- /framspy/evolalg/tests/test_diferent_settings.py	(revision 1307)
+++ /framspy/evolalg/tests/test_diferent_settings.py	(revision 1308)
@@ -47,5 +47,6 @@
     'hof_size': [0, 10],
     'normalize': ['none', 'max', 'sum'],
-    'dissim': [DissimMethod.GENE_LEVENSHTEIN, DissimMethod.PHENE_STRUCT_OPTIM, DissimMethod.PHENE_DESCRIPTORS, DissimMethod.PHENE_DENSITY_FREQ],
+    'dissim': [DissimMethod.GENE_LEVENSHTEIN],# DissimMethod.PHENE_STRUCT_OPTIM, DissimMethod.PHENE_DESCRIPTORS, DissimMethod.PHENE_DENSITY_COUNT, DissimMethod.PHENE_DENSITY_FREQ],
+    'crowding_dissim': [DissimMethod.FITNESS, DissimMethod.GENE_LEVENSHTEIN, DissimMethod.PHENE_STRUCT_OPTIM],#, DissimMethod.PHENE_STRUCT_OPTIM, DissimMethod.PHENE_DESCRIPTORS, DissimMethod.PHENE_DENSITY_COUNT, DissimMethod.PHENE_DENSITY_FREQ],
     'fit': ['niching', 'novelty', 'nsga2', 'nslc', 'raw'],
     'genformat': ['1'],
@@ -130,4 +131,5 @@
                                         normalize=params['normalize'],
                                         dissim=params['dissim'],
+                                        crowding_dissim=params['crowding_dissim'],
                                         fit=params['fit'],
                                         genformat=params['genformat'],
