оптимизация не учитывает ограничения - PullRequest
0 голосов
/ 08 апреля 2019

У меня есть проблема оптимизации, и я решаю ее с помощью scipy и модуля минимизации. Я использую SLSQP в качестве метода, потому что он единственный, который подходит для моей проблемы. Функция для оптимизации - это функция стоимости с 'x' в виде списка процентов. У меня есть некоторые ограничения, которые необходимо соблюдать:

  • Сначала сумма процентов должна быть 1 (PercentSum (x)). Это ограничение добавляется как «например» (равно), как вы можете видеть в коде.
  • Второе ограничение касается физического значения, которое должно быть меньше, чем «proberty1Max». Это ограничение добавляется как 'ineq' (неравный). Поэтому, если 'proberty1

Ниже вы можете увидеть модель моей попытки. Проблема в том, что функция «сдерживать». Я получаю решения, в которых сумма «prop» больше, чем «probertyMax».

import numpy as np
from scipy.optimize import minimize

class objects:
     def __init__(self, percentOfInput, min, max, cost, proberty1, proberty2):
         self.percentOfInput = percentOfInput
         self.min = min
         self.max = max
         self.cost = cost
         self.proberty1 = proberty1
         self.proberty2 = proberty2

class data:
    def __init__(self):
        self.objectList = list()
        self.objectList.append(objects(10, 0, 20, 200, 2, 7))
        self.objectList.append(objects(20, 5, 30, 230, 4, 2))
        self.objectList.append(objects(30, 10, 40, 270, 5, 9))
        self.objectList.append(objects(15, 0, 30, 120, 2, 2))
        self.objectList.append(objects(25, 10, 40, 160, 3, 5))
        self.proberty1Max = 1
        self.proberty2Max = 6

D = data()

def optiFunction(x):
    for index, obj in enumerate(D.objectList):
        obj.percentOfInput = x[1]

    costSum = 0
    for obj in D.objectList:
        costSum += obj.cost * obj.percentOfInput

    return costSum

def PercentSum(x):
    y = np.sum(x) -100
    return y

def constraint(x, val):
    for index, obj in enumerate(D.objectList):
        obj.percentOfInput = x[1]
    prop = 0
    if val == 1:
        for obj in D.objectList:
            prop += obj.proberty1 * obj.percentOfInput

        return D.proberty1Max -prop
    else: 
        for obj in D.objectList:
            prop += obj.proberty2 * obj.percentOfInput

        return D.proberty2Max -prop

def checkConstrainOK(cons, x):
    for con in cons:
        y = con['fun'](x)
        if con['type'] == 'eq' and y != 0:
            print("eq constrain not respected y= ", y)
            return False
        elif con['type'] == 'ineq' and y <0:
            print("ineq constrain not respected y= ", y)
            return False
    return True

initialGuess = []
b = []
for obj in D.objectList:
     initialGuess.append(obj.percentOfInput)
     b.append((obj.min, obj.max))
     bnds = tuple(b)

cons = list()
cons.append({'type': 'eq', 'fun': PercentSum})
cons.append({'type': 'ineq', 'fun': lambda x, val=1 :constraint(x, val) })
cons.append({'type': 'ineq', 'fun': lambda x, val=2 :constraint(x, val) })

solution = minimize(optiFunction,initialGuess,method='SLSQP',\
                            bounds=bnds,constraints=cons,options={'eps':0.001,'disp':True})
print('status ' + str(solution.status))
print('message ' + str(solution.message))
checkConstrainOK(cons, solution.x)

Нет способа найти решение, но вывод таков:

Positive directional derivative for linesearch    (Exit mode 8)
        Current function value: 4900.000012746761
        Iterations: 7
        Function evaluations: 21
        Gradient evaluations: 3
status 8
message Positive directional derivative for linesearch

Где моя вина? В этом случае это заканчивается режимом 8, потому что пример очень маленький. С большими данными алгоритм заканчивается в режиме 0. Но я думаю, что он должен заканчиваться намеком на то, что ограничение не может быть выполнено.

Не имеет значения, если proberty1Max установлен в 4 или 1. Но в случае 1, не может быть допустимого решения.

PS: я сильно изменился в этом вопросе ... Теперь код исполняемый.

EDIT: 1. Хорошо, я узнал, что неравное ограничение принимается, если выходной сигнал положительный (> 0). В прошлом я думаю, что <0 также будет принято. Из-за этого функция ограничений теперь немного короче. </p>

  1. А как насчет ограничений? В моем реальном решении я добавляю некоторые ограничения, используя цикл. В этом случае удобно снабдить функцию индексом цикла, а в функции этот индекс используется для выбора элемента массива. В моем примере здесь "val" решает, является ли ограничение для свойства proberty1 или oder2. Что означает ограничение, так это то, какая часть свойства находится в смеси дырок. Итак, я вычисляю свойство, умноженное на процентOfInput. «опора» - это сумма всех предметов.

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

1 Ответ

0 голосов
/ 25 апреля 2019

Как уже упоминалось в комментарии, я думаю, что это проблема: Вводящий в заблуждение вывод из ....

Если вы посмотрите на последние изменения, ограничение не выполняется, но алгоритм говорит: «Положительная производная по направлениям для линейного поиска»

...