Pricing and target-market#
Description: Formulate a pricing optimization and target-market problem as a MILP.
Tags: industry, pricing, milp, mip
Notebook author: Gyorgy Matyasfalvi <gyorgy@ampl.com>
Model author: Erwin Kalvelagen
References:
https://stackoverflow.com/questions/60669893/formulating-pricing-optimization-as-milp
# Install dependencies
%pip install -q amplpy
# Google Colab & Kaggle integration
from amplpy import AMPL, ampl_notebook
ampl = ampl_notebook(
modules=["cplex"], # modules to install
license_uuid="default", # license to use
) # instantiate AMPL object and register magics
Problem formulation#
We wish to find the optimal combination of a fixed fee \(F\) and variable price \(p\) for a product.
We have \(N\) types of clients who each want to purchase quantity \(q_i (i \in N)\) for which they are willing to pay a total price of \(w_i (i \in N)\).
Our objective is to pick \(F\) and \(p\) such that we maximize revenue.
We can describe the above problem as a MILP using the following formulation:
Above we introduced binary variables \(s_i (i \in N)\), which indicate whether we can sell our product to client type \(i\) (this will reveal our target market), along with defined variables \(y_i (i \in N)\) indicating the total revenue received from client \(i\).
Use amplpy
to solve our pricing model#
Predict customer behavior#
# Load modules
from amplpy import AMPL
# Define dummy prediction functions (in reality these will be a sophisticated ML method)
def client_type():
return ["genx", "geny", "genz"]
def quantity_pred(client):
if client == "genx":
return 5
if client == "geny":
return 10
if client == "genz":
return 20
def wpay_pred(client):
if client == "genx":
return 40
if client == "geny":
return 45
if client == "genz":
return 25
Data prep#
# Generate dictionaries from predictions (to be loaded as AMPL data later)
quant_dict = {i: quantity_pred(i) for i in client_type()}
wpay_dict = {i: wpay_pred(i) for i in client_type()}
Load AMPL model#
# Define AMPL model
ampl = AMPL()
ampl.eval(
r"""
set N; # Types of clients
param q{N}; # Purchase quantity per client type (e.g. GB of data)
param w{N}; # Client's willingness to pay (e.g. USD per month)
var p >= 0; # Variable price (e.g. USD per GB of data)
var F >= 0; # Fixed fee (e.g. USD per month)
var s{i in N} binary; # Ability to sell to client type product
var y{i in N} >=0, <= w[i]; # Revenue received from client
maximize total_revenue:
sum {i in N} y[i];
subject to ic_sell {i in N}:
s[i] = 1 ==> y[i] = F + p*q[i];
subject to ic_no_sell {i in N}:
s[i] = 0 ==> y[i] = 0;
"""
)
Load data#
# Load data into AMPL model
ampl.set["N"] = client_type()
ampl.param["q"] = quant_dict
ampl.param["w"] = wpay_dict
Solve problem and display solution#
# Set solver to one that can handle logical constraints and MILPs
ampl.option["solver"] = "cplex"
# Solve our problem
ampl.solve()
# Print results
tr = ampl.get_objective("total_revenue")
print("\n")
print("Total revenue is:", tr.get().value(), "\n")
tm_df = ampl.get_variable("s").to_pandas()
print("Target market:")
tm_sol = tm_df.loc[tm_df["s.val"] == 1]
print(tm_sol)