2016-03-26 10 views
2

Я написал следующий код Python, используя библиотеку PuLP для решения проблемы Knapsack, используя формулировку Integer Programming. Я использую строки для генерации команд LpVariable и добавляю ограничения, а затем выполняю их с помощью eval. Есть ли способ сделать это без использования eval?Как создать переменные и ограничения PuLP без использования exec?

from pulp import * 

#Knapsack problem 

items = input ('Enter the number of items :') 

items = int(items) 

#print('Enter %d items one by one') 

print ('Enter {0} items profit one by one'.format(items)) 

obj = [] 
weight = [] 
knapweight = 0 


for i in range(0,items): 
    print('Enter {0} item profit : '.format(i+1)) 
    obj.append(input()) 

for i in range(0, items): 
    print('The profit at {0} is {1}'.format(i, obj[i])) 

print ('\nEnter {0} items weights one by one'.format(items)) 


for i in range(0, items): 
    print('Enter {0} item weight'.format(i+1)) 
    weight.append(input()) 

for i in range(0, items): 
    print('The profit at {0} is {1}'.format(i, weight[i])) 

print ('\nEnter the weight of the knapsack :') 
knapweight = input() 

print ('The weight of the knapsack is : {0}'.format(knapweight)) 


#generating variables 
for i in range(0, items): 
    str = 'x{0} = LpVariable("x{1}", cat=\'Binary\')'.format(i+1,i+1) 
    print (str) 
    exec(str) 

prob = LpProblem('Knapsack', LpMaximize) 

print ('\nDynamic Generaion\n') 

#weight constraint generation 
str = "prob += " 

for i in range(0, items): 
    if i == (items-1): 
     str = str + weight[i] + '*x{0}'.format(i+1) 
    else: 
     str = str + weight[i] + '*x{0}'.format(i+1) + '+' 

str = str + '<=' + knapweight 
exec(str) 
print(str) 

#objective function generation 
str = "prob += " 

for i in range(0, items): 
    if i == (items-1): 
     str = str + obj[i] + '*x{0}'.format(i+1) 
    else: 
     str = str + obj[i] + '*x{0}'.format(i+1) + '+' 

exec(str) 
print(str) 

status = prob.solve() 
print(LpStatus[status]) 

print ('\nThe values of the variables : \n') 

for i in range(0, items): 
    print('x{0} = {1}'.format(i+1, value(eval('x{0}'.format(i+1))))) 

ответ

3

Ключ признающего, что это нормально, чтобы иметь объект - скажем, один в списке или словарь - который вы не явным образом связанный с именем. Вы можете сделать объект, добавить его в список и только ссылаться на него как some_list[2]. Как только вы позволите себе эту свободу, ваш код может стать намного проще.

Здесь я жёстко входы, потому что это не имеет значения:

from pulp import * 

objs = [2,3,2,5,3] 
weights = [1,2,2,1,3] 
knapweight = 5 

prob = LpProblem('Knapsack', LpMaximize) 
xs = [LpVariable("x{}".format(i+1), cat="Binary") for i in range(len(objs))] 

# add objective 
total_prof = sum(x * obj for x,obj in zip(xs, objs)) 
prob += total_prof 

# add constraint 
total_weight = sum(x * w for x,w in zip(xs, weights)) 
prob += total_weight <= knapweight 

status = prob.solve() 
print(LpStatus[status]) 
print("Objective value:", value(prob.objective)) 
print ('\nThe values of the variables : \n') 
for v in prob.variables(): 
    print(v.name, "=", v.varValue) 

, который дает мне

Optimal 
Objective value: 10.0 

The values of the variables : 

x1 = 1.0 
x2 = 1.0 
x3 = 0.0 
x4 = 1.0 
x5 = 0.0 

Здесь я построения LpVariables в списке понимание

xs = [LpVariable("x{}".format(i+1), cat="Binary") for i in range(len(objs))] 

где объекты тогда просто живут в списке xs.

>>> xs 
[x1, x2, x3, x4, x5] 
>>> xs[3] 
x4 
>>> type(xs[3]) 
<class 'pulp.pulp.LpVariable'>