【问题标题】:Formulating a constraint on the SUM of the magnitudes of a set of vectors in a constrained optimization在受约束的优化中对一组向量的大小之和制定一个约束
【发布时间】:2017-03-20 23:38:25
【问题描述】:

我正在解决一个几何约束优化问题。优化中的变量是一组向量的 x-y 分量。这些变量的目标函数是二次的。

但是,我需要约束向量子集的大小之和。

具体来说,假设这个子集包含 {v1,v2,...,vn}

我需要解决方案来满足

||v1|| + ||v2|| + .... + ||vn||

如果它只是一个向量,我可以将两边平方以获得二次约束并将问题框定为 QCQP

v1.x * v1.x + v1.y * v1.y

但是,我有多个向量。那么有什么方法可以表达约束,以便我可以应用比一般非线性约束优化更具体的技术?或者考虑到我的目标函数可以通过分析最小化,那么解决问题是否有意义

  1. 忽略约束并获得目标函数的最优值 x*
  2. 将 x* 以数值方式投影到约束流形上以获得满足约束的最终解?

【问题讨论】:

    标签: optimization vector geometry constraints mathematical-optimization


    【解决方案1】:

    不确定您的优化问题中还有什么,但单独约束规范的任务是非线性的,但可以有效解决问题。

    使用外部库,您可以像这样对其进行原型设计。这里使用cvxpy (python)。

    有许多类似的库遵循相同的想法,例如:cvxopt (python)、picos (python)、yalmip (matlab)、convex.jl (julia)。官方的求解器 API 通常更底层,还有更多工作要做。中间还有 JuMP (julia)。

    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]])
    

    以上是自动转换的,所以SOCP-form 可以由商业求解器或开源求解器(如 ECOS 和 SCS)求解。

    这个转换也向我们证明,这个问题是凸的(通过构造)!该方法称为Disciplined Convex Programming 。

    根据您选择的库/软件,您必须手动进行此转换。当您引入一些辅助变量来收集向量的规范时,这应该不难。在 Gurobi 中,您只需要使用基本的 SOCP-constraint docs。

    备注: ||v1|| + ||v2|| + .... + ||vn|| <=。其他一切都需要诡计(epsilon-values...)

    编辑:

    这是一个纯粹的 Gurobi 方法,它可以让您了解如何使用更多支持与 Gurobi API 类似功能的低级库来实现这一点(我正在考虑 Mosek 和 CPLEX,但对 API 了解不多;我认为 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]]
    

    【讨论】:

    • 啊,好吧,我希望它可能是 SOCP。非常感谢这些例子!我对 gurobi 很熟悉,所以这很完美。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    • 2018-05-03
    相关资源
    最近更新 更多