Когда я использую 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'