2323
2424from operations import Operation
2525from schedules import Schedule
26- from individual import Individual , PermutationChromosome
26+ from individual import Individual , PermutationChromosome , EnhancedQuantumRandomKeyIndividual
2727from or_benchmark import BenchmarkCollection
2828import matplotlib .pyplot as plt
2929from PIL import Image
@@ -294,7 +294,7 @@ def non_dominated_sorting(self):
294294 # For each individual go through the rest to find the best possible individual (that dominates all solutions)
295295 dominated = False
296296 for j in range (cur_start , len (self .R )):
297- # swap if J dominates the
297+ # swap if J dominates the
298298 cur_comparison = np .array (self .R [j ].cur_fitness ) <= np .array (self .R [i ].cur_fitness )
299299 if (i != j ) and (cur_comparison ).all ():
300300 # Break the loop if the individual i is dominated -> means that the individual does not belong to the current front
@@ -309,9 +309,6 @@ def non_dominated_sorting(self):
309309 # Move swap position one step to the right
310310 cur_swap_index += 1
311311
312- # What happens when all solutions are dominated.
313- # What happens if only one individual is in a front
314-
315312 # Close the front
316313 if cur_start == cur_swap_index :
317314 # There is only one front in the set,
@@ -323,8 +320,9 @@ def non_dominated_sorting(self):
323320 cur_start = cur_swap_index
324321
325322 # Add the last front
326- if self .front_start_index [- 1 ] < self .N :
327- self .front_start_index .append (self .N )
323+ #if self.front_start_index[-1] < self.N:
324+ self .front_start_index .append (cur_start )
325+
328326
329327
330328 def get_front_range (self , i : int ) -> List :
@@ -898,4 +896,113 @@ def execute_quantum_update(self, c: int, c_tot: int):
898896 temp_front_indexes .append (j )
899897
900898
899+ front_indexes = temp_front_indexes
900+
901+
902+ class EnhancedQMEAPopulation (Population ):
903+ def __init__ (self ,
904+ N : int ,
905+ reset_fraction : float ,
906+ decoding_method : str ,
907+ n_jobs : int ,
908+ n_machines : int ,
909+ jssp_problem : np .ndarray ,
910+ individual_cfg : DictConfig ,
911+ rotation_angles : str ,
912+ std_deltas : str ,
913+ group_partitions : int ,
914+ activate_schedule : bool = False ,
915+ time_log : bool = False ,
916+ individual_type = "EnhancedQuantumRandomKeyIndividual"
917+ ):
918+ super ().__init__ (N , decoding_method , n_jobs , n_machines , jssp_problem , activate_schedule , time_log )
919+ self .individual_type = individual_type
920+ self .reset_fraction = reset_fraction
921+ self .rotation_angles = rotation_angles
922+ self .std_deltas = std_deltas
923+ self .Individual_cfg = individual_cfg
924+ self .group_partitions = group_partitions
925+ self .initialize_population (time_log )
926+ self .evaluate_fitness ()
927+
928+ def evaluate_fitness (self ):
929+ for cur_chromosome in self .R :
930+ # make measurement
931+ cur_chromosome .measure ()
932+ # Convert bit string to operation based representation
933+ cur_chromosome .convert_permutation ()
934+ # Create schedule to evaluate fitness
935+ cur_chromosome .create_schedule (
936+ self .decoding_method ,
937+ self .jssp_problem ,
938+ self .activate_schedule
939+ )
940+ # Fintess values are available as self.R[i].schedule.max_completion_time
941+
942+ def initialize_population (self , time_log : bool = False ):
943+ """Method for populating the population with individuals. Generates random qubit chromosomes.
944+
945+ Parameters
946+ ----------
947+ time_log : bool, optional
948+ Logging durations of different components in representation, by default False
949+ """
950+ # P is index 0 - N-1, while Q is index N - 2N
951+ cur_individual_type = eval (self .individual_type )
952+ self .R = np .empty (2 * self .N , dtype = cur_individual_type )
953+ for i in range (len (self .R )):
954+ self .R [i ] = cur_individual_type (self .n_jobs , self .n_machines , self .Individual_cfg , time_log = time_log )
955+
956+ def execute_quantum_update (self , c : int , c_tot : int ):
957+ """This method is used to perform recombination for the QMEA algorithm
958+
959+ Parameters
960+ ----------
961+ c : int
962+ The current generation number
963+ c_tot : int
964+ The total generation to run
965+
966+ Raises
967+ ------
968+ Exception
969+ The groups of solutions should contains more solutions than 0.
970+ """
971+ population_size = self .N * 2 * (1 - self .reset_fraction )
972+ # Divide the parents into equal groups
973+ S = int (np .floor (population_size / self .group_partitions ))
974+ if S <= 0 :
975+ raise Exception ("The groups of solutions should contains more solutions than 0. Please adjust the n_groups parameter." )
976+
977+ group = np .arange (1 , self .group_partitions , 1 )* S
978+ for g in group :
979+ for s in range (S ):
980+ # For each solution in the best group, use it to rotate the solution
981+ # Solutions in other groups are given by S*group + s
982+ self .R [g + s ].rotate (self .R [s ], c = c , c_tot = c_tot , n_groups = self .group_partitions , cur_group = g , rotation_angles = self .rotation_angles , std_deltas = self .std_deltas )
983+
984+ # Reset remaining solutions
985+ reset_index = int (self .N * 2 * (1 - self .reset_fraction ))
986+ for remaining in self .R [reset_index :]:
987+ remaining .initialize_individual ()
988+
989+ # Set the genes of the best group
990+ for s in range (S ):
991+ self .R [s ].positions = self .R [s ].random_keys
992+ self .R [s ].standard_deviations = np .zeros_like (self .R [s ].random_keys )
993+
994+ # Reset individuals that are duplicated
995+ cur_range = self .get_front_range (0 )
996+ front_indexes = np .arange (cur_range [0 ], cur_range [1 ]).tolist ()
997+ while len (front_indexes ) > 0 :
998+ cur_makespan , cur_flow = self .R [front_indexes [0 ]].cur_fitness
999+ temp_front_indexes = []
1000+ for j in range (1 , len (front_indexes )):
1001+ comp_makespan , comp_flow = self .R [front_indexes [j ]].cur_fitness
1002+ if cur_makespan == comp_makespan and cur_flow == comp_flow :
1003+ # Reset the duplicate to initial positions
1004+ self .R [front_indexes [j ]].initialize_individual ()
1005+ temp_front_indexes .append (j )
1006+
1007+
9011008 front_indexes = temp_front_indexes
0 commit comments