You may think comparing apples to oranges is misguided or illogical, but in reality, we all do it daily – it’s the essence of hard decisions. Choosing between an apple or an orange poses a challenge, unlike deciding between one apple or two – two is clearly better.
Life presents many comparisons: freedom vs security, time vs money, immediate satisfaction vs delayed gratification, growth vs profit, and more. Finding the ‘Goldilocks zone’ or the sweet spot in these scenarios often calls for a touch of optimization.
Now, what if the choice extends to bananas, raspberries, with a budget thrown into the mix? That’s where simple decisions evolve into a complex array of choices. As we delve into optimization and utility, we’ll uncover how a methodical approach can navigate such details, be it in making a fruit salad or tackling life’s many decisions.
Let’s use a story to show this idea. Long ago, I hosted a party where I served a fruit salad that was a big hit. The recipe for a portion was as follows:
|Ingredient|Quantity (gr)| Purpose | Price per Kilo (€) |
|----------|-------------| ------- | ------------------ |
|Apple | 50 | crunch | 3 |
|Orange | 50 | juiciness | 4 |
|Banana | 50 | creamy | 3 |
|Raspberry | 50 | beautify | 30 |
Each portion cost around 2 €.
Now, I’ve been laid off and am short on funds, yet I am hosting the same group of people with the same expectations. This time, however, I have a budget of just 1 euro per portion.
The straightforward idea might be to halve the amounts, but that won’t fly – 100 grams per person is unacceptably scant, leaving half the guests empty-handed. This easy solution is clearly nonoptimal.
If this simple, suboptimal fix satisfies you, stop here. If not, keep reading for a more thoughtful solution.
If you want to see the optimal results and you hate math and python, jump to the result section. If you are either in love with math or python, keep reading.
Being short on money but having a lot of time, I decided to optimize the solution methodically, to get an easy and optimal solution.
We start by crafting an objective function to measure the enjoyment from a fruit salad. We’ll use the Cobb-Douglas utility function:
This function is a favorite in economics, illustrating how different factors contribute to utility or production. In our scenario, it highlights the importance of each fruit – skip any fruit and the utility plunges to zero, showing the vital role of each ingredient. Under a constraint where a+o+b+r = 200 grams, the function is at its best when a = o = b = r = 50. Don’t believe me? Feel free to play around with the values yourself!
However, now our constraint is the budget, not the portion size. We aim to maintain the price per portion at 1 euro, slashing the previous budget by half. This brings us to the equation:
To fine-tune the amount of each fruit under this budget constraint, while using the Cobb-Douglas utility function, we turn to the method of Lagrange multipliers. This method helps in finding the maximum or minimum of a function subject to certain constraints. To simplify our task, we take the logarithm of U before diving into the Lagrangian, leading to:
Now, let’s introduce the Lagrangian as:
Which for our fruit salad is:
The Lagrangian is a remarkable mathematical construct that showcases the trade-offs between the cost of fruits and the joy they bring. Visualize it as a seesaw: on one side, we have our longing for more fruit, and on the other, the stern budget constraint. The Lagrangian helps find that sweet spot where we maximize enjoyment without breaking the bank.
For those with a knack for Mathematics, here’s an interesting tidbit: this optimization problem is convex, meaning it has a single peak value, ensuring a unique optimal solution, which in turn makes the job of numerical methods simple. This characteristic simplifies our quest for the perfect fruit salad.
Now that you’ve grasped the basics of utility and the Lagrangian, let’s delve into the math. If math isn’t your cup of tea, but you fancy Python, feel free to jump to the Python section.
For those ready to dive into the details, here we go:
By taking the partial derivatives and setting them to zero, we arrive at a set of equations, all connected through the variable, λ. Here’s how it pans out:
From here, it’s evident that all equations are tied together through λ, as shown below:
This gives us a system of decoupled equations; each fruit has its own equation, but all are intertwined through λ. This structure helps us find the optimal values for a, o, b, and r, as we can express them in terms of λ:
Furthermore, the utility and total price as functions of λ and budget are given by:
The six equations are linked only by λ. Here, λ, known as the shadow price, reveals the extra value from easing our budget a bit. Once λ is known, each equation can be solved separately, they are mutually exclusive and collectively exhaustive. Here λ is the One Parameter.
One Parameter to rule them all, One Parameter to find them, One Parameter to bring them all, and in the darkness bind them.
Upon substituting these expressions back into the budget constraint equation, we find λ equals 4. This leads to optimized quantities for our ingredients in kilograms: a=1/12, o=1/16, b=1/12, and r=1/120, totaling exactly 1 € for a portion of 238 grams.
This method harmonizes the sweet taste of fruit with the bitter constraints of a budget, illustrating how thoughtful Optimization helps navigate financial hurdles.
Python
Dive into the code below to visualize the problem:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
def calculate_log_utility(weights):
"""
Calculate the log utility for the given weights of the fruits.
:param weights: Dictionary containing the weights of each fruit.
:return: Sum of the logarithm of the weights of the fruits.
"""
return np.sum([np.log(weights[fruit]) for fruit in weights], axis=0)
def calculate_total_price(weights, prices):
"""
Calculate the total price per portion for the given weights and prices of the fruits.
:param weights: Dictionary containing the weights of each fruit.
:param prices: Dictionary containing the prices of each fruit per kg.
:return: Total price per portion.
"""
return np.sum([weights[fruit] * prices[fruit] for fruit in weights], axis=0)
def calculate_lagrangian(weights, prices, lambda_value, budget):
"""
Calculate the Lagrangian for the given weights, prices, lambda, and budget.
:param weights: Dictionary containing the weights of each fruit.
:param prices: Dictionary containing the prices of each fruit per kg.
:param lambda_value: The value of the Lagrange multiplier.
:param budget: The budget per portion.
:return: Calculated Lagrangian value.
"""
log_utility = calculate_log_utility(weights)
total_price = calculate_total_price(weights, prices)
return log_utility - lambda_value * (total_price - budget)
# Set the style of seaborn for better visualization
sns.set(style="whitegrid")
# Define the random weights for each fruit in kg.
weights = {
'apple': np.random.rand(1000) * 0.075 + 0.02,
'orange': np.random.rand(1000) * 0.075 + 0.02,
'banana': np.random.rand(1000) * 0.075 + 0.02,
'raspberry': np.random.rand(1000) * 0.075 + 0.0001,
}
# Define the prices for each fruit in euros per kg.
prices = {
'apple': 3, 'orange': 4, 'banana': 3, 'raspberry': 30
}
# Define the optimum and original recipes in kg.
recipes = {
'optimum': {'apple': 1/12, 'orange': 1/16, 'banana': 1/12, 'raspberry': 1/120},
'original': {'apple': 0.05, 'orange': 0.05, 'banana': 0.05, 'raspberry': 0.05}
}
# Plot Log Utility Graph
plt.figure(figsize=(10, 6))
sns.scatterplot(x=calculate_total_price(weights, prices),
y=calculate_log_utility(weights), alpha=0.5, edgecolor=None)
plt.scatter([calculate_total_price(recipes['optimum'], prices)],
[calculate_log_utility(recipes['optimum'])], color='red', label='Optimum Recipe')
plt.scatter([calculate_total_price(recipes['original'], prices)],
[calculate_log_utility(recipes['original'])], color='orange', label='Original Recipe')
plt.title('Log Utility as a Function of Price per Portion')
plt.xlabel('Price per Portion (€)')
plt.ylabel('Log Utility')
plt.xlim(0.5, 3)
plt.ylim(-16, -9)
plt.legend(loc='upper left')
plt.show()
# Define lambda_value and budget for Lagrangian Graph
lambda_value = 4 # Given value of lambda
budget = 1 # Given budget per portion
# Plot Lagrangian Graph
plt.figure(figsize=(10, 6))
sns.scatterplot(x=calculate_total_price(weights, prices),
y=calculate_lagrangian(weights, prices, lambda_value, budget), alpha=0.5, edgecolor=None)
plt.scatter([calculate_total_price(recipes['optimum'], prices)],
[calculate_lagrangian(recipes['optimum'], prices, lambda_value, budget)], color='red', label='Optimum Recipe')
plt.scatter([calculate_total_price(recipes['original'], prices)],
[calculate_lagrangian(recipes['original'], prices, lambda_value, budget)], color='orange', label='Original Recipe')
plt.title('Lagrangian as a Function of Price per Portion')
plt.xlabel('Price per Portion (€)')
plt.ylabel('Lagrangian')
plt.xlim(0.5, 3)
plt.ylim(-18, -12)
plt.legend(loc='upper right')
plt.show()
Now, let’s solve the equations with sympy:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import sympy as sp
# Setting the style of seaborn for better visualization
sns.set()
# Amounts of each fruit
a, o, b, r = sp.symbols('a o b r', positive=True, real=True) # Quantities of apples, oranges, bananas, and raspberries
# Prices of each fruit per kilo
P_a, P_o, P_b, P_r = sp.symbols('P_a P_o P_b P_r', positive=True, real=True) # Prices for apples, oranges, bananas, and raspberries per kilo
# Total price of the ingredients
P = a*P_a + o*P_o + b*P_b + r*P_r
# Budget
B = sp.Symbol('B', positive=True, real=True) # Budget for the fruit salad
# Lagrange multiplier
λ = sp.Symbol('λ', positive=True, real=True) # Lagrange multiplier
# Cobb-Douglas utility function in its logarithmic form
U_log = sp.ln(a) + sp.ln(o) + sp.ln(b) + sp.ln(r)
# The Lagrangian
L = U_log - λ * (P - B)
# Derive the first order conditions
foc_a = sp.diff(L, a)
foc_o = sp.diff(L, o)
foc_b = sp.diff(L, b)
foc_r = sp.diff(L, r)
foc_λ = sp.diff(L, λ)
# Solve for λ and the optimized quantities of each ingredient
solution = sp.solve((foc_a, foc_o, foc_b, foc_r, foc_λ), (a, o, b, r, λ), dict=True)
solution
Running the second code chunk reveals the precise fruit quantities needed to meet our budget while maximizing utility.
Results
Optimization reveals the best amount for each ingredient:
- Apple: 83 gr.
- Orange: 62 gr.
- Banana: 83 gr.
- Raspberry: 8 gr.
Total portion size: 0.238 kg, costing exactly 1 euro.
We’ve retained all the fruity characters in the salad, smartly adjusting their proportions. The outcome? A substantial 20% increase in portion size by reallocating the costly raspberry quota to the more economical apples and bananas. Quite resourceful, isn’t it?
This method creates a flexible formula, ready to adapt to changing prices, evolving recipes, or shifting budgets with little extra effort. The magic lies in the "One Parameter" – our mathematical key to balancing cost and satisfaction.
Now, does your business scenario echo this fruit salad dilemma? Need a similar optimization? Reach out, and I’ll craft a solution to balance your business ingredients within your budget boundaries.
Enjoyed the read? Click the clap button below – the more claps, the happier I get. Here’s the equation of my happiness:
Here, n is the number of claps, and "!" (factorial) means multiplying all positive integer numbers from 1 up to n. So, 5! is 54321 = 120.
Feel like sharing? Pass this piece along. Your shares spread the joy of a fun optimization tale!
I’d love to hear your thoughts or see your fun optimization ideas in the comments. Who knows, your quirky problem could inspire my next story!
In the meantime, check out my other fun post: