Optimising Nutrition Reviewed By Grok AI

optimising-nutrition

I’ve been doing some more work on my nutrition optimisation script, the script is now running on a schedule via Github Actions, it now supports a number of diet types All, Vegan, Whole Food Plant Based, Nutrient Dense. Every hour it generates new recipes, it will look at the diet json files and read the exclusion and inclusion lists defined in the JSON file and then randomly select a random number of foods from the Australian Nutrition database csv along with their nutrition data and then the script will do a random number of generations of a genetic algorithm attempting to determine the number of grams per food item required to match as closely as possible to the recommended daily intake of essential vitamins and minerals for a 39 year old male (myself), it then saves the generated recipes in the github repo as JSON and HTML files and generates and index of these recipes and sorts them by score, the lower the score the better and the more the closer it is to matching the micronutrient RDI targets. There is a clean up at the end of the script that deletes recipes with a score that’s higher then the specified value and deletes any recipes over a total of 250 files, so over time the script will continue to generate better recipes and push out the ones with higher scores.

Challenges so far have been the Vegan and WFPB json files, trying to exclude all of the meat items, every time I think I’ve excluded them all I see a vegan recipe generated with a Camel or Emu or some type of fish in it and I need to exclude that item from the list and even more so for Whole Food Plant Based have to exclude the meat and all of the non whole food items like cakes and biscuits and packaged goods etc, so it’s still a work in progress.

I fed the optimising nutrition script into Grok and asked it to review the code it has provided some good suggestions that I will take on board :

review the logic of this script, I am a 39 year old male moderately active and want to generate recipes that meet 100% of my daily recommended intake of the essential vitamins and minerals, determine any issues in this script and any flaws

Grok AI Code Review

I’ll review your script for generating recipes that meet 100% of your daily recommended intake (RDI) of essential nutrients. As a 39-year-old moderately active male, your RDI values in the JSON look generally appropriate (based on standard guidelines like those from the NIH or USDA), though I’ll point out potential issues and suggest improvements. Here’s my analysis of the script’s logic and potential flaws:


Strengths of the Script

  1. Genetic Algorithm Approach: Using a genetic algorithm (GA) to optimize nutrient intake is a solid choice for this complex, multi-variable problem. It effectively balances exploration (randomness) and exploitation (optimization toward RDI targets).
  2. Flexible Nutrient Targets: The script scales RDI targets based on the number of meals, which is practical for daily planning.
  3. Detailed Reporting: The JSON and HTML reports are comprehensive, providing actionable insights into food quantities, nutrient profiles, and optimization performance.
  4. Penalty System: Differentiating penalties for under-RDI, over-RDI, and upper limits (UL), with special handling for water-soluble vs. fat-soluble vitamins, is a thoughtful approach to nutrient safety and balance.
  5. Diet Type Support: Filtering foods based on diet types (e.g., vegan, whole food plant-based) adds versatility.

Issues and Flaws

Here are the key issues I identified in the script, along with their potential impact:

1. Missing Upper Limit (UL) Enforcement

  • Problem: While the script penalizes exceeding ULs (e.g., in _calculate_nutrition_score), it doesn’t strictly enforce them. The penalty for exceeding ULs (over_ul) is randomized between 1.8 and 2.5, which may not be strong enough to prevent unsafe nutrient levels (e.g., Vitamin A at 3000 µg or Zinc at 40 mg).
  • Impact: For a 39-year-old male, exceeding ULs for certain nutrients (e.g., Vitamin A, Iron) could lead to toxicity over time.
  • Fix: Add a hard constraint in evaluate_solution to disqualify solutions exceeding ULs for critical nutrients, or increase the over_ul penalty significantly (e.g., 10x instead of 2.5x).

