Python.CVXPY学习指南一

来源:互联网 发布:知乎有趣的话题 编辑:程序博客网 时间:2024/06/07 13:58

前言

cvxpy是解决凸优化问题的,在使用之前要确保目标函数是一个凸优化问题(包括其中的变量范围设置,参数设置等)

CVXPY是什么?

CVXPY是一种可以内置于Python中的模型编程语言,解决凸优化问题。它可以自动转化问题为标准形式,调用解法器,解包结果集

如下代码是使用CVXPY解决一个简单的优化问题:

from cvxpy import *# Create two scalar optimization variables.# 在CVXPY中变量有标量(只有数值大小),向量,矩阵。# 在CVXPY中有常量(见下文的Parameter)x = Variable() //定义变量x,定义变量y。两个都是标量y = Variable()# Create two constraints.//定义两个约束式constraints = [x + y == 1,              x - y >= 1]//优化的目标函数obj = Minimize(square(x - y))//把目标函数与约束传进Problem函数中prob = Problem(obj, constraints)prob.solve()  # Returns the optimal value.print "status:", prob.statusprint "optimal value", prob.value //最优值print "optimal var", x.value, y.value //x与y的解status: optimaloptimal value 0.999999999761optimal var 1.00000000001 -1.19961841702e-11//状态域被赋予'optimal',说明这个问题被成功解决。//最优值是针对所有满足约束条件的变量x,y中目标函数的最小值//prob.solve()返回最优值,同时更新prob.status,prob.value,和所有变量的值。

改变已经创建的问题

Problems是不可改变的,意味着在问题被创建之后它不可被改变。为了改变已有问题的目标或者约束,应该创建一个新的问题

# Replace the objective.//不同的目标函数,相同的约束prob2 = cvx.Problem(cvx.Maximize(x + y), prob.constraints)print("optimal value", prob2.solve())# Replace the constraint (x + y == 1).//不同的约束,相同的目标函数constraints = [x + y <= 3] + prob.constraints[1:] //注意:此处是列表相加,prob.constraints[1:]取prob的约束集中//从第二个开始的所有约束。prob2 = cvx.Problem(prob.objective, constraints)print("optimal value", prob2.solve())optimal value 1.0optimal value 3.00000000006

不可行问题与无边界问题

如果一个问题是不可行问题,这个prob.status将会被设置为’infeasible’,如果问题是无边界的,prob.status=unbounded,变量的值域将不会被更新。

import cvxpy as cvxx = cvx.Variable()//一个不可行问题# An infeasible problem.prob = cvx.Problem(cvx.Minimize(x), [x >= 1, x <= 0])prob.solve()print("status:", prob.status)print("optimal value", prob.value)// 无边界问题# An unbounded problem.prob = cvx.Problem(cvx.Minimize(x))prob.solve()print("status:", prob.status)print("optimal value", prob.value)status: infeasibleoptimal value infstatus: unboundedoptimal value -inf

CVXPY的问题状态即prob.status

cvxpy的prob.status可以有如下状态值:
OPTIMAL: 问题被成功解决
INFEASIBLE:问题无解
UNBOUNDED:无边界
OPTIMAL_INACCURATE:解不精确
INFEASIBLE_INACCURATE:
UNBOUNDED_INACCURATE:
If the solver completely fails to solve the problem, CVXPY throws a SolverError exception. If this happens you should try using other solvers. See the discussion of Choosing a solver for details.如果CVXPY求解器求解完全失败,CVXPY将会抛出一个SolverError异常,如果这发生,你应该使用其他求解器cvxpy求解器

# Solving a problem with different solvers.x = cvx.Variable(2)obj = cvx.Minimize(x[0] + cvx.norm(x, 1))constraints = [x >= 2]prob = cvx.Problem(obj, constraints)# Solve with ECOS.prob.solve(solver=cvx.ECOS)print("optimal value with ECOS:", prob.value)# Solve with ECOS_BB.prob.solve(solver=cvx.ECOS_BB)print("optimal value with ECOS_BB:", prob.value)# Solve with CVXOPT.prob.solve(solver=cvx.CVXOPT)print("optimal value with CVXOPT:", prob.value)# Solve with SCS.prob.solve(solver=cvx.SCS)print("optimal value with SCS:", prob.value)# Solve with GLPK.prob.solve(solver=cvx.GLPK)print("optimal value with GLPK:", prob.value)# Solve with GLPK_MI.prob.solve(solver=cvx.GLPK_MI)print("optimal value with GLPK_MI:", prob.value)# Solve with GUROBI.prob.solve(solver=cvx.GUROBI)print("optimal value with GUROBI:", prob.value)# Solve with MOSEK.prob.solve(solver=cvx.MOSEK)print("optimal value with MOSEK:", prob.value)# Solve with Elemental.prob.solve(solver=cvx.ELEMENTAL)print("optimal value with Elemental:", prob.value)# Solve with CBC.prob.solve(solver=cvx.CBC)print("optimal value with CBC:", prob.value)optimal value with ECOS: 5.99999999551optimal value with ECOS_BB: 5.99999999551optimal value with CVXOPT: 6.00000000512optimal value with SCS: 6.00046055789optimal value with GLPK: 6.0optimal value with GLPK_MI: 6.0optimal value with GUROBI: 6.0optimal value with MOSEK: 6.0optimal value with Elemental: 6.0000044085242727optimal value with CBC: 6.0//Use the installed_solvers utility function to get a list of the solvers your installation of CVXPY //supports.print installed_solvers()['CBC', 'CVXOPT', 'MOSEK', 'GLPK', 'GLPK_MI', 'ECOS_BB', 'ECOS', 'SCS'

向量和矩阵

Variables变量可以是标量、向量、矩阵,意味着它可以是0,1,2维

#A scalar variable.a = cvx.Variable()# Vector variable with shape (5,).x = cvx.Variable(5) 列向量,5维# Matrix variable with shape (5, 1).x = cvx.Variable((5, 1))# Matrix variable with shape (4, 7).A = cvx.Variable((4, 7))

你可以使用python本身的数值库来构造矩阵与向量常数,For instance, if x is a CVXPY Variable in the expression A*x + b, A and b could be Numpy ndarrays, SciPy sparse matrices, etc. A and b could even be different types.
Currently the following types may be used as constants:
NumPy ndarrays
NumPy matrices
SciPy sparse matrices
看如下例子:

// Solves a bounded least-squares problem.import cvxpy as cvximport numpy// Problem data.m = 10n = 5numpy.random.seed(1)A = numpy.random.randn(m, n)矩阵Ab = numpy.random.randn(m)向量b//变量xx是一个向量x = cvx.Variable(n)objective = cvx.Minimize(cvx.sum_squares(A*x - b))constraints = [0 <= x, x <= 1]prob = cvx.Problem(objective, constraints)print("Optimal value", prob.solve())print("Optimal var")print(x.value) # A numpy ndarray.  Optimal value 4.14133859146  Optimal var  [ -5.11480673e-21   6.30625742e-21   1.34643668e-01   1.24976681e-01-4.79039542e-21]

约束

正如上述代码所写,你能够使用==,<=和>=去构造约束条件。无论是否是标量、向量以及矩阵,约束是元素性质的,For example, the constraints 0 <= x and x <= 1 mean that every entry of x is between 0 and 1.
你不能使用>与<构造不等式

参数Parameters

Parameters are symbolic representations of constants. The purpose of parameters is to change the value of a constant in a problem without reconstructing the entire problem.参数是常量的符号表示,参数存在的目的是:不用重新构造整个问题而改变一个问题常量的值。
参数可以是向量或者是矩阵,就像变量一样。当你创建一个参数时,可以指明参数的属性,例如参数的正负,参数的对称性等,Parameters can be assigned a constant value any time after they are created.

# Positive scalar parameter.m = cvx.Parameter(nonneg=True)# Column vector parameter with unknown sign (by default).c = cvx.Parameter(5)# Matrix parameter with negative entries.G = cvx.Parameter((4, 7), nonpos=True)# Assigns a constant value to G.G.value = -numpy.ones((4, 7))You can initialize a parameter with a value. The following code segments are equivalent:# Create parameter, then assign value.rho = cvx.Parameter(nonneg=True)rho.value = 2# Initialize parameter with a value.rho = cvx.Parameter(nonneg=True, value=2)
  //实例代码:Computing trade-off curves is a common use of parameters. The example below computes a trade-off curve for a LASSO problem.import cvxpy as cvximport numpyimport matplotlib.pyplot as plt# Problem data.n = 15m = 10numpy.random.seed(1)A = numpy.random.randn(n, m)b = numpy.random.randn(n)# gamma must be nonnegative due to DCP rules.gamma = cvx.Parameter(nonneg=True)# Construct the problem.x = cvx.Variable(m)error = cvx.sum_squares(A*x - b)obj = cvx.Minimize(error + gamma*cvx.norm(x, 1))prob = cvx.Problem(obj)sq_penalty = []l1_penalty = []x_values = []gamma_vals = numpy.logspace(-4, 6)for val in gamma_vals:    gamma.value = val    prob.solve()    # Use expr.value to get the numerical value of    # an expression in the problem.    sq_penalty.append(error.value)    l1_penalty.append(cvx.norm(x, 1).value)    x_values.append(x.value)plt.rc('text', usetex=True)plt.rc('font', family='serif')plt.figure(figsize=(6,10))# Plot trade-off curve.plt.subplot(211)plt.plot(l1_penalty, sq_penalty)plt.xlabel(r'\|x\|_1', fontsize=16)plt.ylabel(r'\|Ax-b\|^2', fontsize=16)plt.title('Trade-Off Curve for LASSO', fontsize=16)# Plot entries of x vs. gamma.plt.subplot(212)for i in range(m):    plt.plot(gamma_vals, [xi[i] for xi in x_values])plt.xlabel(r'\gamma', fontsize=16)plt.ylabel(r'x_{i}', fontsize=16)plt.xscale('log')plt.title(r'\text{Entries of x vs. }\gamma', fontsize=16)plt.tight_layout()plt.show()
原创粉丝点击