Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo

1

The
                    Optimisation
 University
of Auckland




                     Dr. Stuart Mitchell
              Department of Engineering Science
                    University of Auckland
                        New Zealand
                   s.mitchell@auckland.ac.nz
                December 2008 meeting of NZPUG

2

Contents of presentation


What is Mathematical Programing
     The Whiskas Problem
             PuLP
    Further PuLP examples

3

What is Mathematical
            programing
• A simple mathematically precise way of
  stating optimisation problems.
• Use mathematically rigorous ways to find a
  solution
• Examples of Optimisation Problems that
  can be solved with MP:
  – Shortest Path Problem
  – Scheduling Problems (Set partitioning)
  – Knapsack problems
  – Blending Problems

4

The Whiskas blending problem
• Taken from
  http://130.216.209.237/engsci392/pulp/ABlendingProblem

• Whiskas cat food want to produce their cat
  food products as cheaply as possible while
  ensuring they meet the stated nutritional
  analysis requirements shown on the cans.
• Thus they want to vary the quantities of
  each ingredient used (the main ingredients
  being chicken, beef, mutton, rice, wheat
  and gel) while still meeting their nutritional
  standards.

5

The Whiskas blending problem



  $/kg
  $13

   $8

  $10

   $2

   $5
   $1

6

Whiskas blending problem
• We wish to identify decision variables
• Assume we only have chicken and beef
• Let
  – xc = the percentage of chicken meat
  – xb = the percentage of beef used
• Then we wish to
  minimise $13xc + $8xb

7

Whiskas Blending Problem
• What about the nutritional requirements
• Subject to
  xc+ xb= 100
  0.100xc + 0.200xb >= 8.0
  0.080xc + 0.100xb >= 6.0
  0.001xc + 0.005xb <= 2.0
  0.002xc + 0.005xb <= 0.4
• xc>=0, xb>=0

8

MP Model
Let : I ∈{c , b , m , w , g}the set of ingredients
x i be the percentage of ingredient i in the cat food i∈ I
C i be the cost of ingredient i i ∈I
Pi be the protien content of ingredient i i ∈I
F i be the fat content of ingredient i i ∈I
Fbi be the fibre content of ingredient i i ∈ I
Si be the salt content of ingredient i i ∈ I

                     min ∑ i∈ I C i x i
                     s.t.
                     ∑i∈ I x i=100
                     ∑ i∈ I F i x i≥8
                     ∑i∈ I Fb i xi ≤2
                     ∑i∈ I Si xi≤0.4
                       x i≥0 ∀ i ∈ I

9

Ok where is the python
• On google code you can find pulp-or
  http://code.google.com/p/pulp-or/
• This is a python module that allows the
  easy statement and solution of linear
  programing problems.
• Pulp leverages features of python and the
  open source optimisation libraries Coin-or

10

Whiskas model in python
quot;quot;quot;
The Full Whiskas Model Python Formulation for the PuLP Modeller
Authors: Antony Phillips, Dr Stuart Mitchell 2007
quot;quot;quot;
# Import PuLP modeler functions
from pulp import *
# Creates a list of the Ingredients
Ingredients = ['CHICKEN', 'BEEF', 'MUTTON', 'RICE', 'WHEAT', 'GEL']
# A dictionary of the costs of each of the Ingredients is created
costs = {'CHICKEN': 0.013,
      'BEEF': 0.008,
      'MUTTON': 0.010,
      'RICE': 0.002,
      'WHEAT': 0.005,
      'GEL': 0.001}
# A dictionary of the protein percent in each of the Ingredients is created
proteinPercent = {'CHICKEN': 0.100,
              'BEEF': 0.200,
              'MUTTON': 0.150,
              'RICE': 0.000,
              'WHEAT': 0.040,
              'GEL': 0.000}
# A dictionary of the fat percent in each of the Ingredients is created
fatPercent = {'CHICKEN': 0.080,
          'BEEF': 0.100,
          'MUTTON': 0.110,
          'RICE': 0.010,
          'WHEAT': 0.010,
          'GEL': 0.000}