2. Energy (kJ) Handling is Incomplete

  • Problem: The script treats “Energy with dietary fibre, equated (kJ)” as a nutrient with an RDI (10,878 kJ) and UL (13,389 kJ), but the logic in _calculate_nutrition_score re-reads rdi.json instead of using the passed targets dictionary. This is inconsistent and assumes the JSON file is always available.
  • Impact: For a moderately active 39-year-old male, energy needs are ~10,000-11,000 kJ (2400-2600 kcal), which aligns with your RDI. However, the UL seems arbitrary and may not reflect realistic limits. Plus, the re-reading of JSON could fail if the file is missing.
  • Fix: Use the targets dictionary consistently for all nutrients, including energy. Define a more realistic UL (e.g., 15,000 kJ) based on activity level and safety margins.

3. Food Quantity Range is Limited

  • Problem: In create_solution, food amounts are initialized between 25-100g, and mutations adjust by ±20g. This range is too narrow to meet 100% RDI for a full day in one meal (your number_of_meals=1 setting).
  • Impact: With only 25-100g per food, it’s unlikely to hit high RDIs (e.g., 3400 mg Potassium, 38g Fiber) without including more foods or larger portions.
  • Fix: Increase the range (e.g., 25-500g) and adjust mutation steps proportionally. Alternatively, use a food database with serving size metadata to scale amounts realistically.

4. Nutrient Mapping Mismatch

  • Problem: The nutrient_mapping parameter in optimize_nutrition is a dictionary from rdi.json, but the script uses its keys directly as column names in food_df. However, rdi.json keys (e.g., “Protein (g)”) don’t match typical food database column names (e.g., “PROTEIN”).
  • Impact: This causes warnings ("Column not found") and sets missing nutrients to 0, skewing optimization results.
  • Fix: Create a proper mapping dictionary (e.g., {'Protein (g)': 'PROTEIN', ...}) and pass it to optimize_nutrition. Ensure food_df columns align with this mapping.

5. Single-Meal Assumption

  • Problem: You set number_of_meals=1, aiming for 100% RDI in one meal, but the script’s logic (e.g., scaling RDIs by number_of_meals) assumes multiple meals. This inconsistency could confuse results.
  • Impact: A single meal hitting 100% RDI (e.g., 10,878 kJ, 91g protein) is impractical for most people due to volume and digestion limits.
  • Fix: Either adjust number_of_meals to 3 (typical daily meals) and aim for ~33% RDI per meal, or explicitly design for a single meal with realistic portion constraints (e.g., max 1000g total food).

6. Random Food Selection

  • Problem: The script randomly selects 10-30 foods per run (n_foods = random.randint(10, 30)), which may exclude nutrient-dense options critical for meeting RDIs (e.g., spinach for folate, salmon for omega-3s).
  • Impact: This randomness reduces consistency and may fail to meet 100% RDI for some nutrients by chance.
  • Fix: Pre-filter foods based on nutrient density (e.g., using nutrient_score) before random selection, or increase the pool size (e.g., 50 foods).

7. Lack of Practicality Constraints

  • Problem: The optimization doesn’t consider meal practicality (e.g., taste compatibility, preparation feasibility, or total volume).
  • Impact: You might get a “recipe” with 100g of broccoli, 75g of liver, and 50g of almonds—nutrient-rich but unpalatable or hard to prepare together.
  • Fix: Add constraints like maximum total weight (e.g., 800g), food category diversity (e.g., at least one protein, carb, fat source), or a taste compatibility score.

8. Missing Dependencies and Error Handling

  • Problem: The script assumes the presence of Release 2 - Nutrient file.xlsx, rdi.json, and diet config files (e.g., vegan.json). Missing files or mismatched formats will crash it.
  • Impact: Reduces robustness for real-world use.
  • Fix: Add try-except blocks around file operations and provide default fallbacks or clear error messages.

9. RDI Values for Your Profile

  • Problem: Some RDI values seem off for a 39-year-old moderately active male:
    • Protein (91g): High end; typically 56-70g unless very active or muscular.
    • Vitamin D (15 µg): Matches standard, but many adults need more (20-50 µg) depending on sunlight exposure.
    • Omega-3 (1600 mg): High; typical RDI is 250-500 mg EPA/DHA, though 1600 mg aligns with some heart health guidelines.
  • Impact: Over- or under-targeting nutrients could skew results.
  • Fix: Verify RDIs against authoritative sources (e.g., NIH, IOM) and adjust based on your activity level (e.g., ~0.8g protein/kg body weight).

