Ограничить максимальный размер выделения с помощью смешанного целочисленного программирования - PullRequest
0 голосов
/ 29 августа 2018

У меня есть 2 объекта, у каждого есть трубопровод и стоимость установки. У меня также есть 16 клиентов для обслуживания, у каждого клиента есть стоимость обслуживания. Я хочу назначить каждому объекту максимум 10 клиентов, чтобы минимизировать затраты на трубопровод, установку и обслуживание.

Я реализовал следующий код, но он не работает должным образом. Предполагается, что каждый объект назначается числу клиентов, которых он должен обслуживать, и возвращает минимальные затраты. Тем не менее, на выходе назначить скважины для всех объектов (я думаю).

Ваша помощь очень ценится:

import numpy as np
from pulp import *
import random 
CUSTOMERS = range(1,17) ## generate random Customer Ids
FACILITY =['FAC 1','FAC 2'] # Number and Name of Facilities
randomCosts = random.sample(range(90, 100), 2) ## Generate Random Installation Costs 
actcost = dict(zip(FACILITY, randomCosts)) ## Assign installation cost to each facility
randompipelineCost = random.sample(range(5, 20), 2) ## Generate Random pipeline Costs
pipelineCost = dict(zip(FACILITY, randompipelineCost))## Assign pipeline cost to each facility
sizeOfPlatforms = [10,10] ## Size of Platforms
maxSizeOfPlatforms = dict(zip(FACILITY, sizeOfPlatforms)) ## Assign Size to each Facility
serviceRandom=[] 
serviceCosts = {}
for facility in FACILITY: ## Generate Random Service Costs for each customer
   serviceRandom=[]
   for i in range (16):
     serviceRandom.append(random.randrange(1, 101, 1))
   service = dict(zip(CUSTOMERS, serviceRandom))
   serviceCosts[facility]=service

print 'CUSTOMERS', CUSTOMERS
print 'FACILITY', FACILITY
print 'Facility Cost', actcost 
print 'pipeline Cost',pipelineCost 
print 'service Cost', serviceCosts 

prob = LpProblem("FacilityLocation",LpMinimize)


##Decision Variables

use_facility = LpVariable.dicts("UseFacility", FACILITY,0,1,LpBinary)

use_customer = LpVariable.dicts("UseCustomer",[(i,j) for i in CUSTOMERS for j in FACILITY],1)

## Objective Function 

prob += lpSum(actcost[j]*use_facility[j] for j in FACILITY) + lpSum(pipelineCost[j]*use_facility[j] for j in FACILITY)+ lpSum(serviceCosts[j][i]*use_customer[(i,j)] for i in CUSTOMERS for j in FACILITY)

# Constraints 

for j in FACILITY: 
   prob += lpSum(use_customer[(i,j)] for i in CUSTOMERS) <= maxSizeOfPlatforms[j]


for j in FACILITY: 
   prob += lpSum(use_facility[j] for j in FACILITY) <=1.0 ##Constraint 1 

##Solution 

prob.solve() 
print ("Status:", LpStatus[prob.status])

TOL = 0.00001 


## print Decision Variables
for i in FACILITY: 
   if use_facility[i].varValue > TOL:
     print("Establish Facility at Site",i)

for v in prob.variables():
  print(v.name,"=", v.varValue)


##optimal Solution
print ("The cost of production in dollars for one year=", value(prob.objective))

1 Ответ

0 голосов
/ 29 августа 2018

Есть 4 разных проблемы.

1)

use_customer = LpVariable.dicts("UseCustomer",[(i,j) for i in CUSTOMERS for j in FACILITY],1)

Это эквивалентно тому, что каждая переменная дробная и должна быть больше единицы . То есть вы устанавливаете lowBound=1. Я думаю, что вы хотели бы сказать здесь, что переменная является двоичной:

use_customer = LpVariable.dicts("UseCustomer",[(i,j) for i in CUSTOMERS for j in FACILITY], cat=LpBinary)

2)

Вторая проблема заключается в том, что вы не ограничиваете клиента назначением хотя бы в какое-либо учреждение (хотя бы потому, что поскольку проблема является проблемой минимизации, а ваши затраты строго положительны, клиент никогда не будет назначен более чем одному средство, но в дальнейшем я приму ровно один )

for i in CUSTOMERS: 
     prob += lpSum(use_customer[(i,j)] for j in FACILITY) == 1.0 

3)

Я не уверен, что понял, что вы хотели бы сказать здесь:

for j in FACILITY: 
   prob += lpSum(use_facility[j] for j in FACILITY) <=1.0 ##Constraint 1 

Каждый раз, когда вы суммируете все объекты и ограничивает сумму их значений не более одного. Я думаю, это ошибка.

4) * * тысяча двадцать шесть

Наконец, вы не связываете переменные use_facility и use_customer вместе. То есть переменная use_facility никогда не будет иметь значение, большее чем 0. Поскольку она является двоичной, я предполагаю, что use_facility[j] представляет стоимость активации. Таким образом, вам нужно добавить, чтобы активировать объект, то есть объект j активируется, если его использует хотя бы один клиент :

for j in FACILITY:
    for i in CUSTOMERS:
        prob += use_facility[j] >= lpSum(use_customer[(i,j)])

Собираем все вместе:

##Decision Variables

use_facility = LpVariable.dicts("UseFacility", FACILITY, cat=LpBinary)

use_customer = LpVariable.dicts("UseCustomer",[(i,j) for i in CUSTOMERS for j in FACILITY], cat=LpBinary)

## Objective Function 

prob += lpSum(actcost[j]*use_facility[j] for j in FACILITY) + lpSum(pipelineCost[j]*use_facility[j] for j in FACILITY)+ lpSum(serviceCosts[j][i]*use_customer[(i,j)] for i in CUSTOMERS for j in FACILITY)


# Constraints 
for j in FACILITY: 
   prob += lpSum(use_customer[(i,j)] for i in CUSTOMERS) <= maxSizeOfPlatforms[j]

for i in CUSTOMERS: 
   prob += lpSum(use_customer[(i,j)] for j in FACILITY) == 1

for j in FACILITY:
    for i in CUSTOMERS:
        prob += use_facility[j] >= lpSum(use_customer[(i,j)])
...