当前位置: 首页 > 知识库问答 >
问题:

Gekko优化

连时铭
2023-03-14

我正在解决这个优化问题,我需要计算出我需要打开多少个配送中心,以满足12家公司设施的需求,同时最小化运输成本。运输成本只是配送中心之间的距离乘以每英里成本,然而在这个问题中,每英里成本是一美元。我有5个选择,分别是波士顿、纳舒亚、普罗维登斯、斯普林菲尔德和伍斯特,这5个是12家公司设施的一部分。

我解决了这个问题,得到了正确的答案,但是后来我试图在同一个代码中添加两个约束,我得到的答案是不正确的。另外两个约束是从配送中心到其他设施(客户)的平均距离必须小于60英里;第二个约束是50英里内的客户百分比必须大于80%(0.8)。我知道这个问题的答案,成本必须是66,781美元,平均客户距离是15英里,50英里内的客户百分比是90%。我的代码的输出是成本为66289美元,平均客户距离为15.36英里,50英里内的客户百分比为179%,这没有意义。

你能帮我弄清楚为什么我得到一个奇怪的输出吗?提前感谢。

from gekko import GEKKO
import numpy as np
import pandas as pd
import math

m = GEKKO(remote=False) #So that it solves the problem locally
m.options.SOLVER = 1 #MILP

varx = [[0 for col in range(12)] for row in range(5)] #Creates an empty list
for i in range (5):
    for j in range (12):
        varx[i][j] = m.Var(lb = 0, integer = True) 

varx = np.array(varx)    
varxt = np.transpose(varx)



vary = np.empty([]) #Creates an empty array

for i in range(5):
    vary = np.append(vary, m.Var(lb = 0, ub = 1, integer = True)) #Yes/No variables

vary = vary[1:13] 



dists = np.array([[0 , 93, 69, 98, 55, 37, 128, 95, 62, 42, 82, 34], #Boston
                 [37, 65, 33, 103, 20, 0, 137, 113, 48, 72, 79, 41], #Nashua
                 [42, 106, 105, 73, 92, 72, 94, 57, 104, 0, 68, 38], #Providence
                 [82, 59, 101, 27, 93, 79, 63, 57, 127, 68, 0,  47], #Springfield
                 [34, 68, 72, 66, 60, 41, 98, 71, 85, 38, 47,   0]]) #Worcester



max_dist = 60 #Max average distance (in miles)
min_pct = 0.8 #Min percent of demand within 50 miles



aij = np.zeros((5, 12)) #Creates an empty array

for i in range (5):
    for j in range (12):
        if dists[i][j] <= 50:
            aij[i][j] = 1
        else:
            aij[i][j] = 0 #Creates a 0s and 1s array. If the distance to a costumer 
                          #is less than 50, then the matrix element is 1, it is zero
                          #otherwise


dem_consts = np.array([425, 12, 43, 125, 110, 86, 129, 28, 66, 320, 220, 182])

fixd_cost = 10000


sum1 = np.sum(np.multiply(varx, dists))
sum2 = np.sum(vary*fixd_cost)
z = sum1 + sum2 

tot_dem = np.sum(dem_consts)

M = tot_dem



m.Minimize(z)



for i in range(12):
    m.Equation(np.sum(varxt[i, :]) >= dem_consts[i]) #Demand constraints

for i in range(5):
    m.Equation(np.sum(varx[i, :]) <= 2000) #Capacity constraints
    m.Equation(np.sum(varx[i, :]) <= M*vary[i]) #Enforces 0 or 1 value

m.Equation(np.sum(vary[:]) >= 1)


di_sum = np.sum(np.multiply(varx, dists))
di_sumw = di_sum/ tot_dem
m.Equation(di_sumw <= max_dist) #Average (demand) weighted distance from DC to customer

a_sum = np.sum(np.multiply(varx, aij)) 
a_sumw = a_sum/tot_dem
m.Equation(a_sumw >= min_pct) #Percent of demand that is within 50 miles

m.solve(disp = False)


p1 = np.zeros((5, 12))

for i in range (5):
    for j in range (12):
        p1[i][j] = varx[i][j].value[0]
p1t = np.transpose(p1)

p2 = np.zeros((5, )) 

for i in range(5):
    p2[i] = vary[i].value[0] 

mad1 = np.sum(np.multiply(p1, dists)) 
mad2 = mad1/tot_dem
mpi1 = np.sum(np.multiply(p1, aij)) 
mpi2 = mpi1/tot_dem

tot1 = np.sum(np.multiply(p1, dists))
tot2 = np.sum(p2)*fixd_cost
tot = tot1 + tot2 