Suggestions for Improvement

  1. Add a Feasibility Check: After optimization, validate that the total food weight is reasonable (e.g., 500-1000g for one meal) and nutrients are within safe ranges (RDI ≤ intake ≤ UL).
  2. Incorporate Activity Level: Adjust energy and protein RDIs dynamically based on your moderate activity (e.g., use Harris-Benedict equation for BMR + activity factor).
  3. Improve Nutrient Scoring: Weight nutrients by their physiological importance (e.g., prioritize deficiencies like Vitamin D or Iron over excesses of water-soluble vitamins).
  4. Test with Real Data: Run the script with your food database and check if it consistently hits 100% RDI for all nutrients. Tweak population_size and generations if needed.
  5. Add a Recipe Generator: Convert the food list into a practical recipe with preparation instructions (e.g., “Grilled Salmon with Broccoli and Quinoa”).

Example Fix for Key Issues

Here’s a snippet addressing some critical flaws:

# Adjust RDI for activity level (example: 80kg male, moderate activity)
basal_energy = 10 * 80 + 6.25 * 175 - 5 * 39 + 5  # Harris-Benedict BMR (~1700 kcal)
energy_rdi = basal_energy * 1.55  # Moderate activity factor (~2600 kcal = 10878 kJ)
rdi_values["Energy with dietary fibre, equated (kJ)"] = {"rdi": energy_rdi, "ul": energy_rdi * 1.3}

# Enforce UL in evaluate_solution
def evaluate_solution(solution):
    current_nutrients = {nutrient: 0 for nutrient in meal_rdi_targets}
    for food, amount in solution.items():
        for nutrient in meal_rdi_targets:
            if nutrient in foods_df.loc[food]:
                nutrient_per_gram = foods_df.loc[food][nutrient] / foods_df.loc[food]['density']
                current_nutrients[nutrient] += nutrient_per_gram * amount
    # Check ULs
    with open('rdi.json', 'r') as f:
        nutrient_data = json.load(f)
    for nutrient, value in current_nutrients.items():
        ul = nutrient_data.get(nutrient, {}).get('ul', float('inf'))
        if value > ul:
            return float('inf')  # Disqualify solution
    return _calculate_nutrition_score(current_nutrients, meal_rdi_targets, penalties)

# Wider food range
def create_solution():
    return {food: random.uniform(25, 500) for food in available_foods}

Conclusion

Your script is a strong foundation for generating nutrient-optimized recipes, but it needs refinement to ensure safety (UL enforcement), practicality (portion sizes, meal feasibility), and accuracy (nutrient mapping, RDI alignment). With the fixes above, it should better meet your goal of 100% RDI for a 39-year-old moderately active male. Let me know if you’d like help testing it with your food database or refining specific parts!


Optimising Nutrition Reviewed By Claude AI

optimising-nutrition

I’ve been doing some more work on my nutrition optimisation script, the script is now running on a schedule via Github Actions, it now supports a number of diet types All, Vegan, Whole Food Plant Based, Nutrient Dense. Every hour it generates new recipes, it will look at the diet json files and read the exclusion and inclusion lists defined in the JSON file and then randomly select a random number of foods from the Australian Nutrition database csv along with their nutrition data and then the script will do a random number of generations of a genetic algorithm attempting to determine the number of grams per food item required to match as closely as possible to the recommended daily intake of essential vitamins and minerals for a 39 year old male (myself), it then saves the generated recipes in the github repo as JSON and HTML files and generates and index of these recipes and sorts them by score, the lower the score the better and the more the closer it is to matching the micronutrient RDI targets. There is a clean up at the end of the script that deletes recipes with a score that’s higher then the specified value and deletes any recipes over a total of 250 files, so over time the script will continue to generate better recipes and push out the ones with higher scores.

