| |||||||||||||
| |||||||||||||
|
Transport Description A company produces the same product at different plants.
Every plant has a different production cost per unit and
a limited total capacity. The customers (grouped into
customer regions) may receive the product from different
production locations. The transport cost is proportional
to the distance between plants and customers, and the
capacity on every delivery route is limited. The objective
is to minimize the total cost, whilst satisfying the
demands of all customers. Further explanation of this example: 'Mosel User Guide', Section 3.1 'A transport example', Section 10.1 'Producing formatted output'. Similar problem: 'Applications of optimization with Xpress-MP', Section 10.1 'Car rental' (e1carrent.mos)
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
Data Files transport_graph.mos
(!******************************************************
Mosel Example Problems
======================
file transport.mos
``````````````````
TYPE: Transport problem
DIFFICULTY: 2
FEATURES: simple LP problem, using dynamic arrays for data and
decision variables, formatted output printing, inline `if',
format of data files
DESCRIPTION: A company produces the same product at different plants.
Every plant has a different production cost per unit and
a limited total capacity. The customers (grouped into
customer regions) may receive the product from different
production locations. The transport cost is proportional
to the distance between plants and customers, and the
capacity on every delivery route is limited. The objective
is to minimize the total cost, whilst satisfying the
demands of all customers.
FURTHER INFO: `Mosel User Guide', Section 3.1 `A transport example',
Section 10.1 `Producing formatted output'.
Similar problem:
`Applications of optimization with Xpress-MP',
Section 10.1 `Car rental'
(c) 2008 Fair Isaac Corporation
author: S.Heipcke, Jan. 2001, rev. Nov. 2017
*******************************************************!)
model Transport
uses "mmxprs", "mmsvg"
forward procedure print_table
forward procedure draw_solution
declarations
REGION: set of string ! Set of customer regions
PLANT: set of string ! Set of plants
DEMAND: array(REGION) of real ! Demand at regions
PLANTCAP: array(PLANT) of real ! Production capacity at plants
PLANTCOST: array(PLANT) of real ! Unit production cost at plants
TRANSCAP: dynamic array(PLANT,REGION) of real ! Capacity on each route plant->region
DISTANCE: dynamic array(PLANT,REGION) of real ! Distance of each route plant->region
FUELCOST: real ! Fuel cost per unit distance
flow: dynamic array(PLANT,REGION) of mpvar ! Flow on each route
end-declarations
initializations from 'transport.dat'
DEMAND
[PLANTCAP,PLANTCOST] as 'PLANTDATA'
[DISTANCE,TRANSCAP] as 'ROUTES'
FUELCOST
end-initializations
! Create the flow variables that exist
forall(p in PLANT, r in REGION | exists(TRANSCAP(p,r)) ) create(flow(p,r))
! Objective: minimize total cost
MinCost:= sum(p in PLANT, r in REGION | exists(flow(p,r)))
(FUELCOST * DISTANCE(p,r) + PLANTCOST(p)) * flow(p,r)
! Limits on plant capacity
forall(p in PLANT) Capacity(p):= sum(r in REGION) flow(p,r) <= PLANTCAP(p)
! Satisfy all demands
forall(r in REGION) Demand(r):= sum(p in PLANT) flow(p,r) = DEMAND(r)
! Bounds on flows
forall(p in PLANT, r in REGION | exists(flow(p,r)))
flow(p,r) <= TRANSCAP(p,r)
! Solve the problem
minimize(MinCost)
! Solution printing
print_table
! Solution drawing
draw_solution
!***********************************************************************
procedure print_table
declarations
rsum: array(REGION) of integer ! Auxiliary data table for printing
psum,prsum,ct,iflow: integer ! Counters
end-declarations
! Print heading and the first line of the table
writeln("\nProduct Distribution\n--------------------")
writeln(strfmt("Sales Region",44))
write(strfmt("",14))
forall(r in REGION) write(strfmt(r,9))
writeln(strfmt("TOTAL",9), " Capacity")
! Print the solution values of the flow variables and
! calculate totals per region and per plant
ct:=0
forall(p in PLANT) do
ct += 1
write(if(ct=2,"Plant "," "), strfmt(p,-8))
psum:=0
forall(r in REGION) do
iflow:=integer(getsol(flow(p,r)))
psum += iflow
rsum(r) += iflow
write(if( iflow<>0, strfmt(iflow,9), " -- "))
end-do
writeln(strfmt(psum,9), strfmt(integer(PLANTCAP(p)),9))
end-do
! Print the column totals
write("\n", strfmt("TOTAL",-14))
prsum:=0
forall(r in REGION) do
prsum += rsum(r)
write(strfmt(rsum(r),9))
end-do
writeln(strfmt(prsum,9))
! Print demand of every region
write(strfmt("Demand",-14))
forall(r in REGION) write(strfmt(integer(DEMAND(r)),9))
! Print objective function value
writeln("\n\nTotal cost of distribution = ", strfmt(getobjval/1e6,0,3),
" million.")
end-procedure
!***********************************************************************
procedure draw_solution
declarations
YP: array(PLANT) of integer ! y-coordinates of plants
YR: array(REGION) of integer ! y-coordinates of sales regions
end-declarations
! Scale the size of the displayed graph
svgsetgraphviewbox(0,1,4,getsize(REGION)+1)
svgsetgraphscale(100)
! Determine y-coordinates for plants and regions
ct:= 1+floor((getsize(REGION)-getsize(PLANT))/2)
forall(p in PLANT, ct as counter) YP(p):= ct
ct:=1
forall(r in REGION, ct as counter) YR(r):= ct
! Draw the plants
svgaddgroup("PGr", "Plants", svgcolor(0,63,95))
forall(p in PLANT) svgaddtext(0.55, YP(p)-0.05, p)
! Draw the sales regions
svgaddgroup("RGr", "Regions", svgcolor(0,157,169))
forall(r in REGION) svgaddtext(3.1, YR(r)-0.05, r)
! Draw all transport routes
svgaddgroup("TGr", "Routes", SVG_GREY)
forall(p in PLANT, r in REGION | exists(TRANSCAP(p,r)) )
svgaddline(1, YP(p), 3, YR(r))
! Draw the routes used by the solution
svgaddgroup("SGr", "Solution", SVG_ORANGE)
forall(p in PLANT, r in REGION | exists(flow(p,r)) and getsol(flow(p,r)) > 0)
svgaddarrow(1, YP(p), 3, YR(r))
svgsave("transport.svg")
svgrefresh
svgwaitclose("Close browser window to terminate model execution.", 1)
end-procedure
end-model
| |||||||||||||
| © Copyright 2025 Fair Isaac Corporation. |