danidanidani commited on
Commit
ff9b6c0
1 Parent(s): 1d3caec

Update src/backend/optimization_algo.py

Browse files
Files changed (1) hide show
  1. src/backend/optimization_algo.py +60 -46
src/backend/optimization_algo.py CHANGED
@@ -5,7 +5,8 @@ import streamlit as st
5
  # import all functions from src.backend.chatbot
6
  from src.backend.chatbot import *
7
 
8
- def genetic_algorithm_plants():
 
9
  # Define the compatibility matrix
10
  compatibility_matrix = st.session_state.full_mat
11
  # Define the list of plants
@@ -16,31 +17,30 @@ def genetic_algorithm_plants():
16
  num_plant_beds = st.session_state.n_plant_beds
17
  # 1 <= min_species_per_bed <= max_species_per_bed <= len(user_plants)
18
  min_species_per_bed = st.session_state.min_species
19
- # max_species_per_bed >= floor(length(user_plants)-(min_species_per_bed*num_plant_beds-1) & max_species_per_bed <= len(user_plants)
20
  max_species_per_bed = st.session_state.max_species
21
 
22
-
23
  # Genetic Algorithm parameters
24
  population_size = st.session_state.population_size
25
  num_generations = st.session_state.num_generations
26
  tournament_size = st.session_state.tournament_size
27
  crossover_rate = st.session_state.crossover_rate
28
  mutation_rate = st.session_state.mutation_rate
29
- seed_population_rate = st.session_state.seed_population_rate
30
-
31
 
32
- def generate_initial_population():
33
  population = []
34
 
35
  # Add seed groupings to the population, validated and replaced as necessary
36
- num_seeds = int(population_size * st.session_state.seed_population_rate) # 10% of the population as seeds
 
 
37
  # we generate just one seed grouping for this beta language model suggestion feature
38
- seed_grouping = get_language_model_suggestions()
39
  if seed_grouping != "no response yet":
40
  valid_seed_grouping = validate_and_replace(seed_grouping)
41
  population.append(valid_seed_grouping)
42
 
43
-
44
  # Fill the rest of the population with random groupings, also validated and replaced
45
  while len(population) < population_size:
46
  random_grouping = generate_random_grouping()
@@ -49,7 +49,6 @@ def genetic_algorithm_plants():
49
 
50
  return population
51
 
52
-
53
  def generate_random_grouping():
54
  random.shuffle(user_plants)
55
  remaining_plants = user_plants.copy()
@@ -67,7 +66,9 @@ def genetic_algorithm_plants():
67
  num_species_in_bed = plants_per_bed
68
 
69
  # Ensure the bed size is within the min and max constraints
70
- num_species_in_bed = max(min_species_per_bed, min(num_species_in_bed, max_species_per_bed))
 
 
71
 
72
  bed = remaining_plants[:num_species_in_bed]
73
  remaining_plants = remaining_plants[num_species_in_bed:]
@@ -75,8 +76,6 @@ def genetic_algorithm_plants():
75
 
76
  return grouping
77
 
78
-
79
-
80
  # Perform crossover between two parents, preserving at least one occurrence of each plant
81
  def crossover(parent1, parent2):
82
  if random.random() < crossover_rate:
@@ -88,17 +87,21 @@ def genetic_algorithm_plants():
88
  for plant in user_plants:
89
  if all(plant not in bed for bed in child1):
90
  # Find a bed with fewer species and add the missing plant
91
- min_bed_index = min(range(len(child1)), key=lambda i: len(child1[i]))
 
 
92
  child1[min_bed_index].append(plant)
93
  if all(plant not in bed for bed in child2):
94
  # Find a bed with fewer species and add the missing plant
95
- min_bed_index = min(range(len(child2)), key=lambda i: len(child2[i]))
 
 
96
  child2[min_bed_index].append(plant)
97
 
98
  return child1, child2
99
  else:
100
  return parent1, parent2
101
-
102
  # Perform mutation on an individual, ensuring no bed exceeds the maximum species constraint
103
  def mutate(individual):
104
  if random.random() < mutation_rate:
@@ -110,8 +113,12 @@ def genetic_algorithm_plants():
110
  species_in_bed = random.sample(species_in_bed, max_species_per_bed)
111
 
112
  # Add missing plants by performing swaps between current species and missing plants
113
- missing_plants = [plant for plant in user_plants if plant not in species_in_bed]
114
- num_missing_plants = min(len(missing_plants), max_species_per_bed - len(species_in_bed))
 
 
 
 
115
  for _ in range(num_missing_plants):