Challenges so far have been the Vegan and WFPB json files, trying to exclude all of the meat items, every time I think I’ve excluded them all I see a vegan recipe generated with a Camel or Emu or some type of fish in it and I need to exclude that item from the list and even more so for Whole Food Plant Based have to exclude the meat and all of the non whole food items like cakes and biscuits and packaged goods etc, so it’s still a work in progress.

I fed the optimising nutrition script into Claude and asked it to review the code it has provided some good suggestions that I will take on board :

review the logic of this script, I am a 39 year old male moderately active and want to generate recipes that meet 100% of my daily recommended intake of the essential vitamins and minerals, determine any issues in this script and any flaws

Anthropic Claude response

I’ll review the script and identify any potential issues or flaws specifically for your goal of generating recipes that meet 100% of your daily recommended intake of essential vitamins and minerals as a 39-year-old moderately active male.

Overall Analysis

The script uses a genetic algorithm approach to optimize food combinations to meet nutritional requirements, which is a solid approach for this complex problem. Let’s examine specific aspects:

Strengths

  • The genetic algorithm approach is appropriate for multi-objective optimization like this
  • The penalties system allows for nuanced handling of different nutrients
  • The code handles water-soluble vs. fat-soluble vitamins differently (appropriate since excess water-soluble vitamins are generally less concerning)
  • Detailed reporting and visualization of results

Issues and Potential Improvements

  1. RDI Target Splitting Assumption
    • The code divides RDI targets by the number of meals, assuming equal distribution
    • This may not be ideal for all nutrients, as some (like protein) may benefit from distribution throughout the day while others can be consumed in a single meal
  2. Missing UL Values
    • Several nutrients in your JSON have RDI but no UL (Upper Limit) specified
    • The _calculate_nutrition_score function expects UL values for some calculations
    • Without UL values, the function may not properly penalize excessive nutrient intake
  3. Nutrient Density Calculation
    • The nutrient density scoring doesn’t account for negative nutrients (like sodium, saturated fats) that should be limited
  4. Fixed Food Amount Ranges
    • Food amounts are randomly initialized between 25-100g and mutated in ±20g increments
    • This might not be realistic for all foods (e.g., spices vs. staples)
  5. Food Selection Mechanism
    • For diet-specific runs, the code randomly selects 10-30 foods from the filtered dataset
    • This might lead to suboptimal results if key nutritionally dense foods are randomly excluded
  6. Missing Bioavailability Considerations
    • The script doesn’t account for nutrient interactions that affect bioavailability
    • For example, iron absorption is affected by vitamin C, zinc absorption by phytates, etc.
  7. Generations and Population Size
    • Your implementation randomly selects between 10-300 generations
    • The range is very wide - 10 generations likely won’t be enough for convergence
    • Consider setting a more consistent minimum (e.g., 50+)
  8. Optimization Target
    • The fitness function primarily focuses on matching RDI values but doesn’t explicitly optimize for:
      • Food variety/diversity
      • Food preferences/taste
      • Cost of ingredients
      • Seasonal availability
      • Meal compatibility (foods that work well together)
  9. Practical Meal Planning
    • The script optimizes for nutrients but doesn’t group foods into practical meals
    • No consideration for cooking methods or preparation feasibility
  10. Potential Implementation Issues
    • The code references start_time before defining it in the main function
    • The _is_nutrition_sufficient function is defined but never used

Specific Recommendations

  1. Add Missing UL Values
    • Add upper limits for all nutrients where applicable
    • For nutrients that truly don’t have established ULs, consider setting generous but reasonable values
  2. Adjust Food Amount Constraints
    • Consider categorizing foods by typical serving sizes (e.g., spices vs. vegetables)
    • Adjust the mutation ranges based on food categories
  3. Enhance the Food Selection Mechanism
    • Instead of purely random selection, ensure representation from key food groups
    • Consider implementing a “seed” system where nutritionally exceptional foods are always included
  4. Incorporate Bioavailability Factors
    • Add modifiers for known nutrient interactions
    • Consider time-of-day effects for certain nutrients (e.g., timing of protein intake)
  5. More Strategic Generation Parameters
    • Set a higher minimum number of generations (at least 50)
    • Consider implementing early stopping if scores plateau
  6. Add Meal Practicality Factors
    • Implement clustering to group compatible foods
    • Add penalties for unusual food combinations
  7. Fix Implementation Issues
    • Move the start_time = time.time() into the appropriate function scope
    • Either use or remove the _is_nutrition_sufficient function

