本文是学习组合优化中设计近似算法时,所用的入门概念,与大家共勉!
主要回答:
- 什么是判定问题
- 问题规模与输入字节的长度定义
- 如何衡量算法的运行时间
-
- 多项式时间算法(有效算法)
-
- 强多项式时间算法(有效算法)
-
- 指数时间算法
计算复杂性理论
给定一个最优化问题,我们需要回答以下问题:
- 如何界定最优化问题难易程度,并比较两个最优化问题相对难度?
- 什么是有效算法?怎么定义一个算法比另一个算法好?
弄清楚以上问题将有助于我们理解“最优化”问题中容易问题和困难问题之阿金的差距,并对不同问题采取不同的算法策略.
复杂性理论只适用于判定问题,而非我们熟悉的最优化问题.
判定问题
按照计算复杂性将问题进行分类,这样才能将问题准确归类。需要以下四个概念:
- 集合 C \mathcal{C} C为复杂性理论适用的问题集合;
- 非空子集 C ϵ ⊆ C \mathcal{C_\epsilon}\subseteq\mathcal{C} Cϵ⊆C为容易问题集合;
- 非空子集 C H ⊆ C \mathcal{C_{\mathcal{H}}}\subseteq \mathcal{C} CH⊆C为难问题集合;
- 关系 P ▹ Q P\triangleright Q P▹Q表示问题 P P P不必问题 Q Q Q难.
判定问题是指回答“是”或“否”的问题.
对最优化问题:
z
∗
=
{
max
c
⊤
x
∣
x
∈
S
}
,
z^*=\{\max{c^{\top}x|x\in\mathcal{S}}\},
z∗={maxc⊤x∣x∈S},
其对应的判定问题为:对任意给定常数
k
k
k,是否存在
x
∈
S
x\in\mathcal{S}
x∈S使得
c
⊤
x
≥
k
?
c^{\top}x\geq k?
c⊤x≥k?
例子(装箱问题,The bin-packing problem)
给定若干体积为
C
C
C的箱子,
n
n
n件物品构成集合
S
S
S, 体积分别为
{
s
1
,
s
2
,
⋯
,
s
n
}
\{s_1,s_2,\cdots,s_n\}
{s1,s2,⋯,sn},其中
s
i
s_i
si皆为整数. 目标是希望将物品分配到箱子中使得占用的箱子的数目最小.不失一般性,规定箱子容量为1.
下面写出该问题的整数规划:
实例
I
I
I:给定
n
n
n件物品体积分别为
{
s
1
,
s
2
,
⋯
,
s
n
}
\{s_1,s_2,\cdots,s_n\}
{s1,s2,⋯,sn},其中
s
i
s_i
si皆为整数.
设
I
I
I含有恰好
b
i
b_i
bi个
s
i
(
1
=
1
,
2
,
⋯
,
m
)
s_i(1=1,2,\cdots,m)
si(1=1,2,⋯,m),
T
1
,
T
2
,
⋯
,
T
N
T_1,T_2,\cdots,T_N
T1,T2,⋯,TN是单个箱子装入物品的所有可能形式:
{
T
1
,
T
2
,
⋯
,
T
N
}
:
=
{
(
k
1
,
k
2
,
⋯
,
k
m
)
∈
Z
+
m
∣
∑
i
=
1
n
k
i
s
i
≤
1
}
\{T_1,T_2,\cdots,T_N\}:=\{(k_1,k_2,\cdots,k_m)\in Z^m_{+}|\sum_{i=1}^n k_i s_{i}\leq 1\}
{T1,T2,⋯,TN}:={(k1,k2,⋯,km)∈Z+m∣∑i=1nkisi≤1}.
记
T
j
=
(
t
j
1
,
⋯
,
t
j
m
)
T_j=(t_{j1},\cdots,t_{jm})
Tj=(tj1,⋯,tjm). 则装箱问题等价于下面的整数规划形式(Eisemann,1957):
min
∑
i
=
1
N
x
j
\min\sum_{i=1}^N x_j
mini=1∑Nxj
s.t.
∑
j
=
1
N
t
j
i
s
i
≥
b
i
,
i
=
1
,
2
,
⋯
,
m
\sum_{j=1}^N t_{ji}s_{i}\geq b_i,\quad i=1,2,\cdots,m
j=1∑Ntjisi≥bi,i=1,2,⋯,m
x
j
∈
Z
+
,
j
=
1
,
2
,
⋯
,
N
x_j\in Z_{+},\quad j=1,2,\cdots,N
xj∈Z+,j=1,2,⋯,N
实际上我们要求
∑
j
=
1
N
t
j
i
s
i
=
b
i
,
\sum_{j=1}^N t_{ji}s_{i}= b_i,
∑j=1Ntjisi=bi,但由于是极小化问题,因此放松这个约束并没有影响.
最优化问题:使用最少的
m
m
m个箱子,将集合
S
S
S划分成
m
m
m个子集合,每个子集物品体积不超过箱子容量1.即用最少的箱子将
n
n
n个物品收纳完.
判定问题:给定常数
K
K
K, 能否将集合
S
S
S划分成
K
K
K个子集,每个物品总体积不超过1.即问给定常数
K
K
K, 能否将
n
n
n建物品装完?
衡量算法有效性及问题难度
首先明确我们感兴趣的是“问题”的难度,而非一个问题的特殊实例的难度.
何为问题?
问题(模型)是指目标函数和约束条件符合某种特殊结构的无穷多个最优化问题实例对应的判定问题的集合.
如何衡量一个问题的难度呢?
- 根据求解问题的实例的平均运行时间来衡量. 平均运行时间的计算需要在问题的数据符合某种概率分布的前提下进行,而且很难分析,因此该方法一般也不适合用于算法复杂性分析.
- 根据该问题中所有实例中最坏情形时的运行时间来衡量. 计算复杂性理论主要是基于最坏情形分析起来的.
算法的运行时间不仅与问题规模(即变量的维数和约束的个数)有关,而且与问题输入数据的字节长度有关.
输入字节的长度:对于一个问题的实例
X
X
X, 它的输入长度
L
(
X
)
L(X)
L(X)是指存储该实例的输入数据所需的二进制序列的长度.
设整数
x
x
x满足
2
n
≤
x
≤
2
n
+
1
,
2^n \leq x \leq 2^{n+1},
2n≤x≤2n+1,则
x
x
x可以由二进制序列
{
v
0
,
v
1
,
⋯
,
v
n
}
\{v_0,v_1,\cdots,v_n\}
{v0,v1,⋯,vn}来表示,这里
x
=
∑
i
=
1
n
v
i
2
i
,
v
i
∈
{
0
,
1
}
.
x=\sum_{i=1}^n v_i2^i,\quad v_i\in\{0,1\}.
x=i=1∑nvi2i,vi∈{0,1}.
注意
n
≤
log
2
x
<
n
+
1
n\leq \log_2 x<n+1
n≤log2x<n+1. 所以
x
∈
Z
x\in Z
x∈Z的 输入长度是
log
2
x
+
1
\log_2 x+1
log2x+1. 因不同底的对数是同阶量级,因此就用自然对数
log
x
\log x
logx代替
log
2
x
\log_2 x
log2x. 有理数
α
=
p
q
\alpha=\frac{p}{q}
α=qp、整数矩阵
A
=
(
a
i
j
)
m
∗
n
A=(a_ij)_{m*n}
A=(aij)m∗n\线性不等式或等式
A
x
≤
b
Ax\leq b
Ax≤b、
A
x
=
b
Ax=b
Ax=b. 则他们的输入长度分别为
L
(
X
)
=
log
∣
p
∣
+
log
∣
q
∣
;
#
p
,
q
L
(
X
)
=
m
n
log
∣
θ
∣
,
θ
=
max
∣
a
i
j
∣
;
#
max
∣
a
i
j
∣
m
n
L
(
X
)
=
m
n
log
∣
θ
∣
+
log
∣
b
∣
#
max
∣
a
i
j
∣
m
n
+
b
L(X)=\log |p|+\log |q|;\#p,q\\ L(X)=mn\log |\theta|, \theta=\max|a_{ij}|;\#\max|a_{ij}|^{mn}\\ L(X)=mn\log |\theta|+\log |b|\#\max|a_{ij}|^{mn}+b
L(X)=log∣p∣+log∣q∣;#p,qL(X)=mnlog∣θ∣,θ=max∣aij∣;#max∣aij∣mnL(X)=mnlog∣θ∣+log∣b∣#max∣aij∣mn+b
举例(背包问题)
输入数据:
a
=
(
a
1
,
⋯
,
a
n
)
⊤
,
c
=
(
c
1
,
⋯
,
c
n
)
⊤
,
b
,
a=(a_1,\cdots,a_n)^{\top}, c=(c_1,\cdots,c_n)^{\top}, b,
a=(a1,⋯,an)⊤,c=(c1,⋯,cn)⊤,b,并且满足
a
j
≤
b
,
j
=
1
,
2
,
⋯
,
n
.
a_j \leq b,j=1,2,\cdots,n.
aj≤b,j=1,2,⋯,n. 因此
x
x
x输入长度为
L
(
X
)
=
log
(
n
)
+
(
n
+
1
)
log
(
b
)
+
n
log
(
θ
)
,
L(X)=\log(n)+(n+1)\log(b)+n\log(\theta),
L(X)=log(n)+(n+1)log(b)+nlog(θ),
其中
θ
=
max
i
c
i
\theta=\max_i c_i
θ=maxici.
算法的运行(计算)时间
我们希望计算的衡量方法和具体的计算机无关,因而只考虑算法所需要的基本运算的次数,即加减乘除以及两个数的比较的次数,并且不妨假设每种基本运算的时间相同.
给定问题 P P P和求解问题 P P P的一个算法 A \mathcal{A} A, 算法 A \mathcal{A} A,能在有限时间内求解 P P P任何实例 X X X. 设 g A ( X ) g_A(X) gA(X)为算法 A \mathcal{A} A求解问题 P P P的实例 X X X所需的基本运算次数,则 f A ( l ) = sup { g A ( X ) ∣ L ( X ) = l } f_{A}(l)=\sup\{g_A(X)|L(X)=l\} fA(l)=sup{gA(X)∣L(X)=l}定义为算法 A A A求解问题 P P P的运行时间或计算时间.
通常情况下,不必给出
f
A
(
l
)
f_A(l)
fA(l)的精确表达式,只需要给出一个同阶量的表达式即可.
如果存在常数
α
>
0
,
β
>
0
,
\alpha>0,\beta>0,
α>0,β>0,整数
l
′
>
0
l'>0
l′>0, 使得对所有的整数
l
≥
l
′
,
l\geq l',
l≥l′, 都有
f
(
l
)
≤
α
g
(
l
)
+
β
f(l)\leq \alpha g(l)+\beta
f(l)≤αg(l)+β, 则
f
(
l
)
=
O
(
α
g
(
l
)
)
f(l)=O(\alpha g(l))
f(l)=O(αg(l)).
注意:
∑
i
=
0
p
c
i
l
i
=
O
(
l
p
)
,
\sum_{i=0}^p c_i l^i=O(l^p),
i=0∑pcili=O(lp),即可以忽略所有常熟及指数低于
p
p
p的项. 换言之,只需要考虑当
l
→
∞
l\rightarrow \infty
l→∞时的渐进状态,因而常数及指数低的想都可以忽略不计.
多项式时间算法
给定问题 P P P及其算法 A \mathcal{A} A. 若存在正常数 p p p使得 f A ( l ) = O ( l p ) f_A(l)=O(l^p) fA(l)=O(lp), 则称 A \mathcal{A} A为问题 P P P的多项式时间算法.
强多项式时间算法
如果存在正常数 p p p是的算法 A A A求解问题 P P P的计算时间为 O ( n p ) O(n^p) O(np),其中 n n n为问题的规模, 于输入数据的大小无关, 则称 A A A为问题 P P P的强多项式时间算法.
指数时间算法
给定问题
P
P
P及其算法
A
\mathcal{A}
A, 若对所有的正常数
p
p
p,都有使得
f
A
(
l
)
≠
O
(
l
p
)
f_A(l)\neq O(l^p)
fA(l)=O(lp), 即存在常数
c
1
、
c
2
>
0
,
d
1
,
d
2
>
1
c_1、c_2>0,d_1,d_2>1
c1、c2>0,d1,d2>1及整数
l
′
>
0
l'>0
l′>0, 使得对所有的整数
l
≥
l
′
l\geq l'
l≥l′有
c
1
d
1
l
≤
c
2
d
2
,
c_1d_1^l\leq c_2d_2,
c1d1l≤c2d2,则称
A
\mathcal{A}
A为问题
P
P
P的指数时间算法.
以上内容参考:
《整数规划》孙小玲、李端著.第6章
《组合最优化:理论与算法》[德] Bernhard Korte Jens Vygen 著,越民义 林诒勋 姚恩瑜 张国川 译第18.2节. Eisemann K.1957.The trim problem.Management Science, 3: 279-284.