116
  swap_species = random.choice(missing_plants)
117
  missing_plants.remove(swap_species)
@@ -124,8 +131,12 @@ def genetic_algorithm_plants():
124
 
125
  # Calculate the fitness score of the grouping
126
  def calculate_fitness(grouping):
127
- positive_reward_factor = 1000 # Adjust this to increase the reward for compatible species
128
- negative_penalty_factor = 2000 # Adjust this to increase the penalty for incompatible species
 
 
 
 
129
 
130
  # Define penalties for not meeting constraints
131
  penalty_for_exceeding_max = 500 # Adjust as needed
@@ -144,15 +155,16 @@ def genetic_algorithm_plants():
144
  species2_index = plant_list.index(species2_name)
145
 
146
  # Compatibility score between two species in the same bed
147
- compatibility_score = compatibility_matrix[species1_index][species2_index]
148
-
 
 
149
  if compatibility_score > 0:
150
  # Positive reward for compatible species
151
- score += compatibility_score*positive_reward_factor
152
  elif compatibility_score < 0:
153
  # Negative penalty for incompatible species
154
- score += compatibility_score*negative_penalty_factor
155
-
156
 
157
  # Apply penalties for not meeting constraints
158
  if len(bed) > max_species_per_bed:
@@ -164,7 +176,6 @@ def genetic_algorithm_plants():
164
 
165
  return score
166
 
167
-
168
  # Perform tournament selection
169
  def tournament_selection(population):
170
  selected = []
@@ -189,11 +200,14 @@ def genetic_algorithm_plants():
189
  individual[bed_idx] = species_in_bed
190
  adjusted_offspring.append(individual)
191
 
192
- return sorted_population[:population_size - len(adjusted_offspring)] + adjusted_offspring
 
 
 
193
 
194
  # Genetic Algorithm main function
195
- def genetic_algorithm():
196
- population = generate_initial_population()
197
 
198
  for generation in range(num_generations):
199
  print(f"Generation {generation + 1}")
@@ -213,7 +227,6 @@ def genetic_algorithm_plants():
213
  # Validate and replace any missing plants in the new population
214
  population = [validate_and_replace(grouping) for grouping in population]
215
 
216
-
217
  best_grouping = max(population, key=calculate_fitness)
218
  best_grouping = validate_and_replace(best_grouping)
219
  best_fitness = calculate_fitness(best_grouping)
@@ -224,7 +237,7 @@ def genetic_algorithm_plants():
224
  # st.write(f"Best Grouping: {best_grouping}")
225
  # st.write(f"Fitness Score: {best_fitness}")
226
  return best_grouping
227
-
228
  # def validate_and_replace(grouping):
229
  # print("Grouping structure before validation:", grouping)
230
  # all_plants = set(user_plants)
@@ -250,18 +263,20 @@ def genetic_algorithm_plants():
250
  # random_bed[random.randint(0, len(random_bed) - 1)] = missing_plant
251
 
252
  # return grouping
253
-
254
  ############
255
  ############ experimental
256
 
257
  def adjust_grouping(grouping):
258
- # Determine the plants that are missing in the grouping
259
  plants_in_grouping = set(plant for bed in grouping for plant in bed)
260
  missing_plants = set(user_plants) - plants_in_grouping
261
 
262
  for missing_plant in missing_plants:
263
  # Find a bed that can accommodate the missing plant without exceeding max_species_per_bed
264
- suitable_bed = next((bed for bed in grouping if len(bed) < max_species_per_bed), None)
 
 
265
  if suitable_bed is not None:
266
  suitable_bed.append(missing_plant)
267
  else:
@@ -272,16 +287,18 @@ def genetic_algorithm_plants():
272
  # Ensure min_species_per_bed and max_species_per_bed constraints
273
  for bed in grouping:
274
  while len(bed) < min_species_per_bed:
275
- additional_plant = random.choice([plant for plant in user_plants if plant not in bed])
 
 
276
  bed.append(additional_plant)
277
  while len(bed) > max_species_per_bed:
278
  bed.remove(random.choice(bed))
279
 
280
  return grouping
281
-
282
  def validate_and_replace(grouping):
283
  best_grouping = None
284
- best_fitness = float('-inf')
285
 
286
  for _ in range(5): # Generate 5 different configurations
287
  temp_grouping = [bed.copy() for bed in grouping]