Conclusion

The script has a solid foundation for nutrient optimization but could benefit from refinements to produce more practical, varied, and enjoyable meals while still meeting nutritional requirements. The main philosophical question is whether you want to optimize purely for nutrition or balance nutrition with practical meal planning considerations.

Would you like me to elaborate on any specific aspect of this review or provide code examples for implementing any of these recommendations?

Grok AI Code Review

I’ll review your script for generating recipes that meet 100% of your daily recommended intake (RDI) of essential nutrients. As a 39-year-old moderately active male, your RDI values in the JSON look generally appropriate (based on standard guidelines like those from the NIH or USDA), though I’ll point out potential issues and suggest improvements. Here’s my analysis of the script’s logic and potential flaws:


Strengths of the Script

  1. Genetic Algorithm Approach: Using a genetic algorithm (GA) to optimize nutrient intake is a solid choice for this complex, multi-variable problem. It effectively balances exploration (randomness) and exploitation (optimization toward RDI targets).
  2. Flexible Nutrient Targets: The script scales RDI targets based on the number of meals, which is practical for daily planning.
  3. Detailed Reporting: The JSON and HTML reports are comprehensive, providing actionable insights into food quantities, nutrient profiles, and optimization performance.
  4. Penalty System: Differentiating penalties for under-RDI, over-RDI, and upper limits (UL), with special handling for water-soluble vs. fat-soluble vitamins, is a thoughtful approach to nutrient safety and balance.
  5. Diet Type Support: Filtering foods based on diet types (e.g., vegan, whole food plant-based) adds versatility.

Issues and Flaws

Here are the key issues I identified in the script, along with their potential impact:

1. Missing Upper Limit (UL) Enforcement

  • Problem: While the script penalizes exceeding ULs (e.g., in _calculate_nutrition_score), it doesn’t strictly enforce them. The penalty for exceeding ULs (over_ul) is randomized between 1.8 and 2.5, which may not be strong enough to prevent unsafe nutrient levels (e.g., Vitamin A at 3000 µg or Zinc at 40 mg).
  • Impact: For a 39-year-old male, exceeding ULs for certain nutrients (e.g., Vitamin A, Iron) could lead to toxicity over time.
  • Fix: Add a hard constraint in evaluate_solution to disqualify solutions exceeding ULs for critical nutrients, or increase the over_ul penalty significantly (e.g., 10x instead of 2.5x).

2. Energy (kJ) Handling is Incomplete

  • Problem: The script treats “Energy with dietary fibre, equated (kJ)” as a nutrient with an RDI (10,878 kJ) and UL (13,389 kJ), but the logic in _calculate_nutrition_score re-reads rdi.json instead of using the passed targets dictionary. This is inconsistent and assumes the JSON file is always available.
  • Impact: For a moderately active 39-year-old male, energy needs are ~10,000-11,000 kJ (2400-2600 kcal), which aligns with your RDI. However, the UL seems arbitrary and may not reflect realistic limits. Plus, the re-reading of JSON could fail if the file is missing.
  • Fix: Use the targets dictionary consistently for all nutrients, including energy. Define a more realistic UL (e.g., 15,000 kJ) based on activity level and safety margins.

3. Food Quantity Range is Limited

  • Problem: In create_solution, food amounts are initialized between 25-100g, and mutations adjust by ±20g. This range is too narrow to meet 100% RDI for a full day in one meal (your number_of_meals=1 setting).
  • Impact: With only 25-100g per food, it’s unlikely to hit high RDIs (e.g., 3400 mg Potassium, 38g Fiber) without including more foods or larger portions.
  • Fix: Increase the range (e.g., 25-500g) and adjust mutation steps proportionally. Alternatively, use a food database with serving size metadata to scale amounts realistically.

