对偶(Duality)理论与Farkas引理是线性规划中非常重要的部分,有着广泛的应用。本文聊一下关于它们的一些理解。文章不重在理论推导,因为任何一本关于优化的书基本都会有单独的章节来阐述相关的证明。

以下先分别介绍Duality理论与Farkas引理,再说说它们的联系。

Duality理论

对偶理论主要由von Neumann, Gale, Kuhn和Tucker提出。对偶不局限于线性规划。借用【1】p215的表达,对于一个一般的优化问题:
min ⁡ f 0 ( x ) s.t. f i ( x ) ≤ 0 , i = 1 , . . . , m h i ( x ) = 0 , i = 1 , . . . p \begin{align*} \min \quad &f_0(x) \\ \text{s.t.} \quad &f_i(x) \leq 0, \quad i=1,...,m \\ &h_i(x) = 0, \quad i=1,...p \end{align*} mins.t.f0(x)fi(x)0,i=1,...,mhi(x)=0,i=1,...p
注意这里并不要求函数为凸函数。为了和后面的对偶问题对应,该问题称为原问题(Primal problem)。

接下来,构造其Lagrangian:
L ( x , λ , υ ) = f 0 ( x ) + ∑ i = 1 m λ i f i ( x ) + ∑ i = 1 p υ i h i ( x ) L(x, \lambda, \upsilon) = f_0(x) + \sum_{i=1}^{m} \lambda_i f_i(x) + \sum_{i=1}^{p} \upsilon_i h_i(x) L(x,λ,υ)=f0(x)+i=1mλifi(x)+i=1pυihi(x)
其中 λ i \lambda_i λi υ i \upsilon_i υi为拉格朗日乘子(Lagrange multiplier,或dual variable),与约束条件一一对应。进一步定义Lagrange dual function为Lagrangian的极小值。
g ( λ , υ ) = inf ⁡ x ∈ D L ( x , λ , υ ) g(\lambda, \upsilon) = \inf_{x \in \mathcal{D}} L(x, \lambda, \upsilon) g(λ,υ)=xDinfL(x,λ,υ)
其中 D \mathcal{D} D为各函数的定义域的交集。

对于任意的 λ ⪰ 0 \lambda \succeq 0 λ0 υ \upsilon υ,有:
g ( λ , υ ) ≤ p ∗ g(\lambda, \upsilon) \leq p^* g(λ,υ)p
其中 p ∗ p^* p为原问题的最优值(即目标函数最小值)。推导可参见【1】p216。直观上也很好理解。因为Lagrangian将原问题的硬性约束变成了可以违反(但需付出一定代价)的软性约束,相当于放松了原问题的约束,那自然可以得到比原问题更优的解。

最大化Langrange dual function的优化问题称为Langrange dual problem:
max ⁡ g ( λ , υ ) s.t. λ ⪰ 0 \begin{align*} \max \quad &g(\lambda, \upsilon) \\ \text{s.t.} \quad &\lambda \succeq 0 \end{align*} maxs.t.g(λ,υ)λ0
它即是原问题的对偶问题。该对偶问题的最优值(即目标函数最大值)为 d ∗ d^* d。前面提到 g ( λ , υ ) ≤ p ∗ g(\lambda, \upsilon) \leq p^* g(λ,υ)p,因此有 d ∗ = sup ⁡ g ( λ , υ ) ≤ p ∗ d^* = \sup g(\lambda, \upsilon) \leq p^* d=supg(λ,υ)p。这称为weak duality。

当上面不等式中的等号成立,即 d ∗ = p ∗ d^* = p^* d=p时,称为strong duality。它的含义是,在对偶问题取得最优值时,其最优的Lagrange multipler会使得违反约束对最小化目标函数没有好处(Lagrange multipler可看作是违反约束所产生的代价)。它们称为duality定理,是对偶理论中最重要的结论之一。

但是,和weak duality不同,strong duality并不总是成立的。只有在一些特定条件下(如Slater’s condition)才成立。

现在我们把目光放到线性规划(LP)上。线性规划有个很好的性质。只要原问题是可行(feasible)的(即约束下取值范围不为空),则strong duality就成立。

根据原问题不同,对偶问题的形式也会不同。因此我们经常会看到不同形式的对偶问题。对于线性规划,原问题和对偶的变换规则可参见【2】p143:

PrimalminimizemaximizeDual
constraints ≥ b i \geq b_i bi ≥ 0 \geq 0 0variables
constraints ≤ b i \leq b_i bi ≤ 0 \leq 0 0variables
constraints = b i = b_i =bifreevariables
variables ≥ 0 \geq 0 0 ≤ c i \leq c_i ciconstraints
variables ≤ 0 \leq 0 0 ≥ c i \geq c_i ciconstraints
variablesfree = c i = c_i =ciconstraints

