Meatballs / app.py
rasyidf
Update Meatball
ea88eb3
import random
import numpy as np
import streamlit as st
# Default parameter ranges
default_param_ranges = {
'beef': (400, 600),
'cornflour': (80, 120),
'garlic': (2, 4),
'cilantro': (10, 20),
'salt': (0.5, 1.5),
'pepper': (0.25, 0.75),
'baking_powder': (0.25, 0.75)
}
# Explanations for each parameter
param_explanations = {
'beef': 'Amount of beef in grams.',
'cornflour': 'Amount of cornflour in grams.',
'garlic': 'Number of garlic cloves.',
'cilantro': 'Amount of cilantro in grams.',
'salt': 'Amount of salt in teaspoons.',
'pepper': 'Amount of pepper in teaspoons.',
'baking_powder': 'Amount of baking powder in teaspoons.'
}
def generate_recipe(param_ranges):
return {k: random.uniform(v[0], v[1]) for k, v in param_ranges.items()}
def simulate_mixing(recipe, mix_factor):
beef = recipe['beef']
cornflour = recipe['cornflour']
# Simulate mixing by dividing beef by cornflour and adding mix factor
# If cornflour is 0, return 0
if cornflour == 0:
return 0
mix_factor = (beef / cornflour) + mix_factor
# If mix factor is greater than 1, return 1
if mix_factor > 1:
return 1
return mix_factor
def evaluate_squishiness(recipe):
beef = recipe['beef']
cornflour = recipe['cornflour']
baking_powder = recipe['baking_powder']
squishiness = (beef / cornflour) + (baking_powder * 10)
return squishiness
def evaluate_meat_taste(recipe, taste_weights):
beef = recipe['beef']
garlic = recipe['garlic']
cilantro = recipe['cilantro']
meat_taste = (beef * taste_weights['beef']) + (garlic * taste_weights['garlic']) + (cilantro * taste_weights['cilantro'])
return meat_taste
def evaluate_consistency(recipe, mix_factor):
beef = recipe['beef']
cornflour = recipe['cornflour']
consistency = (beef / cornflour) * mix_factor
return consistency
def evaluate_fitness(recipe, weights, mix_factor, taste_weights):
squishiness = evaluate_squishiness(recipe)
meat_taste = evaluate_meat_taste(recipe, taste_weights)
consistency = evaluate_consistency(recipe, mix_factor)
fitness = (squishiness * weights['squishiness']) + (meat_taste * weights['meat_taste']) + (consistency * weights['consistency'])
return fitness
def genetic_algorithm(param_ranges, weights, pop_size=100, generations=50, mutation_rate=0.1, mix_factor=0.1, taste_weights=None):
population = [generate_recipe(param_ranges) for _ in range(pop_size)]
for gen in range(generations):
fitness_scores = [evaluate_fitness(recipe, weights, mix_factor, taste_weights) for recipe in population]
parents = select_parents(population, fitness_scores, pop_size // 2)
offspring = []
for i in range(0, len(parents), 2):
if i + 1 < len(parents):
child = crossover(parents[i], parents[i + 1])
child = mutate(child, mutation_rate, param_ranges)
offspring.append(child)
population = parents + offspring
best_recipe = select_parents(population, fitness_scores, 1)[0]
return best_recipe
def select_parents(population, fitness_scores, num_parents):
parents_indices = np.argsort(fitness_scores)[-num_parents:]
return [population[i] for i in parents_indices]
def crossover(parent1, parent2):
child = {}
for param in parent1.keys():
child[param] = (parent1[param] + parent2[param]) / 2
return child
def mutate(recipe, mutation_rate, param_ranges):
for param in recipe.keys():
if random.random() < mutation_rate:
recipe[param] += random.uniform(-0.1, 0.1) * recipe[param]
recipe[param] = max(param_ranges[param][0], min(recipe[param], param_ranges[param][1]))
return recipe
# Streamlit app
st.title('🧆 Meatball Recipe Simulator')
# Custom parameter ranges
st.sidebar.header('Custom Parameter Ranges')
param_ranges = {}
for param, (low, high) in default_param_ranges.items():
st.sidebar.markdown(f'**{param.capitalize()}**')
st.sidebar.write(param_explanations[param])
low_val = st.sidebar.number_input(f'{param.capitalize()} Min', value=low, key=f'{param}_min')
high_val = st.sidebar.number_input(f'{param.capitalize()} Max', value=high, key=f'{param}_max')
param_ranges[param] = (low_val, high_val)
# Weights for overall fitness
st.sidebar.header('Weights for Fitness Evaluation')
weights = {
'squishiness': st.sidebar.slider('Weight for Squishiness', 0.0, 1.0, 0.3),
'meat_taste': st.sidebar.slider('Weight for Meat Taste', 0.0, 1.0, 0.4),
'consistency': st.sidebar.slider('Weight for Consistency', 0.0, 1.0, 0.3)
}
# Weights for meat taste evaluation
st.sidebar.header('Weights for Meat Taste Evaluation')
taste_weights = {
'beef': st.sidebar.slider('Weight for Beef', 0.0, 1.0, 0.5),
'garlic': st.sidebar.slider('Weight for Garlic', 0.0, 1.0, 0.3),
'cilantro': st.sidebar.slider('Weight for Cilantro', 0.0, 1.0, 0.2)
}
# Other parameters
pop_size = st.sidebar.slider('Population Size', 50, 200, 100)
generations = st.sidebar.slider('Generations', 10, 100, 50)
mutation_rate = st.sidebar.slider('Mutation Rate', 0.01, 0.2, 0.1)
mix_factor = st.sidebar.slider('Mix Factor', 0.0, 1.0, 0.1)
if st.button('Run Simulation'):
with st.spinner('Running genetic algorithm...'):
best_recipe = genetic_algorithm(param_ranges, weights, pop_size, generations, mutation_rate, mix_factor, taste_weights)
st.subheader('Best Recipe')
for ingredient, amount in best_recipe.items():
st.write(f'{ingredient.capitalize()}: {amount:.2f}')
fitness = evaluate_fitness(best_recipe, weights, mix_factor, taste_weights)
st.write(f'Fitness Score: {fitness:.2f}')