# BIM production variants#

# install dependencies and select solver
%pip install -q amplpy numpy matplotlib scikit-learn yfinance

SOLVER = "highs"

from amplpy import AMPL, ampl_notebook

ampl = ampl_notebook(
modules=["highs"],  # modules to install
)  # instantiate AMPL object and register magics


## Two variants of the BIM problem: fractional objective and additional fixed costs#

Recall the BIM production model introduced earlier here, that is

$\begin{split} \begin{array}{rrcrclr} \max \quad & 12x_1 & + & 9x_2 \\ \text{s.t.} \quad & x_1 & & & \leq & 1000 &\text{(silicon)}\\ & & & x_2 & \leq & 1500 &\text{(germanium)}\\ & x_1 & + & x_2 & \leq & 1750 &\text{(plastic)}\\ & 4x_1 & + & 2x_2 & \leq & 4800 &\text{(copper)}\\ & x_1 & , & x_2 & \geq & 0. \end{array} \end{split}$

Assume the pair $$(12,9)$$ reflects the sales price (revenues) in € and not the profits made per unit produced. We then need to account for the production costs. Suppose that the production costs for $$(x_1,x_2)$$ chips are equal to a fixed cost of 100 (independent of the number of units produced) plus $$7/6 x_1$$ plus $$5/6 x_2$$. It is reasonable to maximize the difference between the revenues and the costs. This approach yields the following linear model:

%%writefile BIM_with_revenues_minus_costs.mod

var x1 >= 0;
var x2 >= 0;

var revenue = 12 * x1 + 9 * x2;
var variable_cost = 7/6 * x1 + 5/6 * x2;

param fixed_cost default 100;

maximize profit: revenue - variable_cost - fixed_cost;

s.t. silicon: x1 <= 1000;
s.t. germanium: x2 <= 1500;
s.t. plastic: x1 + x2 <= 1750;
s.t. copper: 4 * x1 + 2 * x2 <= 4800;

Writing BIM_with_revenues_minus_costs.mod

def BIM_with_revenues_minus_costs():
m = AMPL()

return m

BIM_linear = BIM_with_revenues_minus_costs()
BIM_linear.option["solver"] = SOLVER
BIM_linear.solve()

print(
"x=({:.1f},{:.1f}) value={:.3f} revenue={:.2f} cost={:.2f}".format(
BIM_linear.var["x1"].value(),
BIM_linear.var["x2"].value(),
BIM_linear.obj["profit"].value(),
BIM_linear.var["revenue"].value(),
BIM_linear.var["variable_cost"].value()
+ BIM_linear.param["fixed_cost"].value(),
)
)

HiGHS 1.5.1:HiGHS 1.5.1: optimal solution; objective 15925
2 simplex iterations
0 barrier iterations
x=(650.0,1100.0) value=15925.000 revenue=17700.00 cost=1775.00


This first model has the same optimal solution as the original BIM model, namely $$(650,1100)$$ with a revenue of $$17700$$ and a cost of $$1775$$.

Alternatively, we may aim to optimize the efficiency of the plan, expressed as the ratio between the revenues and the costs:

$\begin{split} \begin{array}{lll} \max \quad & {\dfrac{12x_1+9x_2}{7/6x_1 + 5/6x_2 + 100}} \\ \text{s.t.} \quad & x_1 \leq 1000 &\text{(silicon)}\\ & x_2 \leq 1500 &\text{(germanium)}\\ & x_1 + x_2 \leq 1750 &\text{(plastic)}\\ & 4x_1 + 2x_2 \leq 4800 &\text{(copper)}\\ & x_1 , x_2 \geq 0. \end{array} \end{split}$

In order to solve this second version we need to deal with the fraction appearing in the objective function by introducing an auxiliary variable $$t \geq 0$$. More specifically, we reformulate the model as follows

$\begin{split} \begin{array}{rrcrcrclr} \max \quad & 12y_1 & + & 9y_2 \\ \text{s.t.} \quad & y_1 & & & & & \leq & 1000 \cdot t &\text{(silicon)}\\ & & & y_2 & & & \leq & 1500 \cdot t &\text{(germanium)}\\ & y_1 & + & y_2 & & & \leq & 1750 \cdot t &\text{(plastic)}\\ & 4y_1 & + & 2y_2 & & & \leq & 4800 \cdot t &\text{(copper)}\\ &7/6y_1 & + &5/6y_2 & + & 100y & = & 1 & \text{(fraction)} \\ & y_1 & , & y_2 & , & t & \geq & 0 \\ \end{array} \end{split}$

Despite the change of variables, we can always recover the solution as $$(x_1,x_2)= (y_1/t,y_2/t)$$.

%%writefile BIM_with_revenues_over_costs.mod

var y1 >= 0;
var y2 >= 0;
var t >= 0;

var revenue = 12 * y1 + 9 * y2;
var variable_cost = 7/6 * y1 + 5/6 * y2;

param fixed_cost default 100;

maximize profit: revenue;

s.t. silicon: y1 <= 1000 * t;
s.t. germanium: y2 <= 1500 * t;
s.t. plastic: y1 + y2 <= 1750 * t;
s.t. copper: 4 * y1 + 2 * y2 <= 4800 * t;

s.t. frac: variable_cost + fixed_cost * t == 1;

Writing BIM_with_revenues_over_costs.mod

def BIM_with_revenues_over_costs():
m = AMPL()

return m

BIM_fractional = BIM_with_revenues_over_costs()
BIM_fractional.option["solver"] = SOLVER
BIM_fractional.solve()

t = BIM_fractional.var["t"].value()
y1 = BIM_fractional.var["y1"].value()
y2 = BIM_fractional.var["y2"].value()
profit = BIM_fractional.obj["profit"].value()
variable_cost = BIM_fractional.var["variable_cost"].value()
fixed_cost = BIM_fractional.param["fixed_cost"].value()
revenue = BIM_fractional.var["revenue"].value()

print(
"x=({:.1f},{:.1f}) value={:.3f} revenue={:.2f} cost={:.2f}".format(
y1 / t,
y2 / t,
profit / (variable_cost + fixed_cost * t),
revenue / t,
variable_cost / t + fixed_cost,
)
)

HiGHS 1.5.1: HiGHS 1.5.1: optimal solution; objective 10.05076142
4 simplex iterations
0 barrier iterations
x=(250.0,1500.0) value=10.051 revenue=16500.00 cost=1641.67


The second model has optimal solution $$(250,1500)$$ with a revenue of $$16500$$ and a cost of $$1641.667$$.

The efficiency, measured as the ratio of revenue over costs for the optimal solution, is different for the two models. For the first model the efficiency is equal to $$\frac{17700}{1775}=9.972$$, which is strictly smaller than that of the second model, that is $$\frac{16500}{1641.667}=10.051$$.