根据这些规则,我们便可以构造对偶问题。

注意对偶问题的对偶问题即为原问题。原问题最优解与对偶问题最优解之前存在关系:
λ i ∗ f i ( x ∗ ) = 0 , i = 1 , . . . , m \lambda_i^* f_i(x^*) = 0, \quad i = 1, ..., m λifi(x)=0,i=1,...,m
这称为Complementary slackness。它告诉我们,只有当最优值 x ∗ x^* x使不等式约束的等号成立时(即该约束为active时),对应的Lagrange multiplier才不为0。它直觉上的意义是如果一个不等式约束对于最优解不是active的,那去掉它对于目标函数最优值没有影响。因为对于线性规划,如果一个不等式约束对解产生影响,它一定会让其取在边界(即等号成立)上。想象一下,在二维平面上一个不等式约束代表由一条线分隔的半边,那如果最优解 x ∗ x^* x不在这条边界线上,且该约束还对最优解产生了作用,那为什么我们不能把最优解往这条边界线上移呢?一种情况是往边界线上移会使目标函数更大,那说明这个约束没啥用。还有种情况是被其它约束拦住了。那既然被其它约束拦住了,这个约束自然没啥用了。其它情况下我们把最优解往边界线的方向上移是能使目标函数变得更优的。那就与该解是最优的矛盾了。

好了,现在回过头来问一个问题。对偶问题不还是个优化问题么,为毛我们要整个对偶问题呢?毕竟作为一个工科狗,对于数学结论,除了理论推导,还很感兴趣于有啥实际用处。

  • 首先,对偶问题对解原问题有帮助。从前面的原问题与对偶问题的变换规则可以发现,原问题的约束个数对应对偶问题的变量个数,原问题的变量个数对应对偶问题的约束个数。这意味着如果原问题约束比变量多,转成对偶问题后则会变量多于约束。而这对于线性规划的经典方法单纯形法(Simplex method)是比较友好的。还一些情况中,对偶问题有一些特殊的结构能够被更方便地求解。这样我们求解对偶问题后,可再求解原问题(例子可参见【1】p248)。另外,如果一个优化问题可微且满足strong duality,则原问题和对偶问题的最优点满足Karush-Kuhn-Tucker(KKT)condition。有时可以通过求解KKT condition来求解原问题(例子可参见【1】p244-245)。

  • 其次,对偶问题有它的实际意义。它在经济学中的博弈论与运筹学都有应用。最经典的是例子就是影子价格(Shadow price)。详细可参见【1】p240,p253和【2】p155。我们可以从sensitivity analysis的角度分析约束变化对最优值的影响。将最开始的原问题的约束中的右边从0变为变量(为方便暂且称为约束变量),它代表我们可以放松或是收紧约束。原问题即变为以下形式(称为perturbed problem,原问题相应称为unperturbed problem):
    min ⁡ f 0 ( x ) s.t. f i ( x ) ≤ u i , i = 1 , . . . , m h i ( x ) = v i , i = 1 , . . . p \begin{align*} \min \quad &f_0(x) \\ \text{s.t.} \quad &f_i(x) \leq u_i, \quad i=1,...,m \\ &h_i(x) = v_i, \quad i=1,...p \end{align*} mins.t.f0(x)fi(x)ui,i=1,...,mhi(x)=vi,i=1,...p
    并把最优值看作约束变量的函数,记作 p ∗ ( u , v ) p^*(u, v) p(u,v)。如果该函数在0点可微且strong duality成立(对线性规划成立),则可得:
    λ i ∗ = − ∂ p ∗ ( 0 ) ∂ u i \lambda_i^* = - \frac{\partial p^*(0)}{\partial u_i} λi=uip(0)
    (可参见【1】253)也就是说,拉格朗日乘子实际上是最优值相对于约束变量的层数。如果目标函数是成本或是收益,而约束变量代表某种资源的数量。拉格朗日乘子代表了增加该资源后成本或收益可以相应减小或增加的速率。它是资源的潜在价值的体现,因此称为影子价格。假如你是有一种资源,面临两种选择:一是自己将之加工然后卖出成品赚钱,另一种是直接卖出资源。那你决策时就要参考该种资源的影子价格。如果你卖出资源的价格小于影子价格,那你血亏。其它的例子,比如对偶还可以用于推导图论中的max-flow min-cut theorem(可参见【3】p96)。

  • 最后,它可以引出一些其它的有用的结论,如在线性规划中非常重要的Farkas引理。Farkas引理可以帮助我们证明线性系统无解。证明无解往往比证明有解更让人头痛一些,而它可以让一个证明无解的问题变为证明有解的问题。下面我们就来说说Farkas引理。

