k-server问题
对于一个集合S,如果可以对于其中任意两个元素x,y定义距离d(x,y),并且满足正定性:∀x,y,d(x,y)≥0且d(x,y)=0当且仅当x=y;对称性:∀x,y,d(x,y)=d(y,x);三角不等式∀x,y,z,d(x,y)+d(y,z)≥d(x,z),就称(S,d)为一个度量空间(metric space)。
在一个度量空间(S,d)中,有k个可移动的server,它们初始时位于位置p1,⋯,pk,其中pi∈S。现在有一连串的请求x1,⋯,xn,其中xi∈S。当遇到请求xi时,需要有一个server移动到位置xi,代价就是该server移动前的位置到xi的度量,然后才能处理下一个请求。应当怎样设计server的移动策略,才能使得总代价尽量小?这就是k-server问题。
一个很重要的观察是,Cache问题可以归约到k-server问题。对于一个大小为k的cache,假设不同的页个数最多为m,那么我们可以构造一个m个点的完全图(无向图),边权为1,那么每个点到自己的距离为0,到其他任意点的距离都为1,这就构成了一个度量空间。对于这个度量空间上的k-server问题,如果server不需要移动就对应cache hit,需要移动就对应cache miss,消耗代价为1,因此k-server的代价都可以看作cache miss的总数。
既然我们已经知道Cache问题的确定性算法的ratio只能做到k,因此k-server的确定性算法的ratio不可能比k更小。同理,由于Cache问题的随机算法的ratio最优为O(logk),因此k-server的随机算法的ratio也不可能比O(logk)最好。那么,能否证明k-server的ratio恰好是k(对于随机算法,O(logk))呢?
Fixed Ranged & Greedy
为了讨论方便,我们简化一下问题的模型。考虑“一维数轴上的整点”作为度量空间,并且只有两个server的情况。初始时所有server都位于原点。
我们容易想到一个Fixed Ranged的算法:一个server负责所有[0,+∞)的请求,一个server负责所有(−∞,0)的请求。然而我们可以构造一个请求的序列:3,4,3,4,⋯,我们的算法不停用右侧server去服务,因此总代价是O(n)的。但是OPT只需把两个server分别移到3和4,那么总代价是常数的。因此在这样的例子下ratio达到了O(n),不满足我们的期待。
另一个容易想到的算法是贪心:每次让靠得更近的server去服务。但是这样依然是不优的,假设初始是两个server的位置在−100,100,那么考虑请求序列101,102,101,102,⋯,我们的算法依然是在不停移动右侧的server,而OPT会把两个server分别放置在101和102上,依然达到了O(n)的ratio。
Double Coverage
从以上例子中可以看出,我们构造的算法之所以不好,是因为OPT总是能移动两个server,而我们的算法在特定的构造下只会去移动其中一个server。所以我们提出这样一个算法:当一个请求位于两个server的区间外部时,依然只移动较近的那个server;当请求位于内部时,让两个server同时以相同的速度靠近,直到其中一个先碰到请求位置。这称为Double Coverage算法。
注意,在我们对问题的描述中,虽然只允许每次移动一个server,但是上述描述中我们似乎在同时移动两个server。然而我们可以通过一个“lazy”的转换把以上算法变成每次只移动一个server的版本:当请求位于内部时,移动离请求近的server,同时把本来另一个server应当移动的距离记录下来,并假想它已经到达做了移动,直到下一次需要移动它时,再一次性让它经历所有它本该做的移动。
这个算法很容易拓展到多个server的情形:假设当前状态所有server位于s1≤s2≤⋯≤sk。对于请求x,假设x<s1则移动s1,如果x>sk则移动sk,否则它一定位于某个区间(si,si+1),那么让si,si+1以相同速度靠近直到其中一格先碰到x。
Amortized Analysis
对Double Coverage算法的分析需要用到均摊分析方法(Amortized Analysis)。让我们以对“栈”的分析来回顾用势能函数做均摊分析的过程。某个栈支持两种操作,以常数1的代价push,或以k的代价把栈内所有元素都弹出(其中k是栈内元素个数)。设栈的大小最多为m,那么如果对于每一步做分析我们发现栈的每一步操作我们都只能得到一个代价的上界m。设操作总数为n,显然总的代价不可能真的达到n⋅m。所以我们可以采取这样一种分析方法:每次一个元素push进栈时,实际产生了代价1,我们再认为它产生了一个潜在的(potential)代价1。当栈里有k个元素,并需要执行弹出时,我们已经产生了潜在的代价k,此时我们把潜在的代价变为实际的,那么弹出操作产生的实际代价就可以看作0。最后我们把实际代价和潜在代价之和看作我们分析的代价的上界,得到总的代价应当有上界2n。这就是均摊分析方法,其中用来描述潜在代价的函数称为势能函数(potential function),记为Φ。在这个例子中,Φ(k)=k,表示栈里有k个元素时产生潜在代价k。
在这个问题里,我们也会基于算法中对象的状态(server的位置)定义一个势能函数,并把每一步产生的代价看作实际代价和势能函数变化量的和:cost′(ALG):=cost(ALG)+ΔΦ。这样,对于整个过程就有∑cost′(ALG)=∑cost(ALG)+Φn−Φ0。注意,势能函数是基于程序状态的函数,这和物理中势能的定义很类似,累加后我们只需用末状态减去初状态即可。
我们想证明,Double Coverage有k的ratio。也即我们想证∑cost(ALG)≤k⋅∑cost(OPT)。为此,只需证明每一步都有cost(ALG)+ΔΦ≤k⋅cost(OPT),并且Φn−Φ0≥0。那么,在对Double Coverage的ratio的分析中,我们应当如何设计势能函数呢?可以看到,这里势能函数是用来衡量算法与OPT之间表现的差距的。所以我们考虑OPT算法执行过程中每一步请求以后server位置的状态。对于某一时刻,假设OPT中k个server位于o1≤o2≤⋯≤ok,ALG中的k个server位于s1≤s2≤⋯≤sk,我们(灵光一闪地)定义势能函数Φ=k⋅M+S,其中k就是server个数,M=i=1∑k∣si−oi∣,S=i<j∑(sj−si)。这么设计是出于以下考虑:如果ALG中server的分布和OPT中的分布差异越大,之后ALG所需要做的移动潜在的会变多;如果ALG中server间分布得越分散,之后每一次犯错所带来的代价会越严重。可以看到,这样定义的势能函数确实是关于server状态的函数。
下面我们来分析每一次请求将会带来的势能函数的变化量ΔΦ。由于势能函数是关于状态的函数,我们可以先分析OPT单独移动带来的变化量,再分析ALG单独移动带来的变化量,再把二者累加。首先考虑OPT。对于每个请求,OPT中某一个server的位置会发生变化,假设变化的是ot这个server,那么势能函数发生变化的恰好是k∣st−ot∣这一项,显然这一项的变化量不会超过k倍ot移动的距离,也即k⋅cost(OPT)。再考虑ALG。先考虑请求发生在最右侧(或最左侧)的情况,此时只需移动最右侧的server,假设移动距离为d,那么S这一项的变化量为(k−1)d。并且,请求位置处一定已经存在一个ot了,所以M的变化量恰好为−d,因此Φ在这一步的总变化量为−d;在考虑请求位于(si,si+1)之间的情况,假设它们各自移动了d/2,此时si与前i−1个拉远了d/2,si+1与前i−1个拉近了d/2,si+1与后k−i−1个拉远了d/2,si与后k−i−1个拉近了d/2,si与si+1本身拉近了d,因此综合来看S的变化量为−d。对于M,此时假设ot位于si,si+1内部,如果t≤i,那么∣si−oi∣必定−d/2;如果t≥i+1,那么∣si+1−oi+1∣必定−d/2。而无论∣si−oi∣还是∣si+1−oi+1∣,增加的都不可能超过d/2,综上M不可能增大。综合起来,ALG引起的Φ的变化量不超过−d,也即−cost(ALG)。累加起来,得到cost(ALG)+ΔΦ≤cost(ALG)+k⋅(OPT)−cost(ALG)=k⋅cost(OPT)。
还需要证明Φn−Φ0≥0。由于初始时我们假定所有server都位于原点,因此Φ0=0。而Φn=kM+S≥0,因此成立。
综上,我们得到Double Coverage有k的ratio。
k-server on a tree
边权为1的树也可以作为度量空间,我们可以把一维的Double Coverage算法推广到树上,证明这个算法的ratio也不超过k。
每当请求树上一个点x时,以x为根,假想所有server都会朝x以相同的速度移动,如果某一时刻某个server成为了另一个server的后代节点,那么显然这个后代节点不应该移动,我们认为它一开始就不应该移动,称它为inactive的server,否则称为active的server。因此我们的算法设计如下:当请求x时,令所有active的server移动,直到第一个server碰到x。
我们用与一维情况完全类似的均摊分析。令Φ=kM+S,其中S定义为21i,j∑dist(si,sj),M定义为ρmin{i=1∑kdist(oi,sρi)},其中ρ是所有[k]的permutation(这么定义是为了效仿一维的情况,但是树上没有一个先天的序关系,所以只能取dist之和最小的那个排列)。那么接下来只需证明对于每一次请求cost(ALG)+ΔΦ≤k⋅cost(OPT)。
首先考虑OPT的移动。当ot移动d时,S不变,M的变化不超过d,因此ΔΦ的变化不超过k⋅cost(OPT)。
再考虑ALG。假设共有p个active的server将会移动,且恰好都移动d步。考虑ΔS,inactive的server之间两两距离不变;考虑每对active的和inactive的server之间的距离差之和,枚举inactive的server,在一个inactive的server到根节点的链上有且仅有一个active的server,其余p−1个active server都在x的其它子树上,因此它产生的S变化的贡献为d−(p−1)d,共有k−p个inactive的节点,因此贡献和为(k−p)(2−p)d;对于active的和active之间,两两距离减少2d,因此总变化量为−2d(2p)=−p(p−1)d。综上,ΔS=(2k−pk−p)d。再考虑ΔM,假设每个si依然匹配着上一轮的oi,并让最终会到达根节点的那个si新去匹配位于根节点的那个oi(我们选定了一个特殊的matching,这样会把结果放大),那么M至少增大−d+(p−1)d。
综上,ΔΦ≤k⋅cost(OPT)+k(p−2)cost(ALG)+(2k−pk−p)cost(ALG) =k⋅cost(OPT)−p⋅cost(ALG)。因为p≥1,因此ΔΦ≤k⋅cost(OPT)−cost(ALG),证毕。
Weighted Paging
带权的paging问题可以用树上的k-server解决。假设每个特定页x在cache miss的时候的代价不一定是1,而是一个给定的数值w(x),那么我们可以建这样一棵树:假设共有m个不同的页,那么让这棵树恰好有m个叶节点,叶节点x到根节点的距离为w(x)/2(不妨认为w(x)始终是偶数)。也就是说我们能够得到一个长短参差不齐的star。那么让k个server去serve这些叶节点,恰好对应着树上的k-server问题。所以我们知道,weighted paging也是k competitive的。