(!*********************************************************************
Mosel NL examples
=================
file boxes02.mos
````````````````
A craftsman makes small wooden boxes for sale.
He has four different shapes or styles of box, and can make each of
them in any size (keeping all the dimensions in proportion).
The profit he makes on a box depends on the size.
He has only a limited amount of the necessary wood available and a
limited amount of time in the week to do the work.
How many boxes should he make, and what size should they be,
in order to maximize his profit?
(c) 2013 Fair Issac Corporation
author: S. Heipcke, Nov. 2005, rev. Feb. 2013
*********************************************************************!)
model "Boxes"
uses "mmxnlp"
declarations
BOXES = {"Cube", "Oblong", "Flat", "Economy"} ! Box types
make: array(BOXES) of mpvar ! Number produced per box type
size, battens, ply, profit, mtime: array(BOXES) of mpvar ! Properties per box type
LENGTH,WIDTH,HEIGHT,PROFIT,DUR: array(BOXES) of real ! Length, width, height, profit, time
TotalProfit: nlctr ! Objective: total profit
end-declarations
LENGTH :: (["Cube", "Oblong", "Flat", "Economy"])[1,1,4,1]
WIDTH :: (["Cube", "Oblong", "Flat", "Economy"])[1,2,4,2]
HEIGHT :: (["Cube", "Oblong", "Flat", "Economy"])[1,1,1,1]
PROFIT :: (["Cube", "Oblong", "Flat", "Economy"])[20,27.3,90,10] ![20,24,90,10]
DUR :: (["Cube", "Oblong", "Flat", "Economy"])[1,1,1,0.2]
forall (b in BOXES) do
battens(b) = 4*(LENGTH(b)+WIDTH(b)+HEIGHT(b))*size(b)
ply(b) = 2*(LENGTH(b)*WIDTH(b)+WIDTH(b)*HEIGHT(b)+HEIGHT(b)*LENGTH(b))*size(b)^2
profit(b) = PROFIT(b)*size(b)^1.5
mtime(b) = 1 + DUR(b)*1.5^(ply(b)/10)
end-do
! Bounds on size and number of boxes
forall(b in BOXES) do
size(b) <= 2
make(b) <= 6
make(b) is_integer
end-do
! Limits on resource availability
sum(b in BOXES) make(b)*battens(b) <= 200
sum(b in BOXES) make(b)*ply(b) <= 210
sum(b in BOXES) make(b)*mtime(b) <= 35
! Objective function: total profit
TotalProfit := sum(B in BOXES) make(B)*profit(B)
setparam("xnlp_verbose", true)
! Solve the problem
maximize(TotalProfit)
! Solution display
forall (b in BOXES | make(b).sol>0) writeln(getsol(make(b)), " '", b,
"' boxes of size ", getsol(size(b)),
" each using ", getsol(battens(b)),
" cm of battens, ", getsol(ply(b))," sq cm of plywood, ",
strfmt(getsol(mtime(b)),0,2), " hours")
writeln("\nTotal profit ", getobjval)
writeln("Total battens ",
strfmt(getsol(sum(b in BOXES) make(b)*battens(b)),0,2)," cm")
writeln("Total ply ",
strfmt(getsol(sum(b in BOXES) make(b)*ply(b)),0,2)," sq cm")
writeln("Total mtime ",
strfmt(getsol(sum(b in BOXES) make(b)*mtime(b)),0,2)," hours")
end-model
|
(!*********************************************************************
Mosel NL examples
=================
file pricechange.mos
````````````````````
Five dealers in adjacent stalls at a market were selling apples
of identical quality, so they had to keep their prices equal. At the
end of the day every dealer had sold a different number of apples,
yet all had taken in the same total.
How much did they charge and how much did they take in, assuming
that all prices were integer values?
Note: The problem is possible only if the price was changed during
the course of the day. We minimize the number of price changes.
Based on AMPL model pchange.mod by M.J.Chlond
Reference: M. Kraitchik, Mathematical Recreations (p. 33-35), Dover
(c) 2013 Fair Issac Corporation
author: S. Heipcke, Mar. 2013, rev. Dec. 2017
*********************************************************************!)
model "pricechange"
uses "mmxnlp", "mmsystem"
parameters
NP = 4 ! Maximum number of price changes
MAXPRICE = 10 ! Highest permissible price
end-parameters
forward procedure print_sol
declarations
DEALERS: set of string ! Dealers
PRICES = 1..NP ! Prices
NSOLD: array(DEALERS) of real ! Total number sold by each dealer
sell: array(DEALERS,PRICES) of mpvar ! Number sold by dealer i at price j
price: array(PRICES) of mpvar ! Price j (i.e. first and second prices)
pchange: array(PRICES) of mpvar ! 1 iff price j and j+1 are different
totalrev: mpvar ! Total revenu per dealer
end-declarations
NSOLD:: (["Mr.Brown","Mrs.White","Mr.Black","Mr.Grey","Ms.Violet"])[10, 25, 30, 15, 35]
! More difficult: [10, 25, 30, 12, 35]
! Easy: [10, 25, 30, 15, 35]
finalize(DEALERS)
forall(i in DEALERS,p in PRICES) do
sell(i,p)<=NSOLD(i)
sell(i,p) is_integer
end-do
forall(p in PRICES) do
price(p)>=1
price(p)<=MAXPRICE
price(p) is_integer
pchange(p) is_binary
end-do
! Quantities sold
forall(i in DEALERS) NSOLD(i) = sum(p in PRICES) sell(i,p)
! All dealers take in the same
forall(i in DEALERS)
sum(p in PRICES) (price(p)*sell(i,p)) = totalrev
! Direction of price changes (symmetry breaking)
price(2) >= price(1)+1
! Counter the number of price changes
forall(p in PRICES | p>1) price(p) >= price(p-1)+pchange(p)
forall(p in PRICES | p>1) price(p)-price(p-1) <= MAXPRICE*pchange(p)
! Solve the problem
setparam("xnlp_verbose",true)
! Obj 1: Minimize total span of prices
MaxDiff:= price(NP)-price(1)
! Obj2 : Minimize number of price changes
TotalChanges:= sum(p in PRICES | p>1) pchange(p)
! Solve the problem for the different objectives
minimize(MaxDiff)
print_sol
minimize(TotalChanges)
print_sol
! Obj3 + 4 : Minimize + maximize total revenue per dealer
minimize(totalrev)
print_sol
maximize(totalrev)
print_sol
!**************** Solution printing ****************
procedure print_sol
nlstat:=getparam("XNLP_STATUS")
if nlstat<>XNLP_STATUS_LOCALLY_OPTIMAL and nlstat<>XNLP_STATUS_OPTIMAL then
writeln("No solution found.")
else
writeln("Number of price changes: ", TotalChanges.sol)
writeln("Amplitude of prices: ", MaxDiff.sol)
writeln("Total revenue per dealer: ", totalrev.sol)
writeln("Quantities sold: ")
writeln(" "*(21+round(TotalChanges.sol)), "Quantity at prices")
write("Dealer TotalQty")
forall(p in PRICES | p=1 or pchange(p).sol>0)
write(strfmt(price(p).sol,5),"/kg")
writeln("\n", "-"*(22+(round(TotalChanges.sol)+1)*8))
forall(i in DEALERS) do
write(strfmt(i,-9), strfmt(NSOLD(i),9), " ")
forall(p in PRICES | p=1 or pchange(p).sol>0)
write(strfmt(sum(q in PRICES | price(q).sol=price(p).sol)
round(sell(i,q).sol),8))
writeln
end-do
writeln("-"*(22+(round(TotalChanges.sol)+1)*8))
end-if
end-procedure
end-model
|
(!*********************************************************************
Mosel NL examples
=================
file pricechange_graph.mos
``````````````````````````
Five dealers in adjacent stalls at a market were selling apples
of identical quality, so they had to keep their prices equal. At the
end of the day every dealer had sold a different number of apples,
yet all had taken in the same total.
How much did they charge and how much did they take in, assuming
that all prices were integer values?
Note: The problem is possible only if the price was changed during
the course of the day. We minimize the number of price changes.
Based on AMPL model pchange.mod by M.J.Chlond
Reference: M. Kraitchik, Mathematical Recreations (p. 33-35), Dover
- Graphical representation of results -
(c) 2013 Fair Issac Corporation
author: S. Heipcke, Mar. 2013, rev. Dec. 2017
*********************************************************************!)
model "pricechange"
uses "mmxnlp", "mmsystem", "mmsvg"
parameters
NP = 4 ! Maximum number of price changes
MAXPRICE = 10 ! Highest permissible price
end-parameters
forward procedure print_sol
forward procedure draw_sol(title: text, offset: real, iter: integer)
declarations
DEALERS: set of string ! Dealers
PRICES = 1..NP ! Prices
NSOLD: array(DEALERS) of real ! Total number sold by each dealer
sell: array(DEALERS,PRICES) of mpvar ! Number sold by dealer i at price j
price: array(PRICES) of mpvar ! Price j (i.e. first and second prices)
pchange: array(PRICES) of mpvar ! 1 iff price j and j+1 are different
totalrev: mpvar ! Total revenu per dealer
end-declarations
NSOLD:: (["Mr.Brown","Mrs.White","Mr.Black","Mr.Grey","Ms.Violet"])[10, 25, 30, 15, 35]
! More difficult: [10, 25, 30, 12, 35]
! Easy: [10, 25, 30, 15, 35]
finalize(DEALERS)
forall(i in DEALERS,p in PRICES) do
sell(i,p)<=NSOLD(i)
sell(i,p) is_integer
end-do
forall(p in PRICES) do
price(p)>=1
price(p)<=MAXPRICE
price(p) is_integer
pchange(p) is_binary
end-do
! Quantities sold
forall(i in DEALERS) NSOLD(i) = sum(p in PRICES) sell(i,p)
! All dealers take in the same
forall(i in DEALERS)
sum(p in PRICES) (price(p)*sell(i,p)) = totalrev
! Direction of price changes (symmetry breaking)
price(2) >= price(1)+1
! Counter the number of price changes
forall(p in PRICES | p>1) price(p) >= price(p-1)+pchange(p)
forall(p in PRICES | p>1) price(p)-price(p-1) <= MAXPRICE*pchange(p)
! Solve the problem
setparam("xnlp_verbose",true)
! Obj 1: Minimize total span of prices
MaxDiff:= price(NP)-price(1)
! Obj2 : Minimize number of price changes
TotalChanges:= sum(p in PRICES | p>1) pchange(p)
! Scale the size of the displayed graph
svgsetgraphscale(5)
! Solve the problem for the different objectives
minimize(MaxDiff)
print_sol
draw_sol("Obj 1 (rev="+totalrev.sol+")", 0, 1)
minimize(TotalChanges)
print_sol
draw_sol("Obj 2 (rev="+totalrev.sol+")", 0.2, 2)
! Obj3 + 4 : Minimize + maximize total revenue per dealer
minimize(totalrev)
print_sol
draw_sol("Obj 3 (rev="+totalrev.sol+")", 0.4, 3)
maximize(totalrev)
print_sol
draw_sol("Obj 4 (rev="+totalrev.sol+")", 0.6, 4)
svgsave("pricechange.svg")
svgwaitclose("Close browser window to terminate model execution.", 1)
!**************** Solution printing ****************
procedure print_sol
nlstat:=getparam("XNLP_STATUS")
if nlstat<>XNLP_STATUS_LOCALLY_OPTIMAL and nlstat<>XNLP_STATUS_OPTIMAL then
writeln("No solution found.")
else
writeln("Number of price changes: ", TotalChanges.sol)
writeln("Amplitude of prices: ", MaxDiff.sol)
writeln("Total revenue per dealer: ", totalrev.sol)
writeln("Quantities sold: ")
writeln(" "*(21+round(TotalChanges.sol)), "Quantity at prices")
write("Dealer TotalQty")
forall(p in PRICES | p=1 or pchange(p).sol>0)
write(strfmt(price(p).sol,5),"/kg")
writeln("\n", "-"*(22+(round(TotalChanges.sol)+1)*8))
forall(i in DEALERS) do
write(strfmt(i,-9), strfmt(NSOLD(i),9), " ")
forall(p in PRICES | p=1 or pchange(p).sol>0)
write(strfmt(sum(q in PRICES | price(q).sol=price(p).sol)
round(sell(i,q).sol),8))
writeln
end-do
writeln("-"*(22+(round(TotalChanges.sol)+1)*8))
end-if
end-procedure
!**************** Graphical representation of results ****************
procedure draw_sol(title: text, offset: real, iter: integer)
nlstat:=getparam("XNLP_STATUS")
if nlstat=XNLP_STATUS_LOCALLY_OPTIMAL or nlstat=XNLP_STATUS_OPTIMAL then
SCALE:=10
svgsetgraphviewbox(0,-4,SCALE*(DEALERS.size+2),MAXPRICE*min(i in DEALERS) NSOLD(i)+10)
svgsetgraphlabels("","Total sales prices per dealer")
! Draw the total revenue
svgaddgroup("plotr"+iter, title, svgcolor(200,25,25))
svgaddline(0, totalrev.sol, SCALE*(DEALERS.size+1), totalrev.sol)
svgaddtext(SCALE*(DEALERS.size+1)+1, totalrev.sol-1, "Iteration "+iter)
! Draw a bar chart with the quantity sold per price for every dealer
if iter=1 then
forall(p in 1..MAXPRICE) do
svgaddgroup("P"+p, string(p)+"$/kg", svgcolor(25*p,100-5*p,250-25*p))
writeln( svgcolor(25*p,100-5*p,250-25*p))
svgsetstyle(SVG_FILL,SVG_CURRENT)
end-do
svgaddgroup("D", "Dealers", SVG_BLACK)
svgsetstyle(SVG_FONTSIZE,"xx-small")
forall(i in DEALERS, ct as counter)
svgaddtext(SCALE*(ct-0.4+offset), -2, i)
ct:=0
end-if
forall(i in DEALERS, ct as counter) do
totd:=0
forall(p in PRICES | p=1 or pchange(p).sol>0) do
totq:=sum(q in PRICES | price(q).sol=price(p).sol) round(sell(i,q).sol*price(p).sol)
if totq>0 then
pv:=round(price(p).sol)
svgaddrectangle("P"+pv, SCALE*(ct-0.4+offset), totd, SCALE*(0.15), totq)
totd+=totq
end-if
end-do
end-do
svgrefresh
end-if
end-procedure
end-model
|