import matplotlib.pyplot as plt import pickle from src.cocktails.utilities.cocktail_generation_utilities.population import * from src.cocktails.utilities.glass_and_volume_utilities import glass_volume from src.cocktails.config import RECIPE2FEATURES_PATH def test_mutation_params(cocktail_reps): indexes = np.arange(cocktail_reps.shape[0]) np.random.shuffle(indexes) perfs = [] mutated_perfs = [] pop_params = dict(mutation_params=dict(p_add_ing=0.7, p_remove_ing=0.7, p_switch_ing=0.5, p_change_q=0.7, delta_change_q=0.3, asexual_rep=True, crossover=True, ingredient_addition=(0.1, 0.05)), nb_generations=100, pop_size=100, nb_elites=10, dist='mse', n_neighbors=5) for i in indexes[:20]: target = cocktail_reps[i] for j in range(100): parent = IndividualCocktail(pop_params=pop_params, target_affective_cluster=None, target=target.copy()) perfs.append(parent.perf) child = parent.get_child()[0] # child.compute_cocktail_rep() # child.compute_perf() if perfs[-1] != child.perf: mutated_perfs.append(child.perf) else: perfs.pop(-1) filtered_children = np.argwhere(np.array(mutated_perfs)==-100).flatten() non_filtered_ids = np.argwhere(np.logical_and(np.array(perfs)!=-100, np.array(mutated_perfs)!=-100)).flatten() print(f'Proportion of filtered: {filtered_children.size} / {len(mutated_perfs)} = {int(filtered_children.size / len(mutated_perfs)*100)}%') plt.figure() plt.scatter(np.array(perfs)[non_filtered_ids], np.array(mutated_perfs)[non_filtered_ids], s=100, alpha=0.5) plt.xlabel('parent perf') plt.ylabel('child perf') print(np.corrcoef(np.array(perfs)[non_filtered_ids], np.array(mutated_perfs)[non_filtered_ids])[0, 1]) plt.show() stop = 1 def test_crossover(cocktail_reps): indexes = np.arange(cocktail_reps.shape[0]) np.random.shuffle(indexes) perfs = [] mutated_perfs = [] pop_params = dict(mutation_params=dict(p_add_ing=0.7, p_remove_ing=0.7, p_switch_ing=0.5, p_change_q=0.7, delta_change_q=0.3, asexual_rep=True, crossover=True, ingredient_addition=(0.1, 0.05)), nb_generations=100, pop_size=100, nb_elites=10, dist='mse', n_neighbors=5) for i in indexes[:20]: for j in range(100): target = cocktail_reps[i] parent1 = IndividualCocktail(pop_params=pop_params, target_affective_cluster=None, target=target.copy()) parent2 = IndividualCocktail(pop_params=pop_params, target_affective_cluster=None, target=target.copy()) child = parent1.get_child_with(parent2)[0] # child.compute_cocktail_rep() # child.compute_perf() perfs.append((parent1.perf + parent2.perf)/2) if perfs[-1] != child.perf: mutated_perfs.append(child.perf) else: perfs.pop(-1) filtered_children = np.argwhere(np.array(mutated_perfs)==-100).flatten() non_filtered_ids = np.argwhere(np.logical_and(np.array(perfs)>-45, np.array(mutated_perfs)!=-100)).flatten() print(f'Proportion of filtered: {filtered_children.size} / {len(mutated_perfs)} = {int(filtered_children.size / len(mutated_perfs)*100)}%') plt.figure() plt.scatter(np.array(perfs)[non_filtered_ids], np.array(mutated_perfs)[non_filtered_ids], s=100, alpha=0.5) plt.xlabel('parent perf') plt.ylabel('child perf') print(np.corrcoef(np.array(perfs)[non_filtered_ids], np.array(mutated_perfs)[non_filtered_ids])[0, 1]) plt.show() stop = 1 def run_comparisons(): np.random.seed(0) indexes = np.arange(cocktail_reps.shape[0]) np.random.shuffle(indexes) for n_neighbors in [0, 5]: id_str_neigh = '5neigh_' if n_neighbors == 5 else '0_neigh_' for asexual_rep in [True, False]: id_str_as = id_str_neigh + 'asexual_' if asexual_rep else id_str_neigh for crossover in [True, False]: id_str = id_str_as + 'crossover_' if crossover else id_str_as if crossover or asexual_rep: mutation_params = dict(p_add_ing = 0.5, p_remove_ing = 0.5, p_change_q = 0.5, delta_change_q = 0.3, asexual_rep=asexual_rep, crossover=crossover, ingredient_addition = (0.1, 0.05)) nb_generations = 100 pop_size=100 nb_elites=10 dist = 'mse' results = dict() print(id_str) for i, ind in enumerate(indexes[:30]): print(i+1) target_ing_str = data['ingredients_str'][ind] target = cocktail_reps[ind] population = Population(nb_generations=nb_generations, pop_size=pop_size, nb_elite=nb_elites, target=target, dist=dist, mutation_params=mutation_params, n_neighbors=n_neighbors, target_ing_str=target_ing_str, true_prep_type=data['category'][ind]) population.run_evolution(verbose=False) best_scores, best_ind = population.get_best_score() recipes = [ind.get_recipe()[3] for ind in best_ind[:5]] results[str(ind)] = dict(best_scores=best_scores[:5], recipes=recipes, target=population.target_individual.get_recipe()[3]) with open(f'/home/cedric/Desktop/ga_tests_{id_str}.pickle', 'wb') as f: pickle.dump(results, f) def get_cocktail_distribution(cocktail_reps): return (np.mean(cocktail_reps, axis=0), np.cov(cocktail_reps, rowvar=0)) def sample_cocktails(cocktail_reps, n=10, target_affective_cluster=None, to_print=True): distrib = get_cocktail_distribution(cocktail_reps) sampled_cocktail_reps = np.random.multivariate_normal(distrib[0], distrib[1], size=n) recipes = [] closest_recipes = [] for i_c, cr in enumerate(sampled_cocktail_reps): population = setup_recipe_generation(cr.copy(), target_affective_cluster=target_affective_cluster) closest_recipes.append(population.nn_recipes[0]) best_scores, best_individuals = population.run_evolution() recipes.append(best_individuals[0].get_recipe()[3]) if to_print: print(f'Sample #{len(recipes)}:') print(recipes[-1]) print('Closest from dataset:') print(closest_recipes[-1]) stop = 1 return recipes, closest_recipes def setup_recipe_generation(target, known_target_dict=None, target_affective_cluster=None): # pop_params = dict(mutation_params=dict(p_add_ing=0.7, # p_remove_ing=0.7, # p_switch_ing=0.5, # p_change_q=0.7, # delta_change_q=0.3, # asexual_rep=True, # crossover=True, # ingredient_addition=(0.1, 0.05)), # nb_generations=2, #100 # pop_size=5, #100 # nb_elites=2, #10 # dist='mse', # n_neighbors=3) #5 pop_params = dict(mutation_params=dict(p_add_ing=0.4, p_remove_ing=1, p_switch_ing=0.5, p_change_q=1, delta_change_q=0.3, asexual_rep=True, crossover=True, ingredient_addition=(0.1, 0.05)), nb_generations=100, # 100 pop_size=100, # 100 nb_elites=10, # 10 dist='mse', n_neighbors=5) # 5 population = Population(target=target, target_affective_cluster=target_affective_cluster, known_target_dict=known_target_dict, pop_params=pop_params) return population def cocktailrep2recipe(cocktail_rep, unit='mL', target_affective_cluster=None, known_target_dict=None, n_output=1, return_ind=False, verbose=True, full_verbose=False, level=0): init_time = time.time() if verbose: print(' ' * level + 'Generating cocktail..') if cocktail_rep.ndim > 1: assert cocktail_rep.shape[0] == 1 cocktail_rep = cocktail_rep.flatten() # target_affective_cluster = target_affective_cluster[0] population = setup_recipe_generation(cocktail_rep.copy(), known_target_dict=known_target_dict, target_affective_cluster=target_affective_cluster) if full_verbose: print(' ' * (level + 2) + '3 nearest neighbors:') for i, recipe, score in zip(range(3), population.nn_recipes[:3], population.nn_scores[:3]): print(' ' * (level + 4) + f'#{i+1}, score: {score:.2f}') print(' ' * (level + 4) + recipe[1:].replace('None ()', '').replace('\t\t', ' ' * (level + 6))) best_scores, best_individuals = population.run_evolution(verbose=full_verbose, level=level+2) for i in range(n_output): best_individuals[i].make_recipe_fit_the_glass() instructions = [ind.get_instructions() for ind in best_individuals[:n_output]] recipes = [ind.get_recipe(unit=unit)[3] for ind in best_individuals[:n_output]] glasses = [ind.glass for ind in best_individuals[:n_output]] prep_types = [ind.prep_type for ind in best_individuals[:n_output]] for i, g, p, inst in zip(range(len(recipes)), glasses, prep_types, instructions): recipes[i] = recipes[i].replace('Recipe', 'Ingredients') + f'Serve in:\n {g.capitalize()} glass.\n' + inst if full_verbose: print(f'\n--------------\n{n_output} best results:') for i, recipe, score in zip(range(n_output), recipes, best_scores[:n_output]): print(f'#{i+1}, score: {score:.2f}') print(recipe) if verbose: print(' ' * (level + 2) + f'Generated in {int(time.time() - init_time)} seconds.') if return_ind: return recipes, best_scores[:n_output], best_individuals[:n_output] else: return recipes, best_scores[:n_output] def interpolate(cocktail_rep1, cocktail_rep2, alpha, verbose=False): recipe, score = cocktailrep2recipe(alpha * cocktail_rep1 + (1 - alpha) * cocktail_rep2, verbose=verbose) return recipe[0], score def interpolation_study(n_steps, cocktail_reps): alphas = np.arange(0, 1 + 1e-6, 1/(n_steps + 1)) indexes = np.random.choice(np.arange(cocktail_reps.shape[0]), size=2, replace=False) target_ing_str1, target_ing_str2 = data['ingredients_str'][indexes[0]], data['ingredients_str'][indexes[1]] cocktail_rep1, cocktail_rep2 = cocktail_reps[indexes[0]], cocktail_reps[indexes[1]] recipes, scores = [], [] for alpha in alphas: recipe, score = interpolate(cocktail_rep1, cocktail_rep2, alpha) recipes.append(recipe) scores.append(score[0]) print('Point A:') print_recipe(ingredient_str=target_ing_str2) for i, alpha in enumerate(alphas): print(f'Alpha = {alpha}, score = {scores[i]}') print(recipes[i]) print('Point B:') print_recipe(ingredient_str=target_ing_str1) stop = 1 def test_robustness_affective_cluster(cocktail_reps): indexes = np.arange(cocktail_reps.shape[0]) np.random.shuffle(indexes) matches = [] for i in indexes: target_ing_str = data['ingredients_str'][i] true_prep_type = data['category'][i] target = cocktail_reps[i] # get affective cluster recipes, best_scores, best_inds = cocktailrep2recipe(cocktail_rep=target, target_ing_str=target_ing_str, true_prep_type=true_prep_type, n_output=1, verbose=False, return_ind=True) matches.append(best_inds[0].does_affective_cluster_match()) print(np.mean(matches)) def test(cocktail_reps): indexes = np.arange(these_cocktail_reps.shape[0]) unnormalized_cr = np.array([data[k] for k in rep_keys]).transpose() for i in indexes: target_ing_str = data['ingredients_str'][i] true_prep_type = data['category'][i] target = these_cocktail_reps[i] # print('preptype:', true_prep_type) # print('cocktail unnormalized', np.sum(unnormalized_cr[i]), unnormalized_cr[i]) # print('cocktail hand normalized', np.sum(normalize_cocktail(unnormalized_cr[i])), normalize_cocktail(unnormalized_cr[i])) # print('cocktail rep normalized', np.sum(these_cocktail_reps[i]), these_cocktail_reps[i]) # print('cocktail rep normalized', np.sum(all_reps[i]), all_reps[i]) population = setup_recipe_generation(target.copy(), target_ing_str=target_ing_str, target_affective_cluster=None, true_prep_type=true_prep_type) target = population.target_individual target.compute_perf() if target.perf < -50: print(i) print_recipe(target_ing_str) if not target.is_alcohol_present(): print('No alcohol') if not target.is_total_volume_enough(): print('small volume') if not target.does_fit_glass(): print(target.end_volume) print(glass_volume[target.get_glass_type()] * 0.81) print('too much volume') if not target.is_alcohol_reasonable(): print(f'amount of alcohol too small or too large: {target.alcohol_precentage}') stop = 1 if __name__ == '__main__': these_cocktail_reps = COCKTAIL_REPS.copy() # test_crossover(these_cocktail_reps) # test_mutation_params(these_cocktail_reps) # test(these_cocktail_reps) # recipes, closest_recipes = sample_cocktails(these_cocktail_reps, n=10) # interpolation_study(n_steps=4, cocktail_reps=these_cocktail_reps) # test_robustness_affective_cluster(these_cocktail_reps) indexes = np.arange(these_cocktail_reps.shape[0]) np.random.shuffle(indexes) # test_crossover(mutation_params, dist) # test_mutation_params(mutation_params, dist) stop = 1 unnormalized_cr = np.array([data[k] for k in rep_keys]).transpose() for i in indexes: print(i) target_ing_str = data['ingredients_str'][i] target_prep_type = data['category'][i] target_glass = data['glass'][i] print('preptype:', target_prep_type) print('cocktail unnormalized', np.sum(unnormalized_cr[i]), unnormalized_cr[i]) print('cocktail hand normalized', np.sum(normalize_cocktail(unnormalized_cr[i])), normalize_cocktail(unnormalized_cr[i])) print('cocktail rep normalized', np.sum(these_cocktail_reps[i]), these_cocktail_reps[i]) print('cocktail rep normalized', np.sum(all_reps[i]), all_reps[i]) print(i) print('___________Target') nn_model = NearestNeighbors() nn_model.fit(these_cocktail_reps) dists, indexes = nn_model.kneighbors(these_cocktail_reps[i].reshape(1, -1)) print(indexes) print_recipe(target_ing_str) target = these_cocktail_reps[i] known_target_dict = dict(prep_type=target_prep_type, ing_str=target_ing_str, glass=target_glass) recipes, best_scores = cocktailrep2recipe(cocktail_rep=target, known_target_dict=known_target_dict, n_output=1, verbose=True, full_verbose=True) stop = 1