Farkas引理

Farkas引理由Farkas和Minkowski提出。先不急着看它长什么样。既然Farkas引理称为引理而还是定理或是公理,意味着它是推导出来的。那是从哪里引出来的呢?一种是通过duality theory(可参见【2】p165)。Farkas引理反过来也可以帮助证明duality定理。更加基础一些的证明是通过超平面分离定理(Separating hyperplane theorem)。该定理指对于两个非空不相邻的凸集,必存在一个能够分离它们的超平面。在二维或三维上很直观。想象有两个凸的物体,则我们肯定能用一个板把它们隔开。通过它就可以证明Farkas引理。证明过程可参见【2】p172。【3】中是通过fundamental theorem of linear inequalities证明farkas引理,也可以参考。

Farkas引理形式如下:令 A ∈ R m × n A \in \R^{m \times n} ARm×n b ∈ R m b \in \R^m bRm,则下面只能有一个是成立的:

  • A x = b Ax = b Ax=b, x ≥ 0 x \geq 0 x0有解
  • A T y ≥ 0 A^Ty \geq 0 ATy0 b T y < 0 b^Ty < 0 bTy<0有解

Farkas引理属于Theorems of alternatives。如果两个优化问题最多只有一个是可行的,那称为weak alternatives,像上面这种有且只有一个可行的称为strong alternatives。其它的类似的定理还有Gordan’s Theorem,Stiemke’s Theorem等。

看数学描述比较抽象,直观含义其实很好理解。想象在二维或者三维上有一个锥,还有一个点。那只有两种情况:要么点在锥外,这种情况下应用前面的超平面分离定理可知有个超平面可将两者分离。要么在锥内,这种情况下,这个点是锥的一部分,即可以用构成锥的向量的非负加权组合来表示。图就不放了,可参见如何理解 Farkas 引理?Farkas引理的几何意义

注意Frakas引理有很多的变体,比如【1】p263,【2】p166,【3】p89,p93。它们表达的意思都是类似的。

那么,Farkas引理有啥用呢?它在很多领域都有广泛的应用。下面举两个来自不同领域的例子。

