Gekko 中具有时间间隙的同时间距和持续时间约束

问题描述 投票:0回答:1

我正在尝试同时对 Gekko 中的矢量解输出强制执行连续持续时间和间距约束。通常,使用窗口逻辑这将相当简单,但我的时间数组(以周为单位)在下面的“周”数组中存在间隙(例如,它是 [13, 14, 17...])。

我能够通过使用下面的代码查找下一个连续周的索引来获得几周内的间距要求(似乎适用于“s”的所有值),但我不确定如何将“d”(必须运行的连续周数)纳入现有解决方案中(下面是完整的可重现示例)。

对于 s=1 和 d=2,我正在寻找的通用解决方案输出如下所示:[13, 14, 17, 18, 33, 34, 50, 51...]

import numpy as np
import pandas as pd
from gekko import GEKKO
m = GEKKO(remote=False)
m.options.NODES = 3
m.options.IMODE = 3
m.options.MAX_ITER = 1000

lnuc_weeks = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]

min_promo_price = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,3]

max_promo_price = [3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5,3.5, 3.5, 3.5, 3.5, 3.5, 3.5]

base_srp = [3.48, 3.48, 3.48, 3.48, 3.0799, 3.0799, 3.0799, 3.0799,3.0799, 3.0799, 3.0799, 3.0799, 3.0799, 3.0799, 3.0799, 3.0799, 3.0799, 3.0799, 3.0799]

lnuc_min_promo_price = 1.99

lnuc_max_promo_price = 1.99

coeff_fedi = [0.022589, 0.022589, 0.022589, 0.022589, 0.022589, 0.022589,0.022589, 0.022589, 0.022589, 0.022589, 0.022589, 0.022589, 0.022589, 0.022589, 0.022589, 0.022589, 0.022589, 0.022589, 0.022589]

coeff_feao = [0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995, 0.02929995]

coeff_diso = [0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338, 0.05292338]

sumproduct_base = [0.20560305, 0.24735297, 0.24957423, 0.23155435, 0.23424058,0.2368096 , 0.27567109, 0.27820648, 0.2826393 , 0.28660598, 0.28583971, 0.30238505, 0.31726649, 0.31428312, 0.31073792, 0.29036779, 0.32679041, 0.32156337, 0.24633734]

neg_ln = [[0.14842000515],[0.14842000512],[0.14842000515],[0.14842000512],[-0.10407483058],[0.43676249024],[0.43676249019],[0.43676249024],[0.43676249019],[0.43676249024],[0.43676249019], [0.026284840258],[0.026284840291],[0.026284840258],[0.026284840291], [0.026185109811],[0.026284840258],[0.026284840291],[0.026284840258]]

neg_ln_ppi_coeff = [1.22293879, 1.22293879, 1.22293879, 1.22293879, 1.22293879,1.22293879, 1.22293879, 1.22293879, 1.22293879, 1.22293879, 1.22293879, 1.22293879, 1.22293879, 1.22293879, 1.22293879,1.22293879, 1.22293879, 1.22293879, 1.22293879]

base_volume = [124.38, 193.2, 578.72, 183.88, 197.42, 559.01, 67.68, 110.01,60.38, 177.11, 102.65, 66.02, 209.83, 81.22, 250.44, 206.44, 87.99, 298.95, 71.07]

week = pd.Series([13, 14, 17, 18, 19, 26, 28, 33, 34, 35, 39, 42, 45, 46, 47, 48, 50, 51, 52])


n = 19

x1 = m.Array(m.Var,(n), integer=True) #LNUC weeks

i = 0
for xi in x1:
    xi.value = lnuc_weeks[i]
    xi.lower = 0
    xi.upper = lnuc_weeks[i]
    i += 1

x2 = m.Array(m.Var,(n)) #Blended SRP

i = 0
for xi in x2:
    xi.value = 5
    m.Equation(xi >= m.if3((x1[i]) - 0.5, min_promo_price[i], lnuc_min_promo_price))
    m.Equation(xi <= m.if3((x1[i]) - 0.5, max_promo_price[i], lnuc_max_promo_price))
    i += 1
x3 = m.Array(m.Var,(n), integer=True) #F&D
x4 = m.Array(m.Var,(n), integer=True) #FO
x5 = m.Array(m.Var,(n), integer=True) #DO
x6 = m.Array(m.Var,(n), integer=True) #TPR

#Default to F&D
i = 0
for xi in x3:
    xi.value = 1
    xi.lower = 0
    xi.upper = 1
    i += 1

i = 0
for xi in x4:
    xi.value = 0
    xi.lower = 0
    xi.upper = 1
    i += 1

