Минимизируйте несколько параметров, сохраняя при этом одинаковое соотношение между параметрами - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть особая функция, которая вычисляет среднюю стоимость электроэнергии ($ / МВтч) в течение срока службы электростанции.

Пример функции выглядит следующим образом

def calc(a,b,c):
     res = 65*a+74*b+12*c
     return res

Где a b и c являются параметрами затрат, такими как операционные расходы, стоимость строительства и страхование.

Я мог бы варьировать a b и c бесконечным количеством способов, ноЯ хотел бы оставить эти соотношения такими же, как у примера, который у меня есть, с меньшим результатом для средней стоимости электроэнергии.

Например, когда a=1, b=2 и c=3, res = 249.

Однако я хотел бы найти оптимальные значения, которые сохраняют те же исходные отношения, для a b и c, когда res=600

У меня естьЯ пытался найти способ сделать это с помощью scipy.optimize, но с некоторыми трудностями.

Я не уверен, как мне запрограммировать отношения для ограничений.

Большое спасибо.

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Из этого ответа вы можете указать ограничения следующим образом:

cons = [{'type':'eq', 'fun': con1},
        {'type':'eq', 'fun': con2}]

и использовать функцию минимизации следующим образом:

scipy.optimize.minimize(func, x0, constraints=cons)
0 голосов
/ 27 ноября 2018

Мне удалось найти решение, которое помогло моему конкретному варианту использования, хотя было указано, что для этого конкретного примера было более простое решение.

from scipy.optimize import minimize
import numpy as np

a = 1
b = 2
c = 3

def calc(x):
    res = 65*x[0]+74*x[1]+12*x[2]
    return res

cons = [{'type': 'eq', 'fun': lambda x: x[0]/x[1]-a/b},
        {'type': 'eq', 'fun': lambda x: x[1]/x[2]-b/c},
        {'type': 'eq', 'fun': lambda x: calc(x)-600}]

start_pos = np.ones(3)*(1/6.)

print(minimize(calc, x0=start_pos, constraints=cons))

Ограничения сохраняют те же отношенияи установите результат calc равным 600.

0 голосов
/ 27 ноября 2018

Допустим, у вас есть два набора значений (a_old, b_old, c_old) и (a_new, b_new, c_new).Если вы хотите, чтобы их соотношения были одинаковыми (например, a_old: c_old совпадает с a_new: c_new, а c_old: b_old совпадает с c_new: b_new и т. Д.), То это то же самое, что сказать, что существует некотороеконстанта k такая, что a_new = k * a_old, b_new = k * b_old и c_new = k * c_old.

В вашем примере 65 * a_old + 74 * b_old + 12 * c_old = 249. Если вы умножаетеобе стороны этого уравнения на k, вы получите 65 (k * a_old) + 74 (k * b_old) + 12 (k * c_old) = 249 * k.Это то же самое, что '65 (a_new) + 74 (b_new) + 12 (c_new) = 249k '.

Вы хотите, чтобы 249 * k было равно 600. Следовательно, k = 600/249 = примерно2,4096.Затем вы можете использовать это значение k вместе с a_old, b_old, c_old, чтобы найти значения a_new, b_new, c_new.Помните, что новые значения просто в k раз превышают старые значения.

Вот функция, которая возвращает набор масштабированных значений параметров:

def optimize(a,b,c, opt_res):
    res = 65 * a + 74 * b + 12 * c
    k = opt_res/res
    new_vals = [parameter * k for parameter in [a,b,c]]
    return new_vals

print(optimize(1,2,3,600.0))

## output: [2.4096385542168677, 4.819277108433735, 7.2289156626506035]

Примечание. Я использовал «600.0», а не «600»,Это заставляет Python использовать float вместо того, чтобы делать все с усеченными целыми числами.

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