CVXOPT с только ограничениями равенства
Я пытаюсь выполнить следующие упражнения в CVXOPT. Я внес незначительные изменения в код примера здесь, удалив ограничения неравенства и добавив еще несколько ограничений равенства.
from cvxopt import solvers, blas, matrix, spmatrix, spdiag, log, div
solvers.options['show_progress'] = False
import numpy as np
np.random.seed(1)
# minimize p'*log(p)
# subject to
# sum(p) = 1
# sum(p'*a) = target1
# sum(p'*max(a-K,a^2)) = target2
a = np.random.randint(20, 30, size=500)
target1 = 30
target2 = 0.60
K = 26
A = matrix(np.vstack([np.ones(500), a, np.array([max(x-K,x*x) for x in a])]))
b = matrix([1.0, target1, target2])
n = 500
def F(x=None, z=None):
if x is None: return 0, matrix(1.0, (n,1))
if min(x) <= 0: return None
f = x.T*log(x)
grad = 1.0 + log(x)
if z is None: return f, grad.T
H = spdiag(z[0] * x**-1)
return f, grad.T, H
sol = solvers.cp(F, A=A, b=b)
p = sol['x']
Но когда я выполняю следующее:
np.sum(p)
243.52686763225338
Это нарушило первое ограничение оптимизации. Я не могу понять, что здесь происходит. (Обратите внимание, так как я использую случайные числа для генерации переменной a
, ваш np.sum(p)
будет производить разные значения, но вы должны наблюдать такое же нарушение, что и мое.
Даже если я сохраняю ограничения неравенства по исходной ссылке и добавляю два дополнительных ограничения равенства, ограничения равенства нарушаются.
Есть ли какой-либо другой пакет, который я могу надежно использовать в качестве пакета, который поддерживается?
Изменить:
Если нет приемлемого решения, не должно быть сообщения, которое не найдено ни одного приемлемого решения?
Ответы
Ответ 1
Как @tihom прокомментировал проблему, это невозможно. Вы действительно уверены, что это проблема, которую вы хотите решить? Ваше первое ограничение подразумевает:
p1 + p2 + ... + pn = 1
p1*a1 + p2*a2 + ... + an*pn = 30
p1*a1^2 + p2*a2^2 + ... pn*an^2 = 0.6
Последнее ограничение никогда не может выполняться одновременно с первым или вторым с ai >= 20
для всех i
. То есть сумма p1*a1^2 + p2*a2^2 + ... pn*an^2
всегда больше других сумм (обратите внимание, что pi > 0
).
Если вы даете target1 = sum(a/500.)
и target2= sum(a*a/500.)
, существует точка, удовлетворяющая вашим ограничениям, и вы можете найти оптимальное решение.
Обратите внимание, что в последнем ограничении максимум упрощается до max(a - K, a^2) = a^2
, что истинно независимо от a
.
Изменить: если вы проверите решение (например, print sol
), вы получите что-то вроде:
{'status': 'unknown', 'zl': <0x1 matrix, tc='d'>, 'dual slack': 1.0000000000000007, 'relative gap': 0.005911420508296136, 'dual objective': -97.17320604198335, 'snl': <0x1 matrix, tc='d'>, 'gap': 0.9737154924375709, 'primal objective': -164.7176835197311, 'primal slack': 0.9737154924375703, 'znl': <0x1 matrix, tc='d'>, 'primal infeasibility': 0.5114570271204905, 'dual infeasibility': 0.5091221046374248, 'sl': <0x1 matrix, tc='d'>, 'y': <3x1 matrix, tc='d'>, 'x': <500x1 matrix, tc='d'>}
Обратите внимание, что status
равно 'unknown'
, т.е. не найдено допустимого решения. Это находится в документации cvxopt.solvers.cp
: http://cvxopt.org/userguide/solvers.html?highlight=cp#cvxopt.solvers.cp