4. Nutrient Mapping Mismatch

  • Problem: The nutrient_mapping parameter in optimize_nutrition is a dictionary from rdi.json, but the script uses its keys directly as column names in food_df. However, rdi.json keys (e.g., “Protein (g)”) don’t match typical food database column names (e.g., “PROTEIN”).
  • Impact: This causes warnings ("Column not found") and sets missing nutrients to 0, skewing optimization results.
  • Fix: Create a proper mapping dictionary (e.g., {'Protein (g)': 'PROTEIN', ...}) and pass it to optimize_nutrition. Ensure food_df columns align with this mapping.

5. Single-Meal Assumption

  • Problem: You set number_of_meals=1, aiming for 100% RDI in one meal, but the script’s logic (e.g., scaling RDIs by number_of_meals) assumes multiple meals. This inconsistency could confuse results.
  • Impact: A single meal hitting 100% RDI (e.g., 10,878 kJ, 91g protein) is impractical for most people due to volume and digestion limits.
  • Fix: Either adjust number_of_meals to 3 (typical daily meals) and aim for ~33% RDI per meal, or explicitly design for a single meal with realistic portion constraints (e.g., max 1000g total food).

6. Random Food Selection

  • Problem: The script randomly selects 10-30 foods per run (n_foods = random.randint(10, 30)), which may exclude nutrient-dense options critical for meeting RDIs (e.g., spinach for folate, salmon for omega-3s).
  • Impact: This randomness reduces consistency and may fail to meet 100% RDI for some nutrients by chance.
  • Fix: Pre-filter foods based on nutrient density (e.g., using nutrient_score) before random selection, or increase the pool size (e.g., 50 foods).

7. Lack of Practicality Constraints

  • Problem: The optimization doesn’t consider meal practicality (e.g., taste compatibility, preparation feasibility, or total volume).
  • Impact: You might get a “recipe” with 100g of broccoli, 75g of liver, and 50g of almonds—nutrient-rich but unpalatable or hard to prepare together.
  • Fix: Add constraints like maximum total weight (e.g., 800g), food category diversity (e.g., at least one protein, carb, fat source), or a taste compatibility score.

8. Missing Dependencies and Error Handling

  • Problem: The script assumes the presence of Release 2 - Nutrient file.xlsx, rdi.json, and diet config files (e.g., vegan.json). Missing files or mismatched formats will crash it.
  • Impact: Reduces robustness for real-world use.
  • Fix: Add try-except blocks around file operations and provide default fallbacks or clear error messages.

9. RDI Values for Your Profile

  • Problem: Some RDI values seem off for a 39-year-old moderately active male:
    • Protein (91g): High end; typically 56-70g unless very active or muscular.
    • Vitamin D (15 µg): Matches standard, but many adults need more (20-50 µg) depending on sunlight exposure.
    • Omega-3 (1600 mg): High; typical RDI is 250-500 mg EPA/DHA, though 1600 mg aligns with some heart health guidelines.
  • Impact: Over- or under-targeting nutrients could skew results.
  • Fix: Verify RDIs against authoritative sources (e.g., NIH, IOM) and adjust based on your activity level (e.g., ~0.8g protein/kg body weight).

Suggestions for Improvement

  1. Add a Feasibility Check: After optimization, validate that the total food weight is reasonable (e.g., 500-1000g for one meal) and nutrients are within safe ranges (RDI ≤ intake ≤ UL).
  2. Incorporate Activity Level: Adjust energy and protein RDIs dynamically based on your moderate activity (e.g., use Harris-Benedict equation for BMR + activity factor).
  3. Improve Nutrient Scoring: Weight nutrients by their physiological importance (e.g., prioritize deficiencies like Vitamin D or Iron over excesses of water-soluble vitamins).
  4. Test with Real Data: Run the script with your food database and check if it consistently hits 100% RDI for all nutrients. Tweak population_size and generations if needed.
  5. Add a Recipe Generator: Convert the food list into a practical recipe with preparation instructions (e.g., “Grilled Salmon with Broccoli and Quinoa”).