@@ -294,16 +311,13 @@ def genetic_algorithm_plants():
294
 
295
  return best_grouping
296
 
297
-
298
-
299
  ############
300
- def get_language_model_suggestions():
301
- # Placeholder for your implementation
302
- # This should return a list of seed groupings based on the compatibility matrix
303
- st.session_state.seed_groupings = get_seed_groupings_from_LLM()
304
  return st.session_state.seed_groupings
305
 
 
306
 
307
-
308
- best_grouping = genetic_algorithm()
309
- return best_grouping
 
5
  # import all functions from src.backend.chatbot
6
  from src.backend.chatbot import *
7
 
8
+
9
+ def genetic_algorithm_plants(model, demo_lite):
10
  # Define the compatibility matrix
11
  compatibility_matrix = st.session_state.full_mat
12
  # Define the list of plants
 
17
  num_plant_beds = st.session_state.n_plant_beds
18
  # 1 <= min_species_per_bed <= max_species_per_bed <= len(user_plants)
19
  min_species_per_bed = st.session_state.min_species
20
+ # max_species_per_bed >= floor(length(user_plants)-(min_species_per_bed*num_plant_beds-1) & max_species_per_bed <= len(user_plants)
21
  max_species_per_bed = st.session_state.max_species
22
 
 
23
  # Genetic Algorithm parameters
24
  population_size = st.session_state.population_size
25
  num_generations = st.session_state.num_generations
26
  tournament_size = st.session_state.tournament_size
27
  crossover_rate = st.session_state.crossover_rate
28
  mutation_rate = st.session_state.mutation_rate
29
+ seed_population_rate = st.session_state.seed_population_rate
 
30
 
31
+ def generate_initial_population(model, demo_lite):
32
  population = []
33
 
34
  # Add seed groupings to the population, validated and replaced as necessary
35
+ num_seeds = int(
36
+ population_size * st.session_state.seed_population_rate
37
+ ) # 10% of the population as seeds
38
  # we generate just one seed grouping for this beta language model suggestion feature
39
+ seed_grouping = get_language_model_suggestions(model, demo_lite)
40
  if seed_grouping != "no response yet":
41
  valid_seed_grouping = validate_and_replace(seed_grouping)
42
  population.append(valid_seed_grouping)
43
 
 
44
  # Fill the rest of the population with random groupings, also validated and replaced
45
  while len(population) < population_size:
46
  random_grouping = generate_random_grouping()
 
49
 
50
  return population
51
 
 
52
  def generate_random_grouping():
53
  random.shuffle(user_plants)
54
  remaining_plants = user_plants.copy()
 
66
  num_species_in_bed = plants_per_bed
67
 
68
  # Ensure the bed size is within the min and max constraints
69
+ num_species_in_bed = max(
70
+ min_species_per_bed, min(num_species_in_bed, max_species_per_bed)
71
+ )
72
 
73
  bed = remaining_plants[:num_species_in_bed]
74
  remaining_plants = remaining_plants[num_species_in_bed:]
 
76
 
77
  return grouping
78
 
 
 
79
  # Perform crossover between two parents, preserving at least one occurrence of each plant
80
  def crossover(parent1, parent2):
81
  if random.random() < crossover_rate:
 
87
  for plant in user_plants:
88
  if all(plant not in bed for bed in child1):
89
  # Find a bed with fewer species and add the missing plant
90
+ min_bed_index = min(
91
+ range(len(child1)), key=lambda i: len(child1[i])
92
+ )
93
  child1[min_bed_index].append(plant)
94
  if all(plant not in bed for bed in child2):
95
  # Find a bed with fewer species and add the missing plant
96
+ min_bed_index = min(
97
+ range(len(child2)), key=lambda i: len(child2[i])
98
+ )
99
  child2[min_bed_index].append(plant)
100
 
101
  return child1, child2
102
  else:
103
  return parent1, parent2
104
+
105
  # Perform mutation on an individual, ensuring no bed exceeds the maximum species constraint
106
  def mutate(individual):
107
  if random.random() < mutation_rate:
 
113
  species_in_bed = random.sample(species_in_bed, max_species_per_bed)
114
 
115
  # Add missing plants by performing swaps between current species and missing plants
116
+ missing_plants = [
117
+ plant for plant in user_plants if plant not in species_in_bed
118
+ ]
119
+ num_missing_plants = min(
120
+ len(missing_plants), max_species_per_bed - len(species_in_bed)
121
+ )
122
  for _ in range(num_missing_plants):
