scipy.optimize простая модель заполнения водохранилища отсутствует решение - PullRequest
0 голосов
/ 19 марта 2020

Я пытаюсь запустить простую модель резервуара для воды, резервуар может быть заполнен насосом (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].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...