SciPy оптимизировать свести к минимуму находит не минимальный ответ - PullRequest
0 голосов
/ 26 сентября 2018

Когда я использую Scipy минимизировать в примере ниже, он находит неминимальное решение - может кто-нибудь помочь мне изменить это, чтобы найти минимум?

У меня есть четыре ограничения: 1) догадки массива догадок должны быть равны единице, 2) догадки должны быть> 0, и 3) любые догадки из массива начальных догадок, превышающие порог, должны быть установлены равными порогу и поддерживаться постоянными.
Редактировать: 4-е ограничение - ни одно предположение не может превышать пороговое значение.

Я не использовал ограничения для трех последних ограничений, которые у меня есть.Для ограничения 2 я использовал границы.Для ограничения 3 я сделал это в методе executeMinimize до вызова метода минимизации scipy.

from scipy.optimize import minimize
import numpy as np
from numpy import array

def objective(initialGuesses, threshold):
    overThreshold = initialGuesses[np.where((threshold < initialGuesses[:]))]
    underThreshold = initialGuesses[np.where((threshold >= initialGuesses[:]))]

    overThreshold[:] = threshold
    sumUnderThreshold = np.sum(underThreshold)
    oppositeSumOverTreshold = 1 - np.sum(overThreshold)

    transformedGuess = underThreshold / sumUnderThreshold * oppositeSumOverTreshold

    thresholdedResults = np.concatenate((overThreshold, transformedGuess))

    squaredError = np.square(thresholdedResults - initialGuesses) / initialGuesses

    return np.sum(squaredError)


def performMinimizeSo(initialGuesses, threshold):
    overThreshold = initialGuesses[np.where((threshold < initialGuesses[:]))]
    overThreshold[:] = threshold
    underThreshold = initialGuesses[np.where((threshold >= initialGuesses[:]))]

    # Says one minus the sum of all variables minus the sum of weights over the threshold must be zero
    cons = ({'type': 'eq', 'fun': lambda x: 1 - sum(x) - sum(overThreshold)})

    minimum = minimize(objective, underThreshold, args=(threshold), method='SLSQP',
                       constraints=cons,
                       bounds=[(0, None) for i in range(len(underThreshold))],
                       )

    allGuesses = np.append(overThreshold, minimum.x)

    return allGuesses


def testCaseForSo():
    initialGuesses = array([
        [0.1],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.05],
        [0.025],
        [0.025]])

    threshold = .09
    output = (performMinimizeSo(initialGuesses, threshold))
    print(output)

testCaseForSo()

Минимальный ответ, найденный Excel, таков:

0.09
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.050555556
0.025277778
0.025277778

Scipy минимизирует мыслиэто ответ, близкий, но не правильный минимум:

0.09
0.050526315
0.050526315
0.050526315
0.050526315
0.050526315
0.050526315
0.050526315
0.050526315
0.050526315
0.050526315
0.050526317
0.050526317
0.050526317
0.050526317
0.050526317
0.050526317
0.050526317
0.025526317
0.025526317

Вот как выглядят атрибуты вывода после запуска scipy.minimize (как вы можете видеть, scipy считает, что нашел минимумхотя мы знаем, что это не так):

minimum.sucess == True
minimum.status == 0
minimum.message == 'Optimization terminated successfully'
...