如何限制您的问题以允许自定义 "cool-off period"?
How to constrict your problem to allow a custom-defined "cool-off period"?
我正在使用 CVXPY 和 CVXOPT 来解决一个问题,使我们能够以最便宜的方式控制 运行 电机。
我们有现有的约束,包括需要维护的成本、数量和级别(所有这些都有效,只是为了进一步定义手头的问题)。我们使用它来最小化成本并提供优化方法。
最近,我们希望添加一个允许冷静期的新约束。我们可以设置。因此,如果选择值为 1,那么接下来的两个周期应该为 0(如果这有意义的话)。本质上,如果泵运行了一段时间,它应该关闭以便接下来的两个时间冷却。
请参阅下面的当前正在使用的功能。目前,还没有实施冷却约束,并希望在如何最好地实施这种解决方案的正确方向上得到推动。
def optimiser(self, cost_, volume_,v_min,flow_,min_level,max_level,initial_level,period_lengths,out_flow_, errors) :
"""
This function optimizes the regime possible combinations using convex optimization. We assign and define the problem and uses `GLPK_MI` to solve our problem.
Parameters
----------
cost_
Numpy Array
volume_
Numpy Array
v_min
Float -> minimum volume
flow_
Numpy Array
min_level
Float -> minimum level
max_level
Float -> maximum level
initial_level
Float -> initial level
period_lengths
Integer -> number of period lengths
out_flow_
Numpy Array
errors
Exceptions -> error handling
Returns
----------
selection
Solved problem with the best possible combination for pumping regime.
"""
FACTOR = 0.001*1800*self.RESERVOIR_VOLUME
input_flow_matrix=np.zeros((max(period_lengths),len(period_lengths)))
for i,l in enumerate(period_lengths):
input_flow_matrix[:l,i]=1
selection = cp.Variable(shape=cost_.shape,boolean=True)
assignment_constraint = cp.sum(selection,axis=1) == 1
input_flow_= cp.sum(cp.multiply(flow_,selection),axis=1)
input_flow_vector=cp.vec(cp.multiply(input_flow_matrix,np.ones((max(period_lengths), 1)) @ cp.reshape(input_flow_,(1,len(period_lengths)))))
res_flow= (input_flow_vector-cp.vec(out_flow_))
res_level=cp.cumsum(res_flow) * FACTOR + initial_level
volume_= cp.sum(cp.multiply(volume_,selection))
volume_constraint = volume_ >= v_min
min_level_constraint = res_level >= min_level
max_level_constraint = res_level <= max_level
if errors is LevelTooLowError:
constraints = [assignment_constraint, max_level_constraint, volume_constraint]
elif errors is LevelTooHighError:
constraints = [assignment_constraint, min_level_constraint, volume_constraint]
elif errors is MaxVolumeExceededError:
constraints = [assignment_constraint, min_level_constraint, volume_constraint]
else:
constraints = [assignment_constraint, max_level_constraint, min_level_constraint, volume_constraint]
cost_ = cp.sum(cp.multiply(cost_,selection))
assign_prob = cp.Problem(cp.Minimize(cost_),constraints)
assign_prob.solve(solver=cp.GLPK_MI, verbose=False)
return selection
我们使用的数据样本
这是我们的cost_
数组
[[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 1.35]
[0. 1.35]
[0. 1.35]
[0. 1.8 ]
[0. 1.2 ]]
这是我们的 volume_
数组
[[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 51300.]
[ 0. 51300.]
[ 0. 51300.]
[ 0. 68400.]
[ 0. 51300.]]
我希望我的问题已得到明确定义,以便任何人都能理解我现在想做什么。如果还有什么需要,我可以很乐意提供给大家。
提前致谢。
发电中有时会用到类似这样的东西。发电机可能必须先冷却,然后才能再次打开。
假设我们有一个 二进制变量 x[t]
指示发电机是否在时间段 t 即
x[t] = 1 if machine is "on"
0 "off"
那么我们要要求:
if x[t-1]=1 and x[t]=0 => x[t+1] = 0
这读作:如果在 t 关闭,则在 t+1 也保持关闭。这可以写成线性约束:
x[t+1] <= x[t] - x[t-1] + 1 for all periods t
如果我们读到“如果泵运行一段时间,它应该关闭以便接下来的两个时间冷却”,这表明另外,最大正常运行时间是1,那么我们可以简单的写:
x[t-1] + x[t] + x[t+1] <= 1 for all t
这将允许像 [0,0,0],[1,0,0],[0,1,0],[0,0,1]
这样的模式,但禁止像 [1,1,1],[0,1,1],[1,1,0],[1,0,1]
.
这样的模式
我正在使用 CVXPY 和 CVXOPT 来解决一个问题,使我们能够以最便宜的方式控制 运行 电机。
我们有现有的约束,包括需要维护的成本、数量和级别(所有这些都有效,只是为了进一步定义手头的问题)。我们使用它来最小化成本并提供优化方法。
最近,我们希望添加一个允许冷静期的新约束。我们可以设置。因此,如果选择值为 1,那么接下来的两个周期应该为 0(如果这有意义的话)。本质上,如果泵运行了一段时间,它应该关闭以便接下来的两个时间冷却。
请参阅下面的当前正在使用的功能。目前,还没有实施冷却约束,并希望在如何最好地实施这种解决方案的正确方向上得到推动。
def optimiser(self, cost_, volume_,v_min,flow_,min_level,max_level,initial_level,period_lengths,out_flow_, errors) :
"""
This function optimizes the regime possible combinations using convex optimization. We assign and define the problem and uses `GLPK_MI` to solve our problem.
Parameters
----------
cost_
Numpy Array
volume_
Numpy Array
v_min
Float -> minimum volume
flow_
Numpy Array
min_level
Float -> minimum level
max_level
Float -> maximum level
initial_level
Float -> initial level
period_lengths
Integer -> number of period lengths
out_flow_
Numpy Array
errors
Exceptions -> error handling
Returns
----------
selection
Solved problem with the best possible combination for pumping regime.
"""
FACTOR = 0.001*1800*self.RESERVOIR_VOLUME
input_flow_matrix=np.zeros((max(period_lengths),len(period_lengths)))
for i,l in enumerate(period_lengths):
input_flow_matrix[:l,i]=1
selection = cp.Variable(shape=cost_.shape,boolean=True)
assignment_constraint = cp.sum(selection,axis=1) == 1
input_flow_= cp.sum(cp.multiply(flow_,selection),axis=1)
input_flow_vector=cp.vec(cp.multiply(input_flow_matrix,np.ones((max(period_lengths), 1)) @ cp.reshape(input_flow_,(1,len(period_lengths)))))
res_flow= (input_flow_vector-cp.vec(out_flow_))
res_level=cp.cumsum(res_flow) * FACTOR + initial_level
volume_= cp.sum(cp.multiply(volume_,selection))
volume_constraint = volume_ >= v_min
min_level_constraint = res_level >= min_level
max_level_constraint = res_level <= max_level
if errors is LevelTooLowError:
constraints = [assignment_constraint, max_level_constraint, volume_constraint]
elif errors is LevelTooHighError:
constraints = [assignment_constraint, min_level_constraint, volume_constraint]
elif errors is MaxVolumeExceededError:
constraints = [assignment_constraint, min_level_constraint, volume_constraint]
else:
constraints = [assignment_constraint, max_level_constraint, min_level_constraint, volume_constraint]
cost_ = cp.sum(cp.multiply(cost_,selection))
assign_prob = cp.Problem(cp.Minimize(cost_),constraints)
assign_prob.solve(solver=cp.GLPK_MI, verbose=False)
return selection
我们使用的数据样本
这是我们的cost_
数组
[[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.8 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 0.9 ]
[0. 1.35]
[0. 1.35]
[0. 1.35]
[0. 1.8 ]
[0. 1.2 ]]
这是我们的 volume_
数组
[[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 34200.]
[ 0. 51300.]
[ 0. 51300.]
[ 0. 51300.]
[ 0. 68400.]
[ 0. 51300.]]
我希望我的问题已得到明确定义,以便任何人都能理解我现在想做什么。如果还有什么需要,我可以很乐意提供给大家。
提前致谢。
发电中有时会用到类似这样的东西。发电机可能必须先冷却,然后才能再次打开。
假设我们有一个 二进制变量 x[t]
指示发电机是否在时间段 t 即
x[t] = 1 if machine is "on"
0 "off"
那么我们要要求:
if x[t-1]=1 and x[t]=0 => x[t+1] = 0
这读作:如果在 t 关闭,则在 t+1 也保持关闭。这可以写成线性约束:
x[t+1] <= x[t] - x[t-1] + 1 for all periods t
如果我们读到“如果泵运行一段时间,它应该关闭以便接下来的两个时间冷却”,这表明另外,最大正常运行时间是1,那么我们可以简单的写:
x[t-1] + x[t] + x[t+1] <= 1 for all t
这将允许像 [0,0,0],[1,0,0],[0,1,0],[0,0,1]
这样的模式,但禁止像 [1,1,1],[0,1,1],[1,1,0],[1,0,1]
.