i = 0
for xi in x5:
    xi.value = 0
    xi.lower = 0
    xi.upper = 1
    i += 1

i = 0
for xi in x6:
    xi.value = 0
    xi.lower = 0
    xi.upper = 1
    i += 1

x7 = m.Array(m.Var,(n), integer=True) #Max promos

i = 0
for xi in x7:
    xi.value = 1
    xi.lower = 0
    xi.upper = 1
    i += 1

x = [x1,x2,x3,x4,x5,x6,x7]

neg_ln=[m.Intermediate(-m.log(x[1][i]/base_srp[i])) for i in range(n)]

total_vol_fedi  =[m.Intermediate(coeff_fedi[0]+ sumproduct_base[i] + (neg_ln[i]*neg_ln_ppi_coeff[0])) for i in range(n)]
total_vol_feao  =[m.Intermediate(coeff_feao[0]+ sumproduct_base[i] + (neg_ln[i]*neg_ln_ppi_coeff[0])) for i in range(n)]
total_vol_diso  =[m.Intermediate(coeff_diso[0]+ sumproduct_base[i] + (neg_ln[i]*neg_ln_ppi_coeff[0])) for i in range(n)]
total_vol_tpro  =[m.Intermediate(sumproduct_base[i] + (neg_ln[i]*neg_ln_ppi_coeff[0])) for i in range(n)]

simu_total_volume = [m.Intermediate((
(m.max2(0,base_volume[i]*(m.exp(total_vol_fedi[i])-1)) * x[2][i] +
m.max2(0,base_volume[i]*(m.exp(total_vol_feao[i])-1)) * x[3][i] +
m.max2(0,base_volume[i]*(m.exp(total_vol_diso[i])-1)) * x[4][i] +
m.max2(0,base_volume[i]*(m.exp(total_vol_tpro[i])-1)) * x[5][i]) + base_volume[i]) * x[6][i]) for i in range(n)]


[m.Equation(x3[i] + x4[i] + x5[i] + x6[i] == 1) for i in range(i)]

#Limit max promos
m.Equation(sum(x7)<=10)

#Enforce spacing and duration
d=2
s=1
for s2 in range(1, s+1):
    for i in range(0, n-s2):
        f = week[week == week[i] + s2].index
        if len(f) > 0:
            m.Equation(x7[i] + x7[f[0]]<=1)

m.Maximize(m.sum(simu_total_volume))

m.options.SOLVER=1
m.solve(disp = True)

df = pd.concat([pd.Series(week), pd.Series([i[0] for i in x7]), pd.Series([i[0] for i in simu_total_volume])], axis=1)
df.columns = ['week', 'x7', 'total_volume']
df[df['x7']>0]
python optimization linear-programming gekko mixed-integer-programming
1个回答
0
投票

下面是一个可能有帮助的持续时间和间距限制的最小示例。决策变量是何时开始促销。促销选择是在

st
优化后进行后处理的。

from gekko import GEKKO
import numpy as np

# Initialize the model
m = GEKKO(remote=False)

# Define weeks and parameters
weeks = np.arange(1,11)  # Week numbers [1,2,...,9,10]
n_weeks = len(weeks)  # Number of weeks
d = 3  # Duration constraint: number of consecutive weeks
s = 2  # Spacing constraint: number of weeks between events

# Define variables
# start promo location
st = m.Array(m.Var,n_weeks,integer=True,lb=0,ub=1)

# Objective Function
m.Maximize(sum(st))

# Always start on first week available
m.fix(st[0],1)
# Don't start at the end if duration constraint doesn't allow it
for i in range(n_weeks-d+1,n_weeks):
    m.Equation(st[i]==0)

# Spacing Constraint
for i in range(n_weeks-d-s):
    m.Equation(sum(st[i:i+d+s]) <= 1)

# Solve the problem
m.options.SOLVER=1
m.solve(disp=True)

# Output the solution
print("Weeks:", weeks)
print("Start Promo:", [int(si.VALUE[0]) for si in st])
x = np.zeros(n_weeks)
for i in range(0,n_weeks-d+1):
    if (int(st[i].VALUE[0])==1):
        x[i:i+d]=1
print("Promo occurrence:", [int(xi) for xi in x])

该解决方案遵循持续时间 (

d=3
) 和间距 (
s=2
) 约束。除非有足够的持续时间来满足最短持续时间限制,否则不会安排促销活动的开始。

Weeks: [ 1  2  3  4  5  6  7  8  9 10]
Start Promo: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0]
Promo occurrence: [1, 1, 1, 0, 0, 1, 1, 1, 0, 0]
© www.soinside.com 2019 - 2024. All rights reserved.