Q1: Bid Optimization in First-Price Auction for Advertising using Optimization Approach
A company is running an online advertising campaign, bidding on ad placements in a first-price auction. The goal is to determine the optimal bid that maximizes profit while ensuring that total advertising expenditure stays within a specified budget, using the approach discussed in the last lecture.
Assume there are only two placements: a good place (1) and a bad place (2), and:
- Revenue per Click (RPC): Each click on the advertisement generates $5 in revenue.
- Cost of Goods Sold (COGS): The cost associated with each click is $1.
- Impressions: The ad is ex
- pected to be displayed 1,000 times.
- Click-Through Rate (CTR): CTR | 𝑋 = 𝑥 ∼ Binomial(𝑝(𝑥))
- p(1) = 0.4 for a good place
- p(2) = 0.6 for a bad place
- Function f(x; b) :
- For a good place:
- For a bad place:
- Budget: The total budget for the advertising campaign is $200,000.
- Bid Bounds: The bid b must be between 4.00.
- Write the question in Pyomo.
- Find the optimal bid.
- Plot the objective function.
import pyomo.environ as pyoimport numpy as npfrom scipy.stats import beta
# parametersrpc = 5cogs = 1impressions = 1000budget = 200000min_bid = 0.01max_bid = 4.0
# CTR distribution parametersp = {1: 0.4, 2: 0.6}beta_params = {1: (10, max_bid), 2: (3, min_bid)}budget = 200000
model = pyo.ConcreteModel()model.b = pyo.Var(bounds=(min_bid, max_bid), within=pyo.NonNegativeReals)
def f(x, b): a, b_param = beta_params[x] return beta.mean(a, b_param) * b
model.objective = pyo.Objective(expr=( rpc - cogs - model.b) * impressions * sum(p[x] * f(x, model.b) for x in p), sense=pyo.maximize)
model.budget_constraint = pyo.Constraint( expr=model.b * impressions * sum(p[x] * f(x, model.b) for x in p) <= budget)
solver = pyo.SolverFactory('ipopt')results = solver.solve(model, tee=True)
optimal_bid = pyo.value(model.b.value)
print(f"Optimal Bid: ${optimal_bid}")Output:
Optimal Bid: $2.0000000000009908import matplotlib.pyplot as plt
def objective_func(b): cpc = b profit = (rpc - cogs - cpc) * impressions * (p[1]*f(1, b) + p[2]*f(2, b)) return profit
bids = np.linspace(min_bid, max_bid, 100)obj_vals = [objective_func(b) for b in bids]
plt.plot(bids, obj_vals, label="Objective Function")plt.axvline(optimal_bid, color='r', linestyle='--', label="Optimal Bid")plt.xlabel("Bid ($)")plt.ylabel("Objective Function Value")
Q2. Bid Optimization in First-Price Auction for Advertising using Multi objective Approach
Assume the same parameters with the following modifications:
We are now considering the problem:
where:
- Profit:
- Expected CTR:
- Expected Impressions:
- Expected Clicks:
import numpy as npimport matplotlib.pyplot as pltimport pyomo.environ as pyo
# parametersrpc = 5cogs = 1impressions = 1000budget = 200000min_bid = 0.01max_bid = 4.0p = {1: 0.4, 2: 0.6}
# weightsalpha1, alpha2, alpha3, alpha4 = 0.4, 0.2, 0.2, 0.2
# helper functions
def f_x_b_good(b): return beta.mean(10, max_bid) * b
def f_x_b_bad(b): return beta.mean(3, min_bid) * b
def objective_func(b): E_ctr_good = b / f_x_b_good(b) E_ctr_bad = b / f_x_b_bad(b) E_impression_good = impressions * (b / f_x_b_good(b)) * b E_impression_bad = impressions * (b / f_x_b_bad(b)) * b E_clicks_good = E_impression_good * E_ctr_good E_clicks_bad = E_impression_bad * E_ctr_bad
cpc = b p_bid_good = (rpc - cogs - cpc) * E_impression_good p_bid_bad = (rpc - cogs - cpc) * E_impression_bad
return (alpha1 * (p_bid_good * p[1] + p_bid_bad * p[2]) + alpha2 * (E_ctr_good * p[1] + E_ctr_bad * p[2]) + alpha3 * (E_impression_good * p[1] + E_impression_bad * p[2]) + alpha4 * (E_clicks_good * p[1] + E_clicks_bad * p[2]))
# Compute objective across bidsbids = np.linspace(min_bid, max_bid, 200)obj_vals = [objective_func(b) for b in bids]
# Solve with Pyomomodel = pyo.ConcreteModel()model.b = pyo.Var(bounds=(min_bid, max_bid), within=pyo.NonNegativeReals)
E_ctr_good = model.b / f_x_b_good(model.b)E_ctr_bad = model.b / f_x_b_bad(model.b)E_impression_good = impressions * (model.b / f_x_b_good(model.b)) * model.bE_impression_bad = impressions * (model.b / f_x_b_bad(model.b)) * model.bE_clicks_good = E_impression_good * E_ctr_goodE_clicks_bad = E_impression_bad * E_ctr_badcpc = model.bp_bid_good = (rpc - cogs - cpc) * E_clicks_goodp_bid_bad = (rpc - cogs - cpc) * E_clicks_bad
model.obj = pyo.Objective(expr=alpha1 * (p_bid_good * p[1] + p_bid_bad * p[2]) + alpha2 * (E_ctr_good * p[1] + E_ctr_bad * p[2]) + alpha3 * (E_impression_good * p[1] + E_impression_bad * p[2]) + alpha4 * (E_clicks_good * p[1] + E_clicks_bad * p[2]), sense=pyo.maximize)
model.budget_constraint = pyo.Constraint( expr=model.b * (E_clicks_good + E_clicks_bad) <= budget)
solver = pyo.SolverFactory('ipopt')solver.solve(model)
optimal_bid = pyo.value(model.b)print(f"Optimal Bid from Pyomo: ${optimal_bid}")Output:
Optimal Bid from Pyomo: $2.459292942866574# plotplt.figure(figsize=(8,5))plt.plot(bids, obj_vals, label="Objective Function")plt.axvline(optimal_bid, color='r', linestyle='--', label=f"Optimal Bid = {optimal_bid:.2f}")plt.xlabel("Bid ($)")plt.ylabel("Objective Function Value")plt.title("Objective vs Bid (Your Formulation)")plt.legend()plt.show()