使用Mosek优化二次型平方根函数遇类型错误求助
问题解决:Mosek实现二次范数最小化
错误1:列表与变量运算不兼容
unsupported operand type(s) for -: 'list' and 'LinearVariable'是因为Python原生列表不能直接和Mosek的LinearVariable对象做算术运算。必须把weights_b这类常量转换为Mosek可识别的表达式对象,而非保留原生列表格式。
错误2:平方根的建模方式
直接在目标函数中写平方根不可行,Mosek需要通过二次锥约束来处理这类凸函数;或者利用单调性简化问题——最小化√y等价于最小化y(当y≥0时),两种方式都能实现原目标。
修正后的完整代码
b = [[1.0,2.0,3.0], [2.0,6.0,8.0], [8.0,1.0,5.0]] weights_b = [0.3, 0.5, 0.2] # 改为一维列表,便于转换为Mosek常量 n_opt = 3 import sys from mosek.fusion import * def main(args): with Model("quadratic_norm_min") as M: # 定义优化变量x,添加非负约束 x = M.variable("x", n_opt, Domain.greaterThan(0.0)) # 定义变量t,用于表示平方根的结果 t = M.variable("t", 1, Domain.greaterThan(0.0)) # 将常量转换为Mosek可识别的格式 w_expr = Expr.const(n_opt, weights_b) B_mat = Matrix.dense(b) # 计算 weights_b - x 的差值 diff = Expr.sub(w_expr, x) # 计算二次型项:(weights_b - x)^T · b · (weights_b - x) quad_form = Expr.dot(diff, Expr.mul(B_mat, diff)) # 添加二次锥约束:t ≥ sqrt(quad_form) # 注意:矩阵b必须是正定/半正定的,否则问题非凸,Mosek无法求解 M.constraint("quad_cone", Expr.vstack(t, diff), Domain.inQCone()) # 目标:最小化t(即最小化原目标的平方根) M.objective("obj", ObjectiveSense.Minimize, t) # 求解问题 M.solve() # 输出结果 x_sol = x.level() t_sol = t.level() print("最优解x:") for i in range(n_opt): print(f"x[{i}] = {x_sol[i]:.6f}") print(f"目标函数值(平方根结果):{t_sol[0]:.6f}") if __name__ == '__main__': main(sys.argv[1:])
关键注意事项
- 矩阵正定性:目标函数中的矩阵
b必须是正定或半正定的,否则二次型不是凸函数,Mosek无法处理这类非凸优化问题。可以通过计算特征值检查b的正定性。 - 简化选项:如果不需要显式得到平方根结果,直接将
quad_form设为目标函数即可——因为平方根是单调递增函数,最小化√y和最小化y的最优解x完全一致。
内容的提问来源于stack exchange,提问作者Happy_otter
相关产品推荐
相关产品推荐