# A dictionary of the fibre percent in each of the Ingredients is created
fibrePercent = {'CHICKEN': 0.001,
            'BEEF': 0.005,
            'MUTTON': 0.003,
            'RICE': 0.100,
            'WHEAT': 0.150,

11

# Create the 'prob' variable to contain the problem data
prob = LpProblem(quot;The Whiskas Problemquot;, LpMinimize)

# A dictionary called 'Vars' is created to contain the referenced Variables
vars = LpVariable.dicts(quot;Ingrquot;,Ingredients,0)

# The objective function is added to 'prob' first
prob += lpSum([costs[i]*vars[i] for i in Ingredients]), quot;Total Cost of Ingredients per canquot;

# The five constraints are added to 'prob'
prob += lpSum([vars[i] for i in Ingredients]) == 100, quot;PercentagesSumquot;
prob += lpSum([proteinPercent[i] * vars[i] for i in Ingredients]) >= 8.0, quot;ProteinRequirementquot;
prob += lpSum([fatPercent[i] * vars[i] for i in Ingredients]) >= 6.0, quot;FatRequirementquot;
prob += lpSum([fibrePercent[i] * vars[i] for i in Ingredients]) <= 2.0, quot;FibreRequirementquot;
prob += lpSum([saltPercent[i] * vars[i] for i in Ingredients]) <= 0.4, quot;SaltRequirementquot;

# The problem data is written to an .lp file
prob.writeLP(quot;WhiskasModel2.lpquot;)

# The problem is solved using PuLP's choice of Solver
prob.solve()

# The status of the solution is printed to the screen
print quot;Status:quot;, LpStatus[prob.status]

# Each of the variables is printed with it's resolved optimum value
for v in prob.variables():
   print v.name, quot;=quot;, v.varValue

# The optimised objective function value is printed to the screen
print quot;Total Cost of Ingredients per can = quot;, value(prob.objective)

12

The open source future for OR
• Presently the Computational OR tools
  used, taught within this department, are
  closed source.
  – Excel /Storm
  – AMPL, GAMS
  – CPLEX, EXPRESS, ZIP
• Students can not afford commercial
  licences of this software
• Students cannot see how this software
  works.

13

The open source future for OR

• Outcomes for students
  – Ability to access free (no cost) software to
    implement their own solutions once they
    graduate
  – Ability to access free (open) source code to
    see how the algorithms are implemented.
    • Imagine the difference to 391??
  – The ability to improve the software they use.

14

PuLP
• PuLP is a python module that allows the
  easy expression of Mathematical Programs
• PuLP is built to interface with separate
  solvers
• PuLP is similar in style to:
  – AMPL
  – GAMS
  – OPL
  – LINGO
  – FLOPC++ etc.

15

PuLP
• Why Python?
  – Core Python syntax leads to the concise
    statement of MP's
  – Python is a scripting language so no
    compilation is needed and the code is platform
    independent
  – Python interfaces easily with external solvers
    that do the heavy lifting
  – Python comes with 'batteries included'
    • The Python standard library is huge

16

PuLP
• Written initially by J. S. Roy
• Now maintained by S. A. Mitchell
• It is available at
  http://pulp-or.google-code.com
• Now available for Windows and Linux

17

Generating a Yield Frontier

 Total Volume
 of Pulp logs


40m3




           Lines joining
           extreme points
           represent the
           Yield Frontier


                                 Total Volume
                            20m3 of Saw logs

18

Generating a Yield Frontier

• Using pulp we formulate the bucking
  problem (with a single objective) as a set
  packing problem by log section.

19

lp = LpProblem(quot;Bucking Modelquot;, LpMaximize)
#set up the logvolume variables
logvol=LpVariable.dicts(quot;LogVolume(quot;%squot;)quot;,logtypes,0)
#objective
lp+=lpSum([l.price * logvol[l] for l in logtypes]), quot;Revenue“
#setup the arc variables
x=LpVariable.dict(quot;x(%s)quot;,f_logs,0,1,LpInteger)
#set up a section set partitioning problem
count = 0
for s in stems:
       slogs = fs_logs[s]
       for i,sec in enumerate(s.sections):
          lp +=( lpSum((x[log] for log in slogs
                    if log.startl <= sec.start
                    if log.endl > sec.start)) <= 1
                    , quot;Stem_Section(quot;%squot;,%i)quot; % (str(s),i))
          count += 1
#add the constraints that link the log volumes
for lt in logtypes:
       lp +=( lpSum((log.volume*x[log]
                for log in fl_logs[lt])) - logvol[lt] == 0
                , quot;Logtype_volume(quot;%squot;)quot; % str(lt))

20

Generating a Yield Frontier Using Pulp

• We then iteratively solve the problem to find all
  extreme supported solutions on the Yield
  Frontier
• Equivalent to projecting the problem into the log
  volume space
• I added a module to PuLP that implements
  projection using Iterative Hull Methods (Lassez,
  Lassez 1992)
>>> pprob, ppoints = polytope.project(lp, totalvars)

21

Find Yield Frontier for the Dataset

                 (176, 649)
      (0, 650)      (235, 611)




                                 (737,145)



                                       (823, 35)
     (0, 0)
                                         (838, 0)

22

Find Yield Frontier for a Single Stem

* Total projected *
Minimize
OBJ: __dummy
Subject To
_C1: DomSaw + 1.11154598826 ex <= 2669.27592955
_C2: DomSaw + 1.34653465347 ex <= 3118.57425743
_C3: 1.00863930886 DomSaw + ex <= 2522.60691145
Bounds
__dummy = 0
End

23

Travelling tournament problem with PuLP

• This problem models the allocation of
  teams to Home and Away games in a
  tournament
• A full problem description and datasets are
  found at Michael Trick's page
• http://mat.tepper.cmu.edu/TOURN/

24

Travelling tournament problem with PuLP

• At IFORS 2008 M. Trick presented an
  approach to finding lower bounds to this
  problem using combinatorial benders cuts
• That evening I implemented his algorithm
  using PuLP
• Along the way I also added Powerset,
  Combination and Permutation operators to
  PuLP

25

•   lp = LpProblem(quot;Travelling tournement Masterquot;, LpMinimize)
    #create variables
    triplist = [Trip(t1,p) for t1 in teams
                  for p in
                  allpermutations([t for t in
                  teams if t !=t1] ,k)
                  if p[0] <= p[-1]]
    tripvars = LpVariable.dict(quot;mastervar quot;,triplist,0,1,LpInteger)
    #objective
    lp += lpSum([t.cost()*tripvars[t]
                       for t in triplist])
    #construct constraints to ensure that all teams visit each other
        for t1 in teams:
           for t2 in teams:
              if t1 != t2:
                  lp += lpSum([tripvars[t] for t in triplist
                                     if t.team == t1
                                     if t2 in a.awayteams]) == 1, 
                                    quot;Team_%s_Visits_%squot;%(t1,t2)

26

Further examples
• The 392 course has been converted from
  AMPL to PuLP
 http://130.216.209.237/engsci392/pulp/OptimisationWithPuLP
• There you can see a number of different
  ways to construct problems
• Note that new language features can be
  added very easily only needing approval
  from the BDFL

More Related Content

Stuart Mitchell - Pulp Optimisation

  • 1. The Optimisation University of Auckland Dr. Stuart Mitchell Department of Engineering Science University of Auckland New Zealand s.mitchell@auckland.ac.nz December 2008 meeting of NZPUG
  • 2. Contents of presentation What is Mathematical Programing The Whiskas Problem PuLP Further PuLP examples
  • 3. What is Mathematical programing • A simple mathematically precise way of stating optimisation problems. • Use mathematically rigorous ways to find a solution • Examples of Optimisation Problems that can be solved with MP: – Shortest Path Problem – Scheduling Problems (Set partitioning) – Knapsack problems – Blending Problems
  • 4. The Whiskas blending problem • Taken from http://130.216.209.237/engsci392/pulp/ABlendingProblem • Whiskas cat food want to produce their cat food products as cheaply as possible while ensuring they meet the stated nutritional analysis requirements shown on the cans. • Thus they want to vary the quantities of each ingredient used (the main ingredients being chicken, beef, mutton, rice, wheat and gel) while still meeting their nutritional standards.
  • 5. The Whiskas blending problem $/kg $13 $8 $10 $2 $5 $1
  • 6. Whiskas blending problem • We wish to identify decision variables • Assume we only have chicken and beef • Let – xc = the percentage of chicken meat – xb = the percentage of beef used • Then we wish to minimise $13xc + $8xb
  • 7. Whiskas Blending Problem • What about the nutritional requirements • Subject to xc+ xb= 100 0.100xc + 0.200xb >= 8.0 0.080xc + 0.100xb >= 6.0 0.001xc + 0.005xb <= 2.0 0.002xc + 0.005xb <= 0.4 • xc>=0, xb>=0
  • 8. MP Model Let : I ∈{c , b , m , w , g}the set of ingredients x i be the percentage of ingredient i in the cat food i∈ I C i be the cost of ingredient i i ∈I Pi be the protien content of ingredient i i ∈I F i be the fat content of ingredient i i ∈I Fbi be the fibre content of ingredient i i ∈ I Si be the salt content of ingredient i i ∈ I min ∑ i∈ I C i x i s.t. ∑i∈ I x i=100 ∑ i∈ I F i x i≥8 ∑i∈ I Fb i xi ≤2 ∑i∈ I Si xi≤0.4 x i≥0 ∀ i ∈ I
  • 9. Ok where is the python • On google code you can find pulp-or http://code.google.com/p/pulp-or/ • This is a python module that allows the easy statement and solution of linear programing problems. • Pulp leverages features of python and the open source optimisation libraries Coin-or
  • 10. Whiskas model in python quot;quot;quot; The Full Whiskas Model Python Formulation for the PuLP Modeller Authors: Antony Phillips, Dr Stuart Mitchell 2007 quot;quot;quot; # Import PuLP modeler functions from pulp import * # Creates a list of the Ingredients Ingredients = ['CHICKEN', 'BEEF', 'MUTTON', 'RICE', 'WHEAT', 'GEL'] # A dictionary of the costs of each of the Ingredients is created costs = {'CHICKEN': 0.013, 'BEEF': 0.008, 'MUTTON': 0.010, 'RICE': 0.002, 'WHEAT': 0.005, 'GEL': 0.001} # A dictionary of the protein percent in each of the Ingredients is created proteinPercent = {'CHICKEN': 0.100, 'BEEF': 0.200, 'MUTTON': 0.150, 'RICE': 0.000, 'WHEAT': 0.040, 'GEL': 0.000} # A dictionary of the fat percent in each of the Ingredients is created fatPercent = {'CHICKEN': 0.080, 'BEEF': 0.100, 'MUTTON': 0.110, 'RICE': 0.010, 'WHEAT': 0.010, 'GEL': 0.000} # A dictionary of the fibre percent in each of the Ingredients is created fibrePercent = {'CHICKEN': 0.001, 'BEEF': 0.005, 'MUTTON': 0.003, 'RICE': 0.100, 'WHEAT': 0.150,
  • 11. # Create the 'prob' variable to contain the problem data prob = LpProblem(quot;The Whiskas Problemquot;, LpMinimize) # A dictionary called 'Vars' is created to contain the referenced Variables vars = LpVariable.dicts(quot;Ingrquot;,Ingredients,0) # The objective function is added to 'prob' first prob += lpSum([costs[i]*vars[i] for i in Ingredients]), quot;Total Cost of Ingredients per canquot; # The five constraints are added to 'prob' prob += lpSum([vars[i] for i in Ingredients]) == 100, quot;PercentagesSumquot; prob += lpSum([proteinPercent[i] * vars[i] for i in Ingredients]) >= 8.0, quot;ProteinRequirementquot; prob += lpSum([fatPercent[i] * vars[i] for i in Ingredients]) >= 6.0, quot;FatRequirementquot; prob += lpSum([fibrePercent[i] * vars[i] for i in Ingredients]) <= 2.0, quot;FibreRequirementquot; prob += lpSum([saltPercent[i] * vars[i] for i in Ingredients]) <= 0.4, quot;SaltRequirementquot; # The problem data is written to an .lp file prob.writeLP(quot;WhiskasModel2.lpquot;) # The problem is solved using PuLP's choice of Solver prob.solve() # The status of the solution is printed to the screen print quot;Status:quot;, LpStatus[prob.status] # Each of the variables is printed with it's resolved optimum value for v in prob.variables(): print v.name, quot;=quot;, v.varValue # The optimised objective function value is printed to the screen print quot;Total Cost of Ingredients per can = quot;, value(prob.objective)
  • 12. The open source future for OR • Presently the Computational OR tools used, taught within this department, are closed source. – Excel /Storm – AMPL, GAMS – CPLEX, EXPRESS, ZIP • Students can not afford commercial licences of this software • Students cannot see how this software works.
  • 13. The open source future for OR • Outcomes for students – Ability to access free (no cost) software to implement their own solutions once they graduate – Ability to access free (open) source code to see how the algorithms are implemented. • Imagine the difference to 391?? – The ability to improve the software they use.
  • 14. PuLP • PuLP is a python module that allows the easy expression of Mathematical Programs • PuLP is built to interface with separate solvers • PuLP is similar in style to: – AMPL – GAMS – OPL – LINGO – FLOPC++ etc.
  • 15. PuLP • Why Python? – Core Python syntax leads to the concise statement of MP's – Python is a scripting language so no compilation is needed and the code is platform independent – Python interfaces easily with external solvers that do the heavy lifting – Python comes with 'batteries included' • The Python standard library is huge
  • 16. PuLP • Written initially by J. S. Roy • Now maintained by S. A. Mitchell • It is available at http://pulp-or.google-code.com • Now available for Windows and Linux
  • 17. Generating a Yield Frontier Total Volume of Pulp logs 40m3 Lines joining extreme points represent the Yield Frontier Total Volume 20m3 of Saw logs
  • 18. Generating a Yield Frontier • Using pulp we formulate the bucking problem (with a single objective) as a set packing problem by log section.
  • 19. lp = LpProblem(quot;Bucking Modelquot;, LpMaximize) #set up the logvolume variables logvol=LpVariable.dicts(quot;LogVolume(quot;%squot;)quot;,logtypes,0) #objective lp+=lpSum([l.price * logvol[l] for l in logtypes]), quot;Revenue“ #setup the arc variables x=LpVariable.dict(quot;x(%s)quot;,f_logs,0,1,LpInteger) #set up a section set partitioning problem count = 0 for s in stems: slogs = fs_logs[s] for i,sec in enumerate(s.sections): lp +=( lpSum((x[log] for log in slogs if log.startl <= sec.start if log.endl > sec.start)) <= 1 , quot;Stem_Section(quot;%squot;,%i)quot; % (str(s),i)) count += 1 #add the constraints that link the log volumes for lt in logtypes: lp +=( lpSum((log.volume*x[log] for log in fl_logs[lt])) - logvol[lt] == 0 , quot;Logtype_volume(quot;%squot;)quot; % str(lt))
  • 20. Generating a Yield Frontier Using Pulp • We then iteratively solve the problem to find all extreme supported solutions on the Yield Frontier • Equivalent to projecting the problem into the log volume space • I added a module to PuLP that implements projection using Iterative Hull Methods (Lassez, Lassez 1992) >>> pprob, ppoints = polytope.project(lp, totalvars)
  • 21. Find Yield Frontier for the Dataset (176, 649) (0, 650) (235, 611) (737,145) (823, 35) (0, 0) (838, 0)
  • 22. Find Yield Frontier for a Single Stem * Total projected * Minimize OBJ: __dummy Subject To _C1: DomSaw + 1.11154598826 ex <= 2669.27592955 _C2: DomSaw + 1.34653465347 ex <= 3118.57425743 _C3: 1.00863930886 DomSaw + ex <= 2522.60691145 Bounds __dummy = 0 End
  • 23. Travelling tournament problem with PuLP • This problem models the allocation of teams to Home and Away games in a tournament • A full problem description and datasets are found at Michael Trick's page • http://mat.tepper.cmu.edu/TOURN/
  • 24. Travelling tournament problem with PuLP • At IFORS 2008 M. Trick presented an approach to finding lower bounds to this problem using combinatorial benders cuts • That evening I implemented his algorithm using PuLP • Along the way I also added Powerset, Combination and Permutation operators to PuLP
  • 25. lp = LpProblem(quot;Travelling tournement Masterquot;, LpMinimize) #create variables triplist = [Trip(t1,p) for t1 in teams for p in allpermutations([t for t in teams if t !=t1] ,k) if p[0] <= p[-1]] tripvars = LpVariable.dict(quot;mastervar quot;,triplist,0,1,LpInteger) #objective lp += lpSum([t.cost()*tripvars[t] for t in triplist]) #construct constraints to ensure that all teams visit each other for t1 in teams: for t2 in teams: if t1 != t2: lp += lpSum([tripvars[t] for t in triplist if t.team == t1 if t2 in a.awayteams]) == 1, quot;Team_%s_Visits_%squot;%(t1,t2)
  • 26. Further examples • The 392 course has been converted from AMPL to PuLP http://130.216.209.237/engsci392/pulp/OptimisationWithPuLP • There you can see a number of different ways to construct problems • Note that new language features can be added very easily only needing approval from the BDFL