1. 程式人生 > >Python.CVXPY學習指南三

Python.CVXPY學習指南三

凸問題的程式設計規則(Disciplined Convex Programming)

前言:DCP(Disciplined convex programming )是一個系統,它從已給的基礎函式庫構造已知曲率的數學表示式。CVXPY使用DCP確保目標函式為凸.這部分解釋了DCP規則以及在CVXPY中的應用。
凸優化問題:凸優化之所以如此重要,是因為凸優化的重要特性,凸優化的任意區域性最優解也是全域性最優解
凸優化問題是形式如下:
這裡寫圖片描述
其中f0,...,fm為凸函式,凸優化問題附加三個條件:
  • 目標函式必須是凸的,
  • 不等式約束是凸的
  • 等式約束hi(x)
    =aTibi
    必須是仿射的。
    一個值得注意的問題是:凸優化問題的可行集是凸的。
    凹最大化問題:
    maximize f0(x)
    s.t.fi(x)0,i=1,...,m
    aTix=bi,i=1,...,p

    如果目標函式f0是凹的而不等式約束函式f1,...,fm是凸的,也成為凸優化問題,這個凹最大化問題可以簡單通過極小化凸目標函式f0得以求解。

1、表示式

在cvxpy中表達式由變數、引數、數值常量(例如Python floats、Numpy matrices)、標準算數運算子(+, -, *, /) 和標準庫函式。
如下是cvxpy表示式的例子:

from cvxpy import *
# Create variables and parameters.
//建立變數與引數
x, y = Variable(), Variable()
a, b = Parameter(), Parameter()

# Examples of CVXPY expressions.
//cvxpy表示式:
3.69 + b/3
x - 4*a
sqrt(x) - min_elemwise(y, x - a)
max_elemwise(2.66 - sqrt(y), square(x + 2*y))

表示式可以是標量、向量或者矩陣。表示式的維度被儲存在expr.size

,如果使用表示式的維度沒有意義,cvxpy將會丟擲異常,例如兩個不同size的矩陣相加。

import numpy

X = Variable(5, 4)
A = numpy.ones((3, 5))

# Use expr.size to get the dimensions.
print "dimensions of X:", X.size
print "dimensions of sum_entries(X):", sum_entries(X).size
print "dimensions of A*X:", (A*X).size

# ValueError raised for invalid dimensions.
try:
    A + X
except ValueError, e:
    print e
dimensions of X: (5, 4)
dimensions of sum_entries(X): (1, 1)
dimensions of A*X: (3, 4)
Incompatible dimensions (3, 5) (5, 4)

CVXPY uses DCP analysis to determine the sign and curvature of each expression.
CVXPY使用DCP分析來求每個表示式的正負號與曲率

2、正負號Sign

每一個表示式或者子表示式被標記為非負、非正、零或者未知。複合表示式的正負號可以從它的子表示式的正負號求出。
例如,expr1*expr2的正負號:

  • Zero if either expression has sign zero.只要expr1或者expr2一個為0,則表示式為0
  • Positive if expr1 and expr2 have the same (known) sign.
  • Negative if expr1 and expr2 have opposite (known) signs.
  • Unknown if either expression has unknown sign.

    給一個表示式符號總是正確的,但是當一個表示式能通過更加複雜的分析標記符號時,DCP可能標記一個表示式為unknown。
    例如x*x符號為正,但是x被標記為unknown。
    cvxpy根據常量的值決定它的符號,對於標量常量,它的符號是容易求的。如果向量或者矩陣的每一項都是正(負),則向量或者矩陣常數被標記為正(負)。如果向量或矩陣的每一項有正有負,則向量或者矩陣被標記為unknown sign.

The sign of an expression is stored as expr.sign:
x = Variable()
a = Parameter(sign="negative")
c = numpy.array([1, -1])
print "sign of x:", x.sign
print "sign of a:", a.sign
print "sign of square(x):", square(x).sign
print "sign of c*a:", (c*a).sign
sign of x: UNKNOWN
sign of a: NEGATIVE
sign of square(x): POSITIVE
sign of c*a: UNKNOWN

3、曲率Curvature

每個表示式或子表示式被標記為下列曲率(根據它們的變數):
這裡寫圖片描述使用如下的曲率規則。正如符號分析,結論總是正確的。但是當一個表示式是凸的或者凹的時,一個簡單的分析能標記表示式是unknown。注意常量標記為affine,任何仿函式能標記為凸的或者凹的。

4、DCP problems

一個問題能夠由目標函式和一系列約束構造。如果問題遵從DCP規則,這個問題將是凸的,能夠被cvxpy解決。DCP規則要求目標函式有以下兩種形式:

  • Minimize(convex)
  • Maximize(concave)
    在DCP規則下的有效約束為:
  • affine == affine
  • convex <= concave
  • concave >= convex
    你能呼叫object.is_dcp()來檢查一個問題、約束、目標函式是否滿足DCP規則。
//Here are some examples of DCP and non-DCP problems:
x = Variable()
y = Variable()

# DCP problems.
prob1 = Problem(Minimize(square(x - y)), [x + y >= 0])
prob2 = Problem(Maximize(sqrt(x - y)),
                [2*x - 3 == y,
                 square(x) <= 2])

print "prob1 is DCP:", prob1.is_dcp()
print "prob2 is DCP:", prob2.is_dcp()

# Non-DCP problems.

# A non-DCP objective.
prob3 = Problem(Maximize(square(x)))

print "prob3 is DCP:", prob3.is_dcp()
print "Maximize(square(x)) is DCP:", Maximize(square(x)).is_dcp()

# A non-DCP constraint.
prob4 = Problem(Minimize(square(x)), [sqrt(x) <= 2])

print "prob4 is DCP:", prob4.is_dcp()
print "sqrt(x) <= 2 is DCP:", (sqrt(x) <= 2).is_dcp()
prob1 is DCP: True
prob2 is DCP: True
prob3 is DCP: False
Maximize(square(x)) is DCP: False
prob4 is DCP: False
sqrt(x) <= 2 is DCP: False

CVXPY will raise an exception if you call problem.solve() on a non-DCP problem.

# A non-DCP problem.
prob = Problem(Minimize(sqrt(x)))

try:
    prob.solve()
except Exception as e:
    print e
Problem does not follow DCP rules.