# 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:

1. 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
)  # 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:

\begin{align} \textrm{Objective:} & \ & \max \sum_{i \in N} y_i \ \textrm{Subject to:} & \ s_i & = 1 \Rightarrow y_i = F+p*q_i \ s_i & = 0 \Rightarrow y_i = 0 \ s_i & \in {0, 1} \ p & \geq 0 \ F & \geq 0 \ y_i &\in [0, w_i] \end{align}

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()}


# 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 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)