竞争分析的定义
对于一种在线算法A, 如果存在一个常数K, 对于任何序列S的操作的成本, C A ( S ) < = α . C o p t ( S ) + K C_A(S)<= \alpha.C_{opt}(S)+K CA(S)<=α.Copt(S)+K, 则我们可以称算法A为 α \alpha α阶竞争的,此处, C o p t C_{opt} Copt是最优算法的成本,又称上帝算法,假设该算法可以预见所有的后续操作并给出一个最优的算法。
这意味着,如果最优算法(上帝)可以做的更好,该 α \alpha α阶竞争的算法也可以相对的做的更好,而 α \alpha α阶竞争的算法性能不佳时,最优算法(上帝)也好不到那里去。他们的性能表现始终是同向的。
为了说明竞争分析的方法,我们要对一个在线算法进行分析,并证明该算法是 α \alpha α - 竞争的。
自组织列表
这个算法出现在算法大牛Danny Sleator和Bob Tarjan的论文里,感兴趣的小伙伴可以自行去搜索该论文。
定义:列表L包含n个元素,
- 访问X元素的操作被定义为Access(X), 其成本是 r a n k L ( X ) rank_L(X) rankL(X)等于从L列表头到X的元素个数,假设每访问一个元素的代价为1, 每次都从列表头开始逐个搜索到需要访问的元素。
- 列表L可以通过交换操作相邻位置的两个元素来改变顺序。每一次交换的代价是1。
- 在线算法A每次必须在立即访问操作的同事运行,且无法知道后续访问操作时什么。相对的,最优算法则是可以与之全部后续的访问操作,并将序列调整到最优状态的算法。
此处我们介绍一种启发式算法:move-to-front,即在某元素被访问后,即可使用交换算法,将此元素移到队列的列首。所以,一次访问的代价是
C o s t = 2. r a n k L ( X ) Cost=2.rank_L(X) Cost=2.rankL(X)
这里要解释一下为什么是2倍的 r a n k L ( X ) rank_L(X) rankL(X), 其中一次是访问该元素的代价,另一次是交换该元素的队列首的代价。
竞争分析实例
此处我们就使用竞争分析来分析一下move-to-front(MTF)是否是
α
\alpha
α-竞争的。
C
i
=
M
T
F
C_i=MTF
Ci=MTF算法的每次访问操作的代价
=
2.
r
a
n
k
L
i
−
1
(
X
)
=2.rank_{L_i-1}(X)
=2.rankLi−1(X)
C
i
∗
=
O
P
T
C^*_i=OPT
Ci∗=OPT算法的每次访问操作的代价
=
r
a
n
k
L
i
−
1
∗
(
X
)
+
t
i
=rank^*_{L_i-1}(X)+t_i
=rankLi−1∗(X)+ti 其中设
t
i
t_i
ti是最优算法进行元素交换的代价
定义势能方程
Φ
:
L
i
→
R
\Phi:{L_i} \rightarrow R
Φ:Li→R
Φ
(
L
i
)
=
2
∣
{
(
x
,
y
)
.
x
⋉
L
i
y
,
a
n
d
,
y
⋉
L
i
∗
x
}
∣
\Phi(L_i)=2|\lbrace(x,y).x\ltimes _{L_i}y, and, y\ltimes_{L_i}^*x\rbrace|
Φ(Li)=2∣{(x,y).x⋉Liy,and,y⋉Li∗x}∣
=
2
×
=2\times
=2×#倒置数
此处解释一下集合
∣
{
(
x
,
y
)
.
x
⋉
L
i
y
,
a
n
d
,
y
⋉
L
i
∗
x
}
∣
|\lbrace(x,y).x\ltimes _{L_i}y, and, y\ltimes_{L_i}^*x\rbrace|
∣{(x,y).x⋉Liy,and,y⋉Li∗x}∣代表的是一组列表中的元素的集合,
⋉
\ltimes
⋉是前序符号,表示x在y的前序,该组元素在MTF算法中的列表和最优算法中的列表的前后次序是颠倒的。
为了更清楚的来解释这个问题,我们来看一下下面这个例子。
上图中,L是MTF算法中 i 次访问前的列表序列, 而L是最优算法在 i 次访问前的序列。那逆序的元素对如下:
Φ
(
L
i
)
=
2.
∣
(
E
,
C
)
,
(
E
,
A
)
,
(
E
,
D
)
,
(
E
,
B
)
,
(
B
,
D
)
∣
=
10
\Phi(L_i)=2.|{(E,C), (E,A), (E,D), (E,B), (B,D) }|=10
Φ(Li)=2.∣(E,C),(E,A),(E,D),(E,B),(B,D)∣=10
此处
Φ
(
L
i
)
>
=
0
∀
i
\Phi(L_i)>=0 \forall i
Φ(Li)>=0∀i 且
Φ
(
L
0
)
=
0
\Phi(L_0)=0
Φ(L0)=0 当MTF和OPT的起始列表是一样序列的
那对于一次交换,势能函数
Φ
\Phi
Φ的变化是多少呢?由交换操作的本质可知,每次交换可以产生或消除一对逆序元素。因此
Δ
Φ
=
±
2
\Delta\Phi=\pm2
ΔΦ=±2
那么,我们该如何来计算一次访问后的势能变化呢?为了解答这个问题,我们来定义一组集合如下:
A
=
{
y
∈
l
i
:
y
⋉
L
i
−
1
x
,
a
n
d
,
y
⋉
L
i
−
1
∗
x
}
A=\lbrace y\in l_i: y\ltimes_{L_i-1} x , and, y \ltimes_{L_i-1}^*x\rbrace
A={y∈li:y⋉Li−1x,and,y⋉Li−1∗x}
B
=
{
y
∈
l
i
:
y
⋉
L
i
−
1
x
,
a
n
d
,
y
⋊
L
i
−
1
∗
x
}
B=\lbrace y\in l_i: y\ltimes_{L_i-1} x , and, y \rtimes_{L_i-1}^*x\rbrace
B={y∈li:y⋉Li−1x,and,y⋊Li−1∗x}
C
=
{
y
∈
l
i
:
y
⋊
L
i
−
1
x
,
a
n
d
,
y
⋉
L
i
−
1
∗
x
}
C=\lbrace y\in l_i: y\rtimes_{L_i-1} x , and, y \ltimes_{L_i-1}^*x\rbrace
C={y∈li:y⋊Li−1x,and,y⋉Li−1∗x}
D
=
{
y
∈
l
i
:
y
⋊
L
i
−
1
x
,
a
n
d
,
y
⋊
L
i
−
1
∗
x
}
D=\lbrace y\in l_i: y\rtimes_{L_i-1} x , and, y \rtimes_{L_i-1}^*x\rbrace
D={y∈li:y⋊Li−1x,and,y⋊Li−1∗x}
为了更好的解释这组集合的含义,我们来看下图。
在列表
L
i
−
1
L_{i-1}
Li−1中, X元素位于图中所示的位置,X元素前的所有元素被分成
A和B两个集合,A集合中的元素在列表
L
i
−
1
∗
L_{i-1}^*
Li−1∗中也位于X元素前,而B集合中的元素则在列表
L
i
−
1
∗
L_{i-1}^*
Li−1∗中位于X元素之后。理解了A,B两个集合,则C,D两个集合就很容易了。
由此,我们可以定义在
L
i
−
1
L_{i-1}
Li−1中X的前序元素集合为AUB,X的后续元素集合为CUD。而在列表
L
i
−
1
∗
L_{i-1}^*
Li−1∗中X的前序元素集合为AUC,X的后续元素的集合为BUD。
因此,r=|A|+|B|+1, r=|A|+|C|+1,当MTF移动X元素到列表头时,会产生|A|组逆序,并消除了|B|组逆序。
同时,最优算法的每次交换元素可能产生少于1组逆序。
因此,
Φ
(
L
i
)
−
Φ
(
L
i
−
1
)
<
=
2
(
∣
A
∣
−
∣
B
∣
+
t
i
)
\Phi (L_i)-\Phi (L_{i-1})<=2(|A|-|B|+t_i)
Φ(Li)−Φ(Li−1)<=2(∣A∣−∣B∣+ti)
此处我们使用平摊分析的代价公式来求第 i 次访问的代价的通式:
C
^
i
=
C
i
+
Φ
(
L
i
)
−
Φ
(
L
i
−
1
)
\hat C_i=C_i+\Phi (L_i)-\Phi (L_{i-1})
C^i=Ci+Φ(Li)−Φ(Li−1)
<
=
2.
r
+
2.
(
∣
A
∣
−
∣
B
∣
+
t
i
)
<=2.r+2.(|A|-|B|+t_i)
<=2.r+2.(∣A∣−∣B∣+ti)
由
r
=
∣
A
∣
+
∣
B
∣
+
1
r=|A|+|B|+1
r=∣A∣+∣B∣+1 可得
上式
=
2.
r
+
2
(
∣
A
∣
−
(
r
−
1
−
∣
A
∣
)
+
t
i
)
=2.r+2(|A|-(r-1-|A|)+t_i)
=2.r+2(∣A∣−(r−1−∣A∣)+ti)
=
2.
r
+
4
∣
A
∣
−
2.
r
+
2
+
2
t
i
=2.r+4|A|-2.r+2+2t_i
=2.r+4∣A∣−2.r+2+2ti
=
4.
∣
A
∣
+
2
+
2
t
i
=4.|A|+2+2t_i
=4.∣A∣+2+2ti
由
r
∗
=
∣
A
∣
+
∣
C
∣
+
1
>
=
∣
A
∣
+
1
r^*=|A|+|C|+1>=|A|+1
r∗=∣A∣+∣C∣+1>=∣A∣+1
上式
<
=
4.
(
r
∗
+
t
i
)
=
4
C
i
∗
<=4.(r^*+t_i)=4C_i^*
<=4.(r∗+ti)=4Ci∗
接下来我们来求所有访问的代价总和如下。
C
M
T
F
(
S
)
=
Σ
i
=
1
∣
s
∣
C
i
C_{MTF}(S)=\Sigma_{i=1}^{|s|}C_i
CMTF(S)=Σi=1∣s∣Ci
由
C
^
i
=
C
i
+
Φ
(
L
i
)
−
Φ
(
L
i
−
1
)
\hat C_i=C_i+\Phi (L_i)-\Phi (L_{i-1})
C^i=Ci+Φ(Li)−Φ(Li−1)可得
C
i
=
C
^
i
−
Φ
(
L
i
)
+
Φ
(
L
i
−
1
)
C_i=\hat C_i-\Phi (L_i)+\Phi (L_{i-1})
Ci=C^i−Φ(Li)+Φ(Li−1)代入上式可得
=
Σ
i
=
1
∣
s
∣
(
C
^
i
+
Φ
(
L
i
−
1
)
−
Φ
(
L
i
)
)
=\Sigma_{i=1}^{|s|}(\hat C_i+\Phi(L_{i-1})-\Phi(L_i))
=Σi=1∣s∣(C^i+Φ(Li−1)−Φ(Li))
=
Σ
i
=
1
∣
s
∣
C
^
i
+
Φ
(
L
0
)
−
Φ
(
L
∣
s
∣
)
=\Sigma_{i=1}^{|s|}\hat C_i+\Phi(L_0)-\Phi(L_{|s|})
=Σi=1∣s∣C^i+Φ(L0)−Φ(L∣s∣)
由
Φ
(
L
0
)
=
0
\Phi(L_0)=0
Φ(L0)=0可得
=
Σ
i
=
1
∣
s
∣
C
^
i
−
Φ
(
L
∣
s
∣
)
=\Sigma_{i=1}^{|s|}\hat C_i-\Phi(L_{|s|})
=Σi=1∣s∣C^i−Φ(L∣s∣)
之前我们已经推导出
C
^
i
<
=
4
C
i
∗
\hat C_i <=4C_i^*
C^i<=4Ci∗可得到
上式
<
=
Σ
i
=
1
∣
s
∣
4
C
i
∗
−
Φ
(
L
∣
s
∣
)
<= \Sigma_{i=1}^{|s|} 4C_i^*-\Phi(L_{|s|})
<=Σi=1∣s∣4Ci∗−Φ(L∣s∣)
<
=
4.
C
o
p
t
(
S
)
<=4.C_{opt}(S)
<=4.Copt(S)
以上证明MTF算法对于自组织队列而言是 4阶竞争的。这是一个很赞的证明,因为由此你可以发现MTF算法在任何情况下都不会比最优算法糟糕太多,换句话说如果在某种特定情况想最优算法可以做的更好,那MTF也可以相应的提升,而当MTF算法表现不好的时候,实际上最优算法也不会好到那里去,他们始终是可以相比较的。
此处值得一提的是,在Danny Sleator和Bob Tarjan的论文里,他们的算法将被访问的元素直接移动到列表的头部,而不是通过逐个交换到表头。因此,在他们的算法中移动到表头的代价是固定的,和该元素的位置无关,由此MTF算法可以进一步优化成 2阶竞争的。