print('The minimum cost is:' +str(tot))
print('Average customer distance:' +str(mad2))
print('Percent of customers <= 50 miles:' +str(mpi2))


dc = np.array(['Boston', 'Nashua', 'Providence', 'Springfield', 'Worcester'])
cities = ['Boston', 'Brattleboro', 'Concord', 'Hartford', 'Manchester', 'Nashua',
          'New Haven', 'New London', 'Portsmouth', 'Providence', 'Springfield', 'Worcester']
data = {cities[0]: p1t[0], cities[1]: p1t[1], cities[2]: p1t[2], cities[3]: p1t[3],
       cities[4]: p1t[4], cities[5]: p1t[5], cities[6]: p1t[6], cities[7]: p1t[7],
       cities[8]: p1t[8], cities[9]: p1t[9], cities[10]: p1t[10], cities[11]: p1t[11]}

df = pd.DataFrame(data, index = dc)
df

共有1个答案

邹京
2023-03-14

当您设置m.solve(disp=True)时,解算器会在500次迭代时提前终止。它返回一个可行的整数解,但可能不是最佳解。

 Warning: best integer solution returned after maximum MINLP iterations
 Adjust minlp_max_iter_with_int_sol  500  in apopt.opt to change limit
 Successful solution

 ---------------------------------------------------
 Solver         :  APOPT (v1.0)
 Solution time  :  1.3654 sec
 Objective      :  66829.
 Successful solution
 ---------------------------------------------------


The minimum cost is:66829.0
Average customer distance:15.3659793814433
Percent of customers <= 50 miles:1.7943871706758305

如果添加解算器选项:

m.solver_options = ['minlp_gap_tol 1.0e-2',\
                    'minlp_maximum_iterations 10000',\
                    'minlp_max_iter_with_int_sol 5000']

目标函数改进为66285:

 Successful solution

 ---------------------------------------------------
 Solver         :  APOPT (v1.0)
 Solution time  :  1.7178 sec
 Objective      :  66285.
 Successful solution
 ---------------------------------------------------


The minimum cost is:66285.0
Average customer distance:20.781786941580755
Percent of customers <= 50 miles:1.9873997709049256

客户的百分比是否应该

Percent of customers <= 50 miles (mpi3):0.8994297563504406

新的平均距离是:

Average customer distance (mad3):9.405132192846034

这是一个修改后的脚本,它使用gekko数组和gekko sum函数,以便提高效率。

from gekko import GEKKO
import numpy as np
import pandas as pd
import math

m = GEKKO(remote=False) #So that it solves the problem locally
m.options.SOLVER = 1 #MILP

varx = m.Array(m.Var,(5,12),lb=0,integer=True)
vary = m.Array(m.Var,5,lb=0,ub=1,integer=True)

dists = np.array([[0 , 93, 69, 98, 55, 37, 128, 95, 62, 42, 82, 34], #Boston
                 [37, 65, 33, 103, 20, 0, 137, 113, 48, 72, 79, 41], #Nashua
                 [42, 106, 105, 73, 92, 72, 94, 57, 104, 0, 68, 38], #Providence
                 [82, 59, 101, 27, 93, 79, 63, 57, 127, 68, 0,  47], #Springfield
                 [34, 68, 72, 66, 60, 41, 98, 71, 85, 38, 47,   0]]) #Worcester

max_dist = 60 #Max average distance (in miles)
min_pct = 0.8 #Min percent of demand within 50 miles

#Creates a 0s and 1s array. If the distance to a costumer 
#is less than 50, then the matrix element is 1, it is zero otherwise
aij = [[1 if dists[i,j]<=50 else 0 for j in range(12)] for i in range(5)]

dem_consts = np.array([425, 12, 43, 125, 110, 86, 129, 28, 66, 320, 220, 182])
fixd_cost = 10000
sum1 = np.sum(np.multiply(varx, dists))
sum2 = np.sum(vary*fixd_cost)
z = sum1 + sum2 
tot_dem = np.sum(dem_consts)
M = tot_dem
m.Minimize(z)

for j in range(12):
    m.Equation(m.sum(varx[:,j]) >= dem_consts[j]) #Demand constraints

for i in range(5):
    m.Equation(m.sum(varx[i,:]) <= 2000) #Capacity constraints
    m.Equation(m.sum(varx[i,:]) <= M*vary[i]) #Enforces 0 or 1 value

m.Equation(m.sum(vary) >= 1)


di_sum = np.sum(np.multiply(varx, dists))
di_sumw = di_sum/ tot_dem
m.Equation(di_sumw <= max_dist) #Average (demand) weighted distance from DC to customer

