简体   繁体   中英

How use indices and import data for Python PuLP Mathematical Optimization

I have used optimization modelers in the past, but it's been a while and I am still learning how to do this in python. I have done some online research and am using the open-source version of PuLp https://pythonhosted.org/PuLP/

I have the following formulated and working for three locations. My questions are how to formulate the problem with imported data from a CSV, since my dataset actually includes 70 locations. Typing the number of possibilities for the routes to those routes would seem foolish; I imagine there is a better way to program this. I understand how to use csv.reader() but I am less sure of how to proceed with formulating the problem.

Example Model:

"""
Traveling Salesman Problem (TSP) Simplified Model
Date: 2017-03-30
"""

# Import PuLP modeler functions
from pulp import *

# Create the 'prob' variable to contain the problem data
prob = LpProblem("The TSP Problem1",LpMinimize)

# Formulation summary
#   The decision variable x is equal to 1 or 0, whether the path is chosen
#   Each path has a cost associated with it
#   The objective is to choose the shortest path
#   The constraint, essentially, is that each location is visited

# The LpVariable class has four parameters
    # the first is an arbitrary name
    # the second is the lower bound
    # the third is the upper bound
    # the fourth is the type of data, discrete or continuous
x12=LpVariable("flow12",0,None,LpInteger)
x13=LpVariable("flow13",0,None,LpInteger)
x21=LpVariable("flow21",0,None,LpInteger)
x23=LpVariable("flow23",0,None,LpInteger)
x31=LpVariable("flow31",0,None,LpInteger)
x32=LpVariable("flow32",0,None,LpInteger)

# The objective function is added to 'prob' first
# the objective is to minimize the total distance traveled 
# the numbers represent the distances between two variables

prob += 30*x12 + 5*x13 +25*x21 + 1*x23 + 5*x31 + 8*x32, "Total Distance Traveled"


# The constraints: 

# each location needs to be on the route but only once
prob += x12 + x32 == 1.0, "Location2 is visited"
prob += x13 + x23 == 1.0, "Location3 is visited"
prob += x21 + x31 == 1.0, "Location1 is visited"

# each location is departed exactly once
prob += x31 + x32 == 1.0, "Location3 is departed"
prob += x21 + x23 == 1.0, "Location2 is departed"
prob += x12 + x13 == 1.0, "Location is departed"

# The problem data is written to an .lp file
prob.writeLP("SupplyChainAssignment.lp")

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

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

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

# The optimized objective function value is printed to the screen
print "Total Cost TSP Assignment = ", value(prob.objective)

That's the end of the example which is currently working.

I am thinking that I can use dictionaries such as the following for distance:

distance = {'x12': 30,
            'x13': 5,
            'x21': 25,
            'x23': 1, 
            'x31': 5,
            'x32': 8}

But I am not sure if the following would work for variables:

x = {'x12',
     'x13', 
     'x21',
     'x23', 
     'x31',
     'x32'}

x=LpVariable("flow",0,1,LpInteger)

And that also does not solve my question of how to rewrite the constraints using indices, so I haven't tested whether my guess on syntax above would work:

prob += x12 + x32 == 1.0, "Location2 is visited"
prob += x13 + x23 == 1.0, "Location3 is visited"
prob += x21 + x31 == 1.0, "Location1 is visited"

# each location is departed
prob += x31 + x32 == 1.0, "Location3 is departed"
prob += x21 + x23 == 1.0, "Location2 is departed"
prob += x12 + x13 == 1.0, "Location is departed"

Any suggestions on what I should read up on, or if there are any examples that you could point me to would be helpful.

Thanks!

Read a bit more of the documentation and you will see some good examples

https://pythonhosted.org/PuLP/CaseStudies/a_blending_problem.html#solution-to-full-problem

From this document you will see the following


# A dictionary called 'ingredient_vars' is created to contain the referenced Variables
ingredient_vars = LpVariable.dicts("Ingr",Ingredients,0)

Since costs and ingredient_vars are now dictionaries with the reference keys as the Ingredient names, the data can be simply extracted with a list comprehension as shown. The lpSum() function will add the elements of the resulting list. Thus the objective function is simply entered and assigned a name:

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

Further list comprehensions are used to define the other 5 constraints, which are also each given names describing them.

# The five constraints are added to 'prob'
prob += lpSum([ingredient_vars[i] for i in Ingredients]) == 100, "PercentagesSum"
prob += lpSum([proteinPercent[i] * ingredient_vars[i] for i in Ingredients]) >= 8.0, "ProteinRequirement"
prob += lpSum([fatPercent[i] * ingredient_vars[i] for i in Ingredients]) >= 6.0, "FatRequirement"
prob += lpSum([fibrePercent[i] * ingredient_vars[i] for i in Ingredients]) <= 2.0, "FibreRequirement"
prob += lpSum([saltPercent[i] * ingredient_vars[i] for i in Ingredients]) <= 0.4, "SaltRequirement"

In this example you can see how to define a problem using dictionaries of variables and dictionaries of parameters.

Then you will have to use the csv module to read the parameter data (I would recommend csv.DictReader to do this)

You are right however, it would be nice to have a specific example in the documentation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM