Нелинейное / линейное программирование в Python - PullRequest
0 голосов
/ 29 мая 2018

У меня есть оптимизация, которая выглядит так:

Maximize (x1*a1 + x2*a2+...+xn * an) 

such that :
  any j,  (xj*aj)/sum(all xi*ai) <= 0.35 
  any two j, (xj*aj)/sum(all xi*ai) >= 0.15
  any three j, (xj*aj)/sum(all xi*ai) >= 0.07 
  any j  1<= aj <= 100 and aj is an integer. 

Я попытался реализовать то же самое с помощью Scipy.optimize.Тем не менее, я не уверен, что используемый метод является правильным, поскольку SLSQP не дает решения для любого ввода.Я пытался использовать как Сципи, так и целлюлозу для решения одного и того же с различными формулировками ограничений.Однако ни один из них не работает.Я поделился кодом Scipy ниже.Я не уверен, позволяет ли scipy / pulp ifelse ограничения или принимать ограничения в цикле.

share = 
[1595798.061003,1595798.061003,1595798.061003,1595798.061003,
6335021.83000001,6335021.83000001,6335021.83000001,
6335021.83000001,42842994.4958]

def objective(factors):
    mult = []
    for i in range(len(share)):
       mult.append(share[i]*factors[i])

return -sum(mult)

def constraint1(factors):
    #n=len(factors)
    sum_w = 0
    for i in range(len(share)):
       sum_w= sum_w+(share[i]*factors[i])
    sum_f =0 
    for j in range(len(share)):
        print((share[j]*factors[j])/sum_w)
        if(((share[j]*factors[j])/sum_w) -0.35) <= 0 :
            sum_f = sum_f + 0
        else:
            sum_f = sum_f + 1
return sum_f 

def constraint2(factors):
    sum_w = 0
    for i in range(len(share)):
        sum_w= sum_w+(share[i]*factors[i])
    sum_f2 =0 
    for j in range(len(share)):
        if(((share[j]*factors[j])*100/sum_w) - 0.15) >= 0 :
            sum_f2 = sum_f2 + 1
        else:
            sum_f2 = sum_f2 + 0
return sum_f2 - 2

def constraint3(factors):
    sum_w = 0
    for i in range(len(share)):
        sum_w= sum_w+(share[i]*factors[i])
    sum_f3 =0 
    for j in range(len(share)):
       if(((share[j]*factors[j])*100/sum_w) - 0.07) >= 0 :
           sum_f3 = sum_f3 + 1
       else:
           sum_f3 = sum_f3 + 0
return sum_f3 - 3 

bounds = []
share0=[]

for i in range(len(share)):
    bounds.append((1,100))
    share0.append(100)

cons1={'type': 'eq','fun' : constraint1}
cons2={'type': 'ineq','fun' : constraint2}
cons3={'type': 'ineq','fun' : constraint3} 

cons=[cons1]
sol=minimize(objective,share0,method='SLSQP',bounds=bounds,constraints=cons) 

Вывод, который я получаю, показывает:

fun: 7387762651.568393
jac: array([ -1595776.,  -1595776.,  -1595776.,  -1595776.,  -6335040.,
    -6335040.,  -6335040.,  -6335040., -42843008.])
message: 'Singular matrix C in LSQ subproblem'
nfev: 11
nit: 1
njev: 1
status: 6
success: False
x: array([ 100. , 100. , 100. , 100. , 100., 100., 100., 100., 100. ])

Какой метод я должен использовать здесь?

1 Ответ

0 голосов
/ 29 мая 2018

PySCIPOpt должен хорошо справляться с этими ограничениями.Он более надежен, чем SciPy, особенно если учесть, что вы имеете дело с целочисленными переменными и некоторыми нелинейностями, которые вы можете напрямую моделировать, как вы предлагали.

...