a_sum = np.sum(np.multiply(varx, aij)) 
a_sumw = m.Intermediate(a_sum/tot_dem)
m.Equation(a_sumw >= min_pct) #Percent of demand that is within 50 miles


m.solver_options = ['minlp_gap_tol 1.0e-2',\
                    'minlp_maximum_iterations 10000',\
                    'minlp_max_iter_with_int_sol 5000']
m.solve(disp = True)


p1 = np.zeros((5, 12))

for i in range (5):
    for j in range (12):
        p1[i][j] = varx[i][j].value[0]
p1t = np.transpose(p1)

p2 = np.zeros(5) 
for i in range(5):
    p2[i] = vary[i].value[0] 

mad1 = np.sum(np.multiply(p1, dists)) 
mad2 = mad1/tot_dem
mad3 = mad1/np.sum(p1)
mpi1 = np.sum(np.multiply(p1, aij)) 
mpi2 = mpi1/tot_dem
mpi3 = mpi1/np.sum(p1)

tot1 = np.sum(np.multiply(p1, dists))
tot2 = np.sum(p2)*fixd_cost
tot = tot1 + tot2 

print(p1)
print(p2)
print('The minimum cost is:' +str(tot))
print('Average customer distance (mad2):' +str(mad2))
print('Average customer distance (mad3):' +str(mad3))
print('Percent of customers <= 50 miles (mpi2):' +str(mpi2))
print('Percent of customers <= 50 miles (mpi3):' +str(mpi3))

dc = np.array(['Boston', 'Nashua', 'Providence', 'Springfield', 'Worcester'])
cities = ['Boston', 'Brattleboro', 'Concord', 'Hartford', 'Manchester', 'Nashua',
          'New Haven', 'New London', 'Portsmouth', 'Providence', 'Springfield', 'Worcester']
data = {cities[0]: p1t[0], cities[1]: p1t[1], cities[2]: p1t[2], cities[3]: p1t[3],
       cities[4]: p1t[4], cities[5]: p1t[5], cities[6]: p1t[6], cities[7]: p1t[7],
       cities[8]: p1t[8], cities[9]: p1t[9], cities[10]: p1t[10], cities[11]: p1t[11]}

df = pd.DataFrame(data, index = dc)
df

以下是解决方案:

[[1102.    0.   43.    0.  110.   86.    0.    0.   66.    0.    0.  182.]
 [   0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.]
 [   0.    0.    0.    0.    0.    0.    0.   28.    0.  495.    0.    0.]
 [   0.   12.    0.  125.    0.    0.  129.    0.    0.    0. 1480.    0.]
 [   0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.]]
[1. 0. 1. 1. 0.]
The minimum cost is:66285.0
Average customer distance (mad2):20.781786941580755
Average customer distance (mad3):9.405132192846034
Percent of customers <= 50 miles (mpi2):1.9873997709049256
Percent of customers <= 50 miles (mpi3):0.8994297563504406
 类似资料:
  • 我试图用Python中的GEKKO定义一个优化问题,我想使用一些带有预定义选择列表的设计变量。此外,每个选择都有一个相关的成本,约束条件是总成本应低于指定的限制。 下面是一个常见的壁虎示例(在这里找到),修改后的x1和x2是sos1。此外,利用所选值x1和x2的索引,我从另一个列表中找到了它们的相关成本,它们的总和应该小于某个值(约束)。 注意:我必须在函数中添加一个if块作为的初始值,而似乎为零

  • This repo is not maintained anymore I am officially not maintaining this project anymore. It was an amazing journey and I want to thank everyone forplaying the role in this amazing story! More details

  • 函数“def gekko_obj(x)”适用于任何x值。 但是,当m作为Gekko目标函数调用时,它会失败。Obj(gekko_obj(x))。 文件“/anaconda3/lib/python3.6/site packages/spyder/utils/site/sitecustomize.py”,第710行,在runfile execfile(文件名,命名空间)中 文件“/anaconda3/

  • Gekko BacktestTool CLI tool that enhances the features of Gekko's Trading Bot. The tool performs a test with multiple pairs on a single run. Suppose you have a strategy that you want to test on more c

  • 我目前正试图用Gekko的分支来解决一个混合整数非线性问题 以下是我迄今为止的尝试:

  • 我刚刚开始使用Gekko优化软件。到目前为止,我找到了如何获得问题的最优解。但我不确定是否有可能看到满足约束的所有可能结果?(不仅是最佳值)。问题是,对于我的特定任务,我需要多次进行优化,尽管最优值在某一点上是最优的,但最优决策序列可能会随着时间的推移而不同。我想通过创建MDP来检查这一点。但要做到这一点,我需要知道可能的状态,这些状态表示要优化的变量的所有可能值,它们满足约束。我还没有发现如何在