| |||||||||||||
| |||||||||||||
|
Coco: The Coco productional planning problem Description The company Coco has two plants that can produce two types
of cocoa powder. The plant capacities are limited.
It is possible to store raw materials and finished product
from one time period to the next. Raw material prices,
sales revenues, and the maximum amount that may be sold
depend on the time period. Raw material storage capacity
is limited.
Storing product between time periods incurs storage costs.
Some product is held in stock at the beginning of the
planning period.
The objective function of maximizing the total profit is
to maximize the sales revenues, minus the cost of production,
buying raw material, and storing finished products and raw
material. Further explanation of this example: 'Xpress Python Reference Manual'
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
coco.py
# Example for the use of the Python language (Complete Coco Problem).
#
# Specify phase by PHASE parameter. Data input in the model.
#
# (C) 2018-2025 Fair Isaac Corporation
import xpress as xp
PHASE = 5
'''* Phase = 3: Multi-period parameterised model; mines always open
* Phase = 4: Mines may open/closed freely; when closed save 20000 per month
* Phase = 5: Once closed always closed; larger saving
'''
NT = 4 # Number of time periods.
RP = [0, 1] # Range of products (p).
RF = [0, 1] # Range of factories (f).
RR = [0, 1] # Range of raw materials (r).
RT = [i for i in range(NT)] # Time periods (t).
CPSTOCK = 2.0 # Unit cost to store any product p.
CRSTOCK = 1.0 # Unit cost to store any raw material r.
MXRSTOCK = 300 # Max. amount of r that can be stored each f and t.
Post = [i for i in range(0, NT+1)]
prob = xp.problem()
# Amount of product p made at factory f.
make = prob.addVariables(RP, RF, RT, name='make')
# Amount of product p sold from factory f in period t.
sell = prob.addVariables(RP, RF, RT, name='sell')
# Amount of raw material r bought for factory f in period t.
buy = prob.addVariables(RR, RF, RT, name='buy')
# Stock level of product p at factory f at start of period t.
pstock = prob.addVariables(RP, RF, Post, name='pst')
# Stock level of raw material r at factory f at start of period t.
rstock = prob.addVariables(RR, RF, Post, name='rst')
# 1 if factory f is open in period t, else 0.
openm = prob.addVariables(RF, RT, name='openm', vartype=xp.binary)
REV = [[400, 380, 405, 350],
[410, 397, 412, 397]]
CMAKE = [[150, 153],
[75, 68]]
CBUY = [[100, 98, 97, 100],
[200, 195, 198, 200]]
COPEN = [50000, 63000]
REQ = [[1.0, 0.5],
[1.3, 0.4]]
MXSELL = [[650, 600, 500, 400],
[600, 500, 300, 250]]
MXMAKE = [400, 500]
PSTOCK0 = [[50, 100],
[50, 50]]
RSTOCK0 = [[100, 150],
[50, 100]]
# Objective: maximize total profit.
MaxProfit = (
xp.Sum(REV[p][t] * sell[p, f, t] for p in RP
for f in RF for t in RT) - # Revenue.
xp.Sum(CMAKE[p][f] * make[p, f, t] for p in RP
for f in RF for t in RT) - # Prod. cost.
xp.Sum(CBUY[r][t] * buy[r, f, t] for r in RR
for f in RF for t in RT) - # Raw mat. cost.
xp.Sum(CPSTOCK * pstock[p, f, t] for p in RP
for f in RF for t in range(1, NT+1)) - # p stor. cost.
xp.Sum(CRSTOCK * rstock[r, f, t] for r in RR
for f in RF for t in range(1, NT+1))) # r stor. cost.
if PHASE == 4: # Factory fixed cost.
MaxProfit -= xp.Sum((COPEN[f] - 20000) * openm[f, t]
for f in RF for t in RT)
elif PHASE == 5:
MaxProfit -= xp.Sum(COPEN[f] * openm[f, t] for f in RF for t in RT)
prob.setObjective(MaxProfit, sense=xp.maximize)
# Product stock balance.
prob.addConstraint(pstock[p, f, t+1] == pstock[p, f, t]
+ make[p, f, t] - sell[p, f, t]
for p in RP for f in RF for t in RT)
# Raw material stock balance.
prob.addConstraint(rstock[r, f, t+1] == rstock[r, f, t] + buy[r, f, t] -
xp.Sum(REQ[p][r]*make[p, f, t] for p in RP)
for r in RR for f in RF for t in RT)
# Capacity limit at factory f.
prob.addConstraint(xp.Sum(make[p, f, t] for p in RP) <= MXMAKE[f] * openm[f, t]
for f in RF for t in RT)
# Limit on the amount of prod. p to be sold.
prob.addConstraint(xp.Sum(sell[p, f, t] for f in RF) <= MXSELL[p][t]
for p in RP for t in RT)
# Raw material stock limit.
prob.addConstraint(xp.Sum(rstock[r, f, t] for r in RR) <= MXRSTOCK
for f in RF for t in range(NT))
if PHASE == 5: # Once closed, always closed.
prob.addConstraint(openm[f, t+1] <= openm[f, t]
for f in RF for t in range(NT - 1))
# Initial product levels.
prob.addConstraint(pstock[p, f, 1] == PSTOCK0[p][f] for p in RP for f in RF)
# Initial raw material levels.
prob.addConstraint(rstock[r, f, 1] == RSTOCK0[r][f] for r in RR for f in RF)
if PHASE < 4:
prob.addConstraint(openm[f, t] == 1 for f in RF for t in RT)
prob.optimize() # Solve the LP or MIP-problem.
# Print out the solution.
print("Solution:\n Objective: ", prob.attributes.objval)
hline = 60*"-"
print("Total profit: ", prob.attributes.objval)
print(hline)
print(8*" ", "Period", end='')
for t in range(NT+1):
print("{:8}".format(t), end='')
print("\n", hline)
print("Finished products\n",
"=================")
make_sol = prob.getSolution(make)
sell_sol = prob.getSolution(sell)
pstock_sol = prob.getSolution(pstock)
for f in RF:
print(" Factory", f)
for p in RP:
print(3*" ", "P", p, ": Prod", 12*" ", end='', sep='')
for t in RT:
print("{:8.2f}".format(make_sol[p, f, t]), end='')
print('')
print(8*" ", "Sell", 12*" ", end='', sep='')
for t in RT:
print("{:8.2f}".format(sell_sol[p, f, t]), end='')
print('')
print(7*" ", "(Stock)", end='')
for t in range(NT+1):
print(" (", "{:4.1f}".format(pstock_sol[p, f, t]),
")", end='', sep='')
print('')
buy_sol = prob.getSolution(buy)
rstock_sol = prob.getSolution(rstock)
print(hline)
print("Raw material\n",
"============")
for f in RF:
print(" Factory", f)
for r in RR:
print(3*" ", "R", r, ": Buy", 12*" ", end='', sep='')
for t in RT:
print("{:8.2f}".format(buy_sol[r, f, t]), end='')
print('')
print(8*" ", "Use", 12*" ", end='', sep='')
for t in RT:
print("{:8.2f}".format(sum(REQ[p][r] *
make_sol[p, f, t]
for p in RP)), end='')
print('')
print(7*" ", "(Stock)", end='')
for t in range(NT+1):
print(" (", "{:4.1f}".format(rstock_sol[r, f, t]),
")", end='', sep='')
print('')
print(hline)
| |||||||||||||
| © Copyright 2025 Fair Isaac Corporation. |