123
  swap_species = random.choice(missing_plants)
124
  missing_plants.remove(swap_species)
 
131
 
132
  # Calculate the fitness score of the grouping
133
  def calculate_fitness(grouping):
134
+ positive_reward_factor = (
135
+ 1000 # Adjust this to increase the reward for compatible species
136
+ )
137
+ negative_penalty_factor = (
138
+ 2000 # Adjust this to increase the penalty for incompatible species
139
+ )
140
 
141
  # Define penalties for not meeting constraints
142
  penalty_for_exceeding_max = 500 # Adjust as needed
 
155
  species2_index = plant_list.index(species2_name)
156
 
157
  # Compatibility score between two species in the same bed
158
+ compatibility_score = compatibility_matrix[species1_index][
159
+ species2_index
160
+ ]
161
+
162
  if compatibility_score > 0:
163
  # Positive reward for compatible species
164
+ score += compatibility_score * positive_reward_factor
165
  elif compatibility_score < 0:
166
  # Negative penalty for incompatible species
167
+ score += compatibility_score * negative_penalty_factor
 
168
 
169
  # Apply penalties for not meeting constraints
170
  if len(bed) > max_species_per_bed:
 
176
 
177
  return score
178
 
 
179
  # Perform tournament selection
180
  def tournament_selection(population):
181
  selected = []
 
200
  individual[bed_idx] = species_in_bed
201
  adjusted_offspring.append(individual)
202
 
203
+ return (
204
+ sorted_population[: population_size - len(adjusted_offspring)]
205
+ + adjusted_offspring
206
+ )
207
 
208
  # Genetic Algorithm main function
209
+ def genetic_algorithm(model, demo_lite):
210
+ population = generate_initial_population(model, demo_lite)
211
 
212
  for generation in range(num_generations):
213
  print(f"Generation {generation + 1}")
 
227
  # Validate and replace any missing plants in the new population
228
  population = [validate_and_replace(grouping) for grouping in population]
229
 
 
230
  best_grouping = max(population, key=calculate_fitness)
231
  best_grouping = validate_and_replace(best_grouping)
232
  best_fitness = calculate_fitness(best_grouping)
 
237
  # st.write(f"Best Grouping: {best_grouping}")
238
  # st.write(f"Fitness Score: {best_fitness}")
239
  return best_grouping
240
+
241
  # def validate_and_replace(grouping):
242
  # print("Grouping structure before validation:", grouping)
243
  # all_plants = set(user_plants)
 
263
  # random_bed[random.randint(0, len(random_bed) - 1)] = missing_plant
264
 
265
  # return grouping
266
+
267
  ############
268
  ############ experimental
269
 
270
  def adjust_grouping(grouping):
271
+ # Determine the plants that are missing in the grouping
272
  plants_in_grouping = set(plant for bed in grouping for plant in bed)
273
  missing_plants = set(user_plants) - plants_in_grouping
274
 
275
  for missing_plant in missing_plants:
276
  # Find a bed that can accommodate the missing plant without exceeding max_species_per_bed
277
+ suitable_bed = next(
278
+ (bed for bed in grouping if len(bed) < max_species_per_bed), None
279
+ )
280
  if suitable_bed is not None:
281
  suitable_bed.append(missing_plant)
282
  else:
 
287
  # Ensure min_species_per_bed and max_species_per_bed constraints
288
  for bed in grouping:
289
  while len(bed) < min_species_per_bed:
290
+ additional_plant = random.choice(
291
+ [plant for plant in user_plants if plant not in bed]
292
+ )
293
  bed.append(additional_plant)
294
  while len(bed) > max_species_per_bed:
295
  bed.remove(random.choice(bed))
296
 
297
  return grouping
298
+
299
  def validate_and_replace(grouping):
300
  best_grouping = None
301
+ best_fitness = float("-inf")
302
 
303
  for _ in range(5): # Generate 5 different configurations
304
  temp_grouping = [bed.copy() for bed in grouping]
 
311
 
312
  return best_grouping
313
 
 
 
314
  ############
315
+ def get_language_model_suggestions(model, demo_lite):
316
+ # This returns a list of seed groupings based on the compatibility matrix
317
+ st.session_state.seed_groupings = get_seed_groupings_from_LLM(model, demo_lite)
 
318
  return st.session_state.seed_groupings
319
 
320
+ # Run the genetic algorithm
321
 
322
+ best_grouping = genetic_algorithm(model, demo_lite)
323
+ return best_grouping