我正在解决几何约束优化问题。优化中的变量是一组向量的x-y分量。目标函数在这些变量中是二次的。
但是,我需要约束矢量子集的幅度的和。
具体来说,假设该子集由{v1,v2,...,vn}
组成我需要解决方案来满足
|| || V1 + || v2 || + .... + || vn || < →
如果它只是一个矢量,我可以将两边平方以获得二次约束并将问题框架为QCQP
v1.x * v1.x + v1.y * v1.y< L *→
但是,我有多个向量。那么有没有办法以这样的方式表达约束,即我可以应用比一般非线性约束优化更具体的技术?或者考虑到我的目标函数可以通过分析最小化,通过
解决问题是否有意义答案 0 :(得分:1)
不确定你的优化问题还有什么,但是限制你的规范的任务是非线性的但是凸的,这样可以有效地解决问题。
使用外部库可以像这样对其进行原型设计。这里使用https://code.msdn.microsoft.com/XmlLite-XML-node-writer-4472022a/sourcecode?fileId=51211&pathId=2033671260(python)。
有许多类似的库遵循相同的想法,如:cvxopt(python),picos(python),yalmip(matlab),convex.jl(julia)。官方求解器-API通常更低级别,还有更多工作要做。在中间还有JuMP(朱莉娅)。
from cvxpy import *
L = 10.0
V = Variable(3,5) # 3 vectors
constraints = []
constraints.append(sum_entries(norm(V, axis=1)) <= L)
objective = Maximize(sum_entries(V))
prob = Problem(objective, constraints)
prob.solve()
print("status:", prob.status)
print("optimal value", prob.value)
print("optimal var", V.value)
print('constr: ', sum_entries(norm(V, axis=1).value))
输出:
status: optimal
optimal value 22.36067971461066
optimal var [[ 1.49071198 1.49071198 1.49071198 1.49071198 1.49071198]
[ 1.49071198 1.49071198 1.49071198 1.49071198 1.49071198]
[ 1.49071198 1.49071198 1.49071198 1.49071198 1.49071198]]
constr: sum_entries([[ 3.33333332]
[ 3.33333332]
[ 3.33333332]])
以上内容自动转换为cvxpy,可以通过商业解算器或开源解算器(如ECOS和SCS)解决。
这种转换也向我们证明,这个问题是凸的(通过构造)!该方法称为SOCP-form。
根据您的库/软件选择,您必须手动执行此转换。当你引入一些辅助变量来收集你的向量规范时,应该不是那么难。在Gurobi中,您只需要使用基本的 SOCP约束 Disciplined Convex Programming 。
备注: || v1 || + || v2 || + .... + || vn || &LT; L是可怕的,因为数值优化通常只关心<=
。其他一切都需要诡计(epsilon-values ...)
修改强>
这是一个纯粹的Gurobi方法,它可以让你对如何通过支持类似Gurobi API的类似功能的更低级库实现这一点(我在考虑Mosek和CPLEX而不知道那些API很多; i认为Mosek是完全不同的。)
from gurobipy import *
import numpy as np
L = 10.0
# Model
m = Model("test")
# Vars
v = np.empty((3,5), dtype=object)
for i in range(3):
for j in range(5):
v[i, j] = m.addVar() # by default >= 0; it's just an example
norm_v = np.empty(3, dtype=object)
for i in range(3):
norm_v[i] = m.addVar() # aux-vars to collect norms
m.update() # make vars usable for posting constraints
# Constraints
for i in range(3):
m.addQConstr(np.dot(v[i, :], v[i, :]),
GRB.LESS_EQUAL, norm_v[i] * norm_v[i]) # this is the SOCP-constraint for our norm
m.addConstr(np.sum(norm_v) <= L) # gurobi-devs would propose using quicksum
# Objective
m.setObjective(np.sum(v), GRB.MAXIMIZE)
# Solve
m.optimize()
def get_val(x):
return x.X
get_val_func = np.vectorize(get_val)
print('optimal var: ', get_val_func(v))
输出:
Optimal objective 2.23606793e+01
optimal var: [[ 1.49071195 1.49071195 1.49071195 1.49071195 1.49071195]
[ 1.49071195 1.49071195 1.49071195 1.49071195 1.49071195]
[ 1.49071195 1.49071195 1.49071195 1.49071195 1.49071195]]