Example Fix for Key Issues

Here’s a snippet addressing some critical flaws:

# Adjust RDI for activity level (example: 80kg male, moderate activity)
basal_energy = 10 * 80 + 6.25 * 175 - 5 * 39 + 5  # Harris-Benedict BMR (~1700 kcal)
energy_rdi = basal_energy * 1.55  # Moderate activity factor (~2600 kcal = 10878 kJ)
rdi_values["Energy with dietary fibre, equated (kJ)"] = {"rdi": energy_rdi, "ul": energy_rdi * 1.3}

# Enforce UL in evaluate_solution
def evaluate_solution(solution):
    current_nutrients = {nutrient: 0 for nutrient in meal_rdi_targets}
    for food, amount in solution.items():
        for nutrient in meal_rdi_targets:
            if nutrient in foods_df.loc[food]:
                nutrient_per_gram = foods_df.loc[food][nutrient] / foods_df.loc[food]['density']
                current_nutrients[nutrient] += nutrient_per_gram * amount
    # Check ULs
    with open('rdi.json', 'r') as f:
        nutrient_data = json.load(f)
    for nutrient, value in current_nutrients.items():
        ul = nutrient_data.get(nutrient, {}).get('ul', float('inf'))
        if value > ul:
            return float('inf')  # Disqualify solution
    return _calculate_nutrition_score(current_nutrients, meal_rdi_targets, penalties)

# Wider food range
def create_solution():
    return {food: random.uniform(25, 500) for food in available_foods}

Conclusion

Your script is a strong foundation for generating nutrient-optimized recipes, but it needs refinement to ensure safety (UL enforcement), practicality (portion sizes, meal feasibility), and accuracy (nutrient mapping, RDI alignment). With the fixes above, it should better meet your goal of 100% RDI for a 39-year-old moderately active male. Let me know if you’d like help testing it with your food database or refining specific parts!


Optimising Nutrition with Genetic Algorithms

optimising-nutrition

I have been working on creating an Optimising Nutrition with Genetic Algorithms python script that will randomly select a number of foods from the Australian Food Composition Database will then generate random amounts for each food in grams for a number of specified generations with each generation trying to get closer and closer to matching 100% of the Daily Recommended Intake (RDI) for each essential vitamin and mineral, so the end result will be a list of ingredients and the amount in grams you should eat to get as close as possible to the RDI.

alt text

alt text

Kind of like a whole food version of Soylent

This would be helpful for some one wanting to do a daily eating plan and wants to hit their micronutrient RDI’s.

You can view the index of recipes generated by genetic algorithm here : https://alexlaverty.github.io/optimize-nutrition/

They are sorted by score, a lower score is better, a lower score means it’s closer to matching the RDI’s and the higher the score the further away from matching the RDI’s.

I have also specified different diet types to generate for All, meaning all foods in the database, Vegan to exclude any animal products, and WFPB meaning Whole Food Plant Based which excludes food if they do not match this criteria.

The script and repo is still a work in progress, so I am open to any feedback or suggestions.

This script is designed to optimize meal planning using a genetic algorithm, which is a type of artificial intelligence inspired by natural selection.

The main goal is to select and adjust quantities of various foods to ensure that the daily nutritional requirements such as essential vitamins and minerals are met.

By using a genetic algorithm, the script evolves a set of food combinations over multiple generations, gradually improving the meal plan to better meet these nutritional targets.

Key Features and Functionality:

Food Selection and Customization:

The script begins by reading a dataset of foods, each with nutritional information. It allows for dietary customization, such as selecting only vegan or whole-food plant-based foods, by applying exclusion rules. This ensures the optimization is tailored to different diet types.

Genetic Algorithm:

The core of the optimization is the genetic algorithm. The algorithm works by simulating the process of natural selection:

It starts with a randomly selected population of meal plans (combinations of foods and their quantities). Over several generations, the algorithm “evolves” better solutions by selecting the best meal plans (those that are closer to the nutritional targets), and creating new meal plans through processes like crossover (mixing different plans) and mutation (random changes). This evolutionary process continues until an optimal or satisfactory meal plan is found.

Nutrient Calculation:

Each food item in the selected meal plans is analyzed for its contribution to meeting the daily recommended intake (RDI) of various nutrients.

The script calculates how much of each nutrient each food provides, ensuring that the final combination meets or comes close to the daily nutritional goals for essential vitamins and minerals.

Output and Reports:

After running the optimization process, the script generates detailed reports in various formats. These include:

JSON files containing the optimized meal plans, which can be saved and reused. Markdown and HTML files summarizing the results in an easily readable format.

These reports show key details like the optimization score (how well the meal plan meets the nutritional goals), the number of foods used, and how the nutrients in the meal plan are distributed across different categories (e.g., nutrients at good levels, below target, or above target).

Scalability and Flexibility:

The script is designed to be flexible, allowing it to handle various numbers of foods (from 5 to 20) and a customizable number of generations (up to 300). This means the user can adjust how complex and refined the meal plan optimization process is.

How Genetic Algorithms Help in Meal Planning:

Genetic algorithms are particularly well-suited for problems like meal optimization, where the number of possible food combinations is large and complex. Instead of manually trying every possible combination, which would be time-consuming and inefficient, the genetic algorithm simulates the natural process of evolution to “search” for the best combination efficiently.

By creating a population of meal plans and evolving them through generations, the algorithm can gradually find the combination of foods that best meets the nutritional targets, all while considering factors like variety and balance in the meal.

In summary, this script automates the process of meal planning by intelligently selecting and adjusting food items to meet nutritional needs, making use of genetic algorithms to improve the meal plans over time. It provides a flexible, automated solution for anyone looking to optimize their diet for specific health goals or dietary preferences.

Analysis of the Results

After letting the script run every hour for a few days I fed the table into ChatGPT and asked it to analyse the results.

Here is ChatGPT’s analysis of the trends and optimal values based on the provided data:

Key Observations

  1. Best Score Range:
    • The lowest (best) scores are in the range 5.07 to 6.17.
    • The worst scores are above 20, with the worst being 31.85.
  2. Diet Type Trends:
    • Best scores (≤6.17): Mostly “all” and “vegan” diets.
    • Worst scores (>20): Mostly “wfpb” (Whole Food Plant-Based).
    • Implication: The best-performing recipes tend to include all food groups or vegan options, while purely whole-food plant-based diets seem harder to optimize.
  3. Number of Ingredients (Foods):
    • Best scores (≤6.17): Use between 10 to 20 ingredients.
    • Worst scores (>20): Often have very few ingredients (e.g., 5–8), suggesting that having more variety contributes to better nutritional balance.
  4. Nutrient Balance (OK/Low/High):
    • Best scores (≤6.17): Tend to have around 17-20 nutrients at OK levels, 9-12 nutrients below target, and 0-2 above target.
    • Worst scores (>20): Have significantly more nutrients below target (e.g., 20-28 low), meaning they fail to meet nutritional needs.
  5. Generations & Computation Time:
    • The best runs typically required 150-300 generations and computation times ranging 450s to 2000s.
    • The worst runs often completed in very few generations (3-50), meaning they likely didn’t converge to a well-optimized solution.

Optimal Recipe Parameters for Genetic Algorithm

If you’re generating recipes, these values would likely yield the best results:

Parameter Optimal Range
Diet Type All or Vegan
Number of Ingredients 10 - 20
Nutrients (OK/Low/High) ~18/10/2
Generations 150 - 300
Computation Time 500s - 2000s

Using this analysis I’m going to continue to tweak the script and add in more features to get recipes that more closely match the recommended daily requirements for the essential vitamins and minerals and also adding more requirements to match, calories, other things that are not essential but still desirable.

I’ve also been working on a UI which updates in real time and shows you a chart of the score as it decreases with each generation :

alt text