Я пытаюсь запустить простую модель резервуара для воды, резервуар может быть заполнен насосом (Q> 0) или опорожнен турбиной (Q <0). В 3 часа я хочу максимизировать турбину (минимизировать Q, когда <0) с учетом следующих ограничений: </p>
-Qmax Для каждого из через 3 часа уровень резервуара должен оставаться между Vmin и Vmax, поэтому, учитывая начальный уровень V0, мы имеем следующие ограничения:
V0 + Q[0] - Vmin >= 0
V0 + Q[0] + Q[1] - Vmin >= 0
V0 + Q[0] + Q[1] + Q[2] - Vmin >= 0
Vmax - (V0 + Q[0]) >= 0
Vmax - (V0 + Q[0]+ Q[1]) >= 0
Vmax - (V0 + Q[0]+ Q[1]+ Q[2]) >= 0
здесь под моим кодом:
from scipy.optimize import minimize
# input parameters
V0 = 600.0 # start level of reservoir
Vmin = 500.0 # min level of reservoir
Vmax = 2700.0 # max level of reservoir
Qmax = 800.0 # max pumping level of reservoir
Qmin = -800.0 # max turbining level of reservoir
# bounds
boundsQ0 = (Qmin, Qmax)
bounds = tuple(boundsQ0 for i in range(0, 3))
# initialization
Q0 = np.zeros(3)
for i in range(0, Q0.size):
Q0[i] = -100.0
def objective(Q): # objective function to be min Q, Q negative = turbine, Q postive = pumping
Qtot = 0
for i in range(0, Q.size):
if Q[i] < 0:
Qtot += Q[i]
return Qtot
def constraintVmin0(Q, V0, Vmin):
return Q[0] + V0 - Vmin
def constraintVmin1(Q, V0, Vmin):
return Q[1] + Q[0] + V0 - Vmin
def constraintVmin2(Q, V0, Vmin):
return Q[2] + Q[1] + Q[0] + V0 - Vmin
def constraintVmax0(Q, V0, Vmax):
return Vmax - (Q[0] + V0)
def constraintVmax1(Q, V0, Vmax):
return Vmax - (Q[0] + Q[1] + V0)
def constraintVmax2(Q, V0, Vmax):
return Vmax - (Q[0] + Q[1] + Q[2] + V0)
constraintV0_type_min = {'type': 'ineq', 'fun': constraintVmin0, 'args': (V0, Vmin)}
constraintV1_type_min = {'type': 'ineq', 'fun': constraintVmin1, 'args': (V0, Vmin)}
constraintV2_type_min = {'type': 'ineq', 'fun': constraintVmin2, 'args': (V0, Vmin)}
constraintV0_type_max = {'type': 'ineq', 'fun': constraintVmax0, 'args': (V0, Vmax)}
constraintV1_type_max = {'type': 'ineq', 'fun': constraintVmax1, 'args': (V0, Vmax)}
constraintV2_type_max = {'type': 'ineq', 'fun': constraintVmax2, 'args': (V0, Vmax)}
constraint = ([constraintV0_type_min, constraintV1_type_min, constraintV2_type_min
, constraintV1_type_max, constraintV1_type_max, constraintV2_type_max])
sol = minimize(objective, Q0, method='SLSQP', bounds=bounds, constraints=constraint)
print(sol)
Таким образом, здесь решение возвращает x: array([-33.3, -33.3, -33.3])
при V0 = 600 и Vmin = 500, что в сумме составляет 100 за 3 часа. Но для меня искомое решение было бы больше похоже на x: array([800, -800, -100])
, так что в общей сложности -900.
=> Любая идея, почему scipy не рассматривает здесь переключение между положительным и отрицательным значением для минимизации Qtot?
и дополнительный вопрос, если есть более элегантный способ вычислить все ограниченияV0,1,2 ..
РЕДАКТИРОВАТЬ: хорошо, так что кажется, что выбор начального значения Q0 имеет большое влияние на результаты будут привязаны к каждому знаку Q [i].