一个来源于经济学中的无套利资产定价(可参考【1】p263和【2】p167)。我们常说风险与机遇并存,这在投资领域是广泛存在的,并且也是市场有效健康的保证。那我们如何为投资品定价来保证不存在只有机遇没有风险的情况呢?假设有 n n n种资产,它们的初始时的价格分别为 p = [ p 1 , . . . , p n ] p = [p_1, ..., p_n] p=[p1,...,pn]。一段时间后,它们的价值分别为 v = [ v 1 , . . . , v n ] v = [v_1, ..., v_n] v=[v1,...,vn]。注意 v v v可能有多种可能,记为 v ( 1 ) , . . . , v ( m ) v^{(1)}, ... , v^{(m)} v(1),...,v(m)(即有 m m m种可能)。这样,一段时间后这些资源的价值组合可以写成一个 m × n m \times n m×n的矩阵,记作 V V V。另外记 x = [ x 1 , . . . , x n ] x = [x_1, ..., x_n] x=[x1,...,xn]为对这些资产的投资组合(portfolio)。注意它可以为负,代表做空。于是,投资的初始成本为 p T x p^T x pTx,第 i i i可能下,最终的价值为 v ( i ) T v^{(i)T} v(i)T。如果有 p T x < 0 p^Tx < 0 pTx<0,且对于所有的可能 i = 1 , . . . m i = 1, ... m i=1,...m,有 v ( i ) T ≥ 0 v^{(i)T} \geq 0 v(i)T0(即 V x ⪰ 0 V x \succeq 0 Vx0)。也就是说初始投资成本小于0,最终价值必定大于0,那就说存在套利。通俗地说,就是“空手套白狼”。然而一个有效的市场怎么能允许这种情况出现呢?当然不能。那如何为这些资源定价,保证不存在套利的空间((即absence of arbitrage)呢。用线性规划的语言来说,我们要使 p T x < 0 p^Tx < 0 pTx<0 V x ⪰ 0 V x \succeq 0 Vx0组成的不等式系统无解。但要证明无解通常比较难。Farkas引理告诉我们,它等价于 − V y + p = 0 -V^y + p = 0 Vy+p=0, y ⪰ 0 y \succeq 0 y0有解。于是可以通过求解下面的线性优化问题得到不存在套利前提下第 i i i份资产的定价区间:
min ⁡ or max ⁡ p i s.t. V T y = p y ⪰ 0 \begin{align*} \min \text{or} \max \quad &p_i \\ \text{s.t.} \quad &V^Ty = p \\ & y \succeq 0 \end{align*} minormaxs.t.piVTy=py0
也就是说,要保证无套利条件,资产的定价需要是该种资产在最终价值的所有的可能的非负加权组合。

另一个例子来源于编译,详细可参见【4】。我们知道性能优化的主要手段之一就是并行化。并行化的主要对象是数组操作。但是做并行化的前提是变换不能变更原来的语义,即不能违反数据依赖。

这里的主要优化对象是程序中的循环嵌套(Loop nest),这也常常是最主要耗时的部分之一。要想用数学方法解决工程问题,首先得用数学语言来表达来描述它。对于这样的循环:

for (i = 0; i < m; i++)
    for (j = 0; j < n; j++)
        A[f(i, j)] = A[g(i, j)]

这里的 f f f g g g是循环变量的仿射(affine)函数。仿射函数形如 i i i i + j i+j i+j 2 i + 1 2i + 1 2i+1,但不能是 i ∗ j i*j ij这种。这里限定是仿射函数是因为便于分析,因为仿射函数都可以表示为 A x + b \mathbf{Ax+b} Ax+b这样的形式。这个函数表示了循环中数据的访问模式,实际是迭代空间到数据空间的映射。这样,循环嵌套中的访问就可以形式化地用四元组表示: F , f , B , b \mathbf{F, f, B, b} F,f,B,b B i + b ≥ 0 \mathbf{Bi} + \mathbf{b} \geq \mathbf{0} Bi+b0代表了循环边界约束。 F i + f \mathbf{Fi + f} Fi+f代表了上面提到的仿射函数。如果对于两组迭代索引 i \mathbf{i} i i ′ \mathbf{i}' i,有 F i + f = F ′ i ′ + f ′ \mathbf{Fi + f = F'i' + f'} Fi+f=Fi+f,那就意味着它们访问了数组中的同一元素。于是,我们可以通过求解这个规划来判断是否有数据依赖。

我们在做并行优化时想避免同步,因此希望让访问同一元素的迭代放到同一处理器中。这样不同的处理器间没有数据依赖,就可以自管自尽情跑了。设有数据依赖的两条语句 s 1 s_1 s1 s 2 s_2 s2分别在循环 d 1 d_1 d1 d 2 d_2 d2中。 i 1 \mathbf{i}_1 i1 i 2 \mathbf{i}_2 i2分别表示它们的迭代变量。 C 1 , c 1 \mathbf{C}_1,\mathbf{c}_1 C1,c1 C 2 , c 2 \mathbf{C}_2, \mathbf{c}_2 C2,c2是循环变量到处理器的映射,即代表了迭代到处理器的分配方案。那该优化问题就可以表示为下面的数学问题:对于所有的 i 1 ∈ Z d 1 \mathbf{i}_1 \in \mathbb{Z}^{d_1} i1Zd1 i 2 ∈ Z d 2 \mathbf{i}_2 \in \mathbb{Z}^{d_2} i2Zd2,如果符合:
B 1 i 1 + b 1 ≥ 0 B 2 i 2 + b 2 ≥ 0 F 1 i 1 + f 1 = F 2 i 2 + f 2 \begin{align*} \mathbf{B}_1\mathbf{i}_1 + \mathbf{b}_1 \geq 0 \\ \mathbf{B}_2\mathbf{i}_2 + \mathbf{b}_2 \geq 0 \\ \mathbf{F}_1\mathbf{i}_1 + \mathbf{f}_1 = \mathbf{F}_2\mathbf{i}_2 + \mathbf{f}_2 \end{align*} B1i1+b10B2i2+b20F1i1+f1=F2i2+f2
则有 C 1 i 1 + c 1 = C 2 i 2 + c 2 \mathbf{C}_1 \mathbf{i}_1 + \mathbf{c}_1 = \mathbf{C}_2 \mathbf{i}_2 + \mathbf{c}_2 C1i1+c1=C2i2+c2。更详细的求解过程可参见【4】p835,这里不展开了。

上面是空间维度上(称为Space-partition constraints),那在时间维度也会有面临类似的问题(称为Time-partition constraints)。我们知道,Pipelining是一个常见的优化,比如对于 n n n次迭代的循环,可以组成 n n n个stage的pipeline。不同stage分配给不同的处理器。这样不同的处理器之间就可以并行起来,从而减少耗时。

