优化充电站选择

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

跟进问题在 Python 中使用 PuLP 优化 EV 充电站选择

当前设置

from pulp import * 

from matplotlib import pyplot as plt
BC = 100 # battery capacity
SOC_in = 1.0 # (%) initial state of charge 
SOC_max = 1.0 #(%) maximum SOC

# energy consumed in each trip segment
e_c = [23.5,  4.6,  4.4, 33.8, 89.5,  0. , 24.5,  4.7, 21.5,  0. ,  0. ,
       16.2,  4.8, 20.1,  0. , 62.8,  0.6, 40.8, 41.1,  5.1, 16.7,  0. ,
       39.6,  9.6,  9.8, 23.7,  0. ,  0. , 23.4,  5.3,  8.6, 23.7, 18.6,
        5.8,  9.1,  0.1,  0. ,  0.1,  0. ,  0.3, 19.8,  0. ,  4.9, 23.4,
        7.7,  9.6,  8. ,  1. ,  0. ,  0. ,  0. ,  0. , 28.1,  5.5,  9.3,
        0. ,  0.1, 27.9, 41.3,  2.8, 20.8,  6.4,  5.7, 28.4,  7.7, 35.2,
        2.8, 21. , 11.8,  0.1, 21.6,  7.4, 13.5,  8.6,  7.5,  0. , 12.8,
       10.5,  0.4,  0. ,  0. ,  0.5, 37.2,  5.8, 19. , 10.7, 21.7, 17.1,
        0.9,  0. , 17.1, 12. ,  7.9,  2.4,  0.2, 20.6,  4.9, 21.1]

# energy recharged in each trip segment
e_r = [30.7,  64.8,  31.2, 181.2,   2.2,  66.5,  30.3,  52.8,  43.8,
        54.1, 151.1,  33.9,  22.2,  68.3,  66.4,  70.2, 170.5, 260.2,
        32.7,  72.6,  89.1, 138.1,  54.6,  70.2,  24.3,  42.2,  44.4,
        38. ,  38.8,  30.1,  28.7, 179.4,  48.6,  96.6,   0.2,  38.5,
        44.5,   0.4,   0.4,  28.8,  13.5,  25.5,  44.9, 196.8, 269.8,
       215.7,  81.1, 166.6,   0.4,   0.4,   0.1,  22.3, 111.9,  36.9,
        43.3,  38. , 712.2,   9.7,  25.2, 242.3,  24.5,  49.4,  31.6,
       231.6,   0.4,  27.5, 228.6,  31.7, 685.1, 812.4,  84.5,  36.7,
        28.4, 214.7,   0.5,  46. ,  61.3,   0.4,   0.4,  22.4,   0.4,
         0.5,  47.5,  27. ,  43.8, 182.3,  24.2,  76.3,  54. , 748.8,
        72. ,  46. ,  31.3, 113.2,   0.4,  22.7,  70.6,  78.9]

candidate_nodes = range(len(e_c))
n = len(candidate_nodes)


# Define optimization problem
model = LpProblem("EV charging optimization modellem", LpMinimize)

### Decision variables
X = LpVariable.dicts("UseLocation", candidate_nodes, cat=LpBinary)
E = LpVariable.dicts("energy", candidate_nodes, lowBound=0, upBound = 100, cat = LpContinuous)


### Objective function
model += lpSum(X[i] for i in candidate_nodes)

### Constraints

# Initial energy level
model += E[0] == SOC_in * BC  # typo fixed

for i in range(n-1):
    # Energy at next stop (only add charge if charging station is built there)
    model += E[i+1] <= E[i] - e_c[i] + (e_r[i] * X[i])  # less than or equal => prevent over-charge

    # Energy does not exceed battery capacity
    model += E[i+1] <= BC * SOC_max

    # Has enough energy to reach the next stop without going below minimum battery level
    model += E[i] >= e_c[i] 

# Solve
status = model.solve()

# print the "build plan":
build_plan = [i for i in candidate_nodes if X[i].varValue > 0]
print('build at nodes: ')
print(build_plan)

plt.plot(candidate_nodes, [E[i].varValue for i in candidate_nodes], color='r', label='no bonus')
plt.scatter(build_plan, [0 for t in build_plan], s=10, alpha=0.6, color='orange', label='no-bonus charge')

# replace the objective function with this
model += lpSum(X[i] for i in candidate_nodes) - 1/(100*100)*lpSum(E[i] for i in candidate_nodes)
status2 = model.solve()

# QA the build plan has the same NUMBER of build points
build_plan_2 = [i for i in candidate_nodes if X[i].varValue > 0]
assert len(build_plan) == len(build_plan_2)

print('build at nodes: ', build_plan_2)
plt.plot(candidate_nodes, [E[i].varValue for i in candidate_nodes], color='b', label='bonus')
plt.scatter(build_plan_2, [0 for t in build_plan_2], s=10, alpha=0.6, color='g', label='charge')
plt.legend(loc='upper right')
plt.show()

以上作品。 BUT e_r 处的每个节点代表车辆停止充电的点,不一定是唯一的充电站。以下数组 'station_labels ' 实际上包含车辆停在哪个充电站。

station_labels = [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 2, 1, 0, 0, 1, 1,
       0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 3, 4, 4, 1, 0, 0, 0, 4, 4, 4,
       1, 0, 1, 1, 0, 0, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 0, 0, 4, 4, 5, 4,
       4, 4, 4, 4, 4, 1, 1, 0, 0, 3]

所以车辆在充电站 0 停了三次,然后去充电站 1,然后又是 0,等等。从这个数组可以看出,车辆完成充电可能需要 0、1 和 4 站它的行程而 2、3 和 5 可能不是因为车辆几乎没有访问它们。 (事实上 ,当您运行优化时,第 5 站未被使用,但 2 和 3 可能不需要)

目标: 将断点映射到它们在优化问题中代表的实际站点

到目前为止尝试过:
我尝试将决策变量 X 更改为 station_labels 中的唯一值,然后通过更改“下一站能量”约束将 X 映射到约束中的站点标签。

所以

X = LpVariable.dicts("UseLocation", candidate_nodes, cat=LpBinary)

改为

X = LpVariable.dicts("UseLocation", range(len(np.unique(station_labels))), lowBound=0, upBound=1, cat=LpBinary)

model += E[i+1] <= E[i] - e_c[i] + (e_r[i] * X[i])  

改为

model += E[i+1] <= E[i] - e_c[i] + (e_r[i] * X[station_labels[i]])

但是这使得优化说“问题不可行”并给出了一些像这样的无意义输出:

有什么想法吗?

python optimization linear-programming pulp
© www.soinside.com 2019 - 2024. All rights reserved.