但是,要做这样的优化是有前提的。一般地,如果最外层循环可以变换迭代顺序,那可以被pipeline。

沿用前面的数学表达,区别是这里的 C 1 , c 1 \mathbf{C}_1,\mathbf{c}_1 C1,c1 C 2 , c 2 \mathbf{C}_2, \mathbf{c}_2 C2,c2是循环变量到最外层循环迭代次数的映射,代表了迭代在时间维度上的切分。如果对于 i 1 \mathbf{i}_1 i1 i 2 \mathbf{i}_2 i2 i 1 ≺ s 1 s 2 i 2 \mathbf{i}_1 \prec_{s_1 s_2} \mathbf{i}_2 i1s1s2i2 ≺ \prec 为lexicographically less than,想象下字典中的单词排序),那么需要满足 C 1 i 1 + c 1 ≤ C 2 i 2 + c 2 \mathbf{C}_1 \mathbf{i}_1 + \mathbf{c}_1 \leq \mathbf{C}_2 \mathbf{i}_2 + \mathbf{c}_2 C1i1+c1C2i2+c2。该约束的实际含义是对于在原程序中的两次迭代,经过变换后在外层循环中其先后顺序不能颠倒。将前面这坨写在一起就是:对于所有 i 1 ∈ Z d 1 \mathbf{i}_1 \in \mathbb{Z}^{d_1} i1Zd1 i 2 ∈ Z d 2 \mathbf{i}_2 \in \mathbb{Z}^{d_2} i2Zd2,如果符合:
i 1 ≺ s 1 s 2 i 2 B 1 i 1 + b 1 ≥ 0 B 2 i 2 + b 2 ≥ 0 F 1 i 1 + f 1 = F 2 i 2 + f 2 \begin{align*} \mathbf{i}_1 \prec_{s_1 s_2} \mathbf{i}_2 \\ \mathbf{B}_1\mathbf{i}_1 + \mathbf{b}_1 \geq 0 \\ \mathbf{B}_2\mathbf{i}_2 + \mathbf{b}_2 \geq 0 \\ \mathbf{F}_1\mathbf{i}_1 + \mathbf{f}_1 = \mathbf{F}_2\mathbf{i}_2 + \mathbf{f}_2 \end{align*} i1s1s2i2B1i1+b10B2i2+b20F1i1+f1=F2i2+f2
则有 C 1 i 1 + c 1 ≤ C 2 i 2 + c 2 \mathbf{C}_1 \mathbf{i}_1 + \mathbf{c}_1 \leq \mathbf{C}_2 \mathbf{i}_2 + \mathbf{c}_2 C1i1+c1C2i2+c2。对于这个线性系统,如果有多个解,就可以pipelining。但它与前面的线性系统相比,它的多个两个不等式。前面提过,Farkas引理的一个作用是可以把烦人的不等式换成等式。这里把前面一坨的约束统一写成 A x ≥ 0 \mathbf{Ax} \geq 0 Ax0 C 1 i 1 + c 1 ≤ C 2 i 2 + c 2 \mathbf{C}_1 \mathbf{i}_1 + \mathbf{c}_1 \leq \mathbf{C}_2 \mathbf{i}_2 + \mathbf{c}_2 C1i1+c1C2i2+c2写成 c T x ≥ 0 \mathbf{c}^T\mathbf{x} \geq 0 cTx0,那我们其实是要求解:求解 c \mathbf{c} c,使得对于所有的符合 A x ≥ 0 \mathbf{Ax} \geq 0 Ax0 x \mathbf{x} x,有 c T x ≥ 0 \mathbf{c}^T\mathbf{x} \geq 0 cTx0。而Farkas引理告诉我们,下面两个不等式系统只有一个是有解的:
primal : A x ≥ 0 , c T x < 0 dual : A T y = c , y ≥ 0 \begin{align*} \text{primal}: &\quad \mathbf{Ax} \geq 0, &\mathbf{c}^T\mathbf{x} < 0 \\ \text{dual}: &\quad \mathbf{A}^Ty = \mathbf{c}, &\mathbf{y} \geq 0 \end{align*} primal:dual:Ax0,ATy=c,cTx<0y0
易见原问题等价于这里的primal问题无解,也就等价于dual问题有解。这里只列了与Farkas引理相关的部分,更详细求解算法可见【4】p872。

References

  1. 《Convex Optimization》
  2. 《Introdution to Linear Optimization》
  3. 《Theory of Linear and Integer Programming》
  4. 《Compilers: Principles, Techniques, and Tools》
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