1. 程式人生 > >(轉)max-min fairness 最大最小公平演算法

(轉)max-min fairness 最大最小公平演算法

我們經常面臨給一組使用者劃分稀有資源的問題,他們都享有等價的權利來獲取資源,但是其中一些使用者實際上只需要比其他使用者少的資源.那麼我們如何來分配資源呢?一種在實際中廣泛使用的分享技術稱作“最大最小公平分享”.直觀上,公平分享分配給每個使用者想要的可以滿足的最小需求,然後將沒有使用的資源均勻的分配給需要‘大資源’的使用者。

最大最小公平分配演算法的形式化定義如下:

資源按照需求遞增的順序進行分配
不存在使用者得到的資源超過自己的需求
未得到滿足的使用者等價的分享資源
與之對應的可執行定義:

考慮使用者集合1, …, n分別有資源需求x1, x2, …, xn.不失一般性,令資源需求滿足x1 <= x2 <= … <= xn.令伺服器具有能力C.那麼,我們初始把C/n資源給需求最小的使用者.這可能會超過使用者1的需求,繼續處理.該過程結束時,每個使用者得到的沒有比自己要求更多,而且,如果其需求得不到滿足,得到的資源也不會比其他使用者得到的最多的資源還少.我們之所以稱之為最大最小公平分配是因為我們最大化了資源得不到滿足的使用者最小分配的資源.

示例1

有一四個使用者的集合,資源需求分別是2,2.6,4,5,其資源總能力為10,為其計算最大最小公平分配

解決方法:我們通過幾輪的計算來計算最大最小公平分配.第一輪,我們暫時將資源劃分成4個大小為2.5的.由於這超過了使用者1的需求,這使得剩了0.5個均勻的分配給剩下的3個人資源,給予他們每個2.66.這又超過了使用者2的需求,所以我們擁有額外的0.066…來分配給剩下的兩個使用者,給予每個使用者2.5+0.66…+0.033…=2.7.因此公平分配是:使用者1得到2,使用者2得到2.6,使用者3和使用者4每個都得到2.7.

到目前為止,我們假設所有的使用者擁有相同的權利來獲取資源.有時候我們需要給予一些使用者更大的配額.特別的,我們可能會給不同的使用者1, …, n關聯權重w1, w2, …, wn,這反映了他們間的資源配額.

我們通過定義帶權的最大最小公平分配來擴充套件最大最小公平分配的概念以使其包含這樣的權重:

資源按照需求遞增的順序進行分配,通過權重來標準化?
不存在使用者得到的資源超過自己的需求
未得到滿足的使用者按照權重分享資源
下面的示例描述瞭如何實現?

示例2

有一四個使用者的集合,資源需求分別是4,2,10,4,權重分別是2.5,4,0.5,1,資源總能力是16,為其計算最大最小公平分配.

解決方法:第一步是標準化權重,將最小的權重設定為1.這樣權重集合更新為5,8,1,2.這樣我們就假裝需要的資源不是4份而是5+8+1+2=16份.因此將資源劃分成16份.在資源分配的每一輪,我們按照權重的比例來劃分資源,因此,在第一輪,我們計算C/n為16/16=1.在這一輪,使用者分別獲得5,8,1,2單元的資源,使用者1得到了5個資源,但是隻需要4,所以多了1個資源,同樣的,使用者2多了6個資源.使用者3和使用者4拖欠了,因為他們的配額低於需求.現在我們有7個單元的資源可以分配給使用者3和使用者4.他們的權重分別是1和2,最小的權重是1,因此不需要對權重進行標準化.給予使用者3額外的7 × 1/3單元資源和使用者4額外的7 × 2/3單元.這會導致使用者4的配額達到了2 + 7 × 2/3 = 6.666,超過了需求.所以我們將額外的2.666單元給使用者3,最終獲得1 + 7/3 + 2.666 = 6單元.最終的分配是,4,2,6,4,這就是帶權的最大最小公平分配.

# coding=utf-8

st_demand = [4.0, 2.0, 10.0, 4.0]
st_weight = [5, 8, 1, 2]
st_power = [0.0, 0.0, 0.0, 0.0]
cap = 0
n = 0
br = 0
init_cap = 0
remain_cap = 0

if __name__ == '__main__':
    init_cap = cap = 16.0
    while cap > 0:
        for i in range(0, len(st_demand)):
            if st_power[i] < st_demand[i]:
                n += st_weight[i]
        br = cap / n
        cap = 0
        n=0
        for i in range(0, len(st_demand)):
            if st_power[i] < st_demand[i]:
                st_power[i] += (br * st_weight[i])

                if st_power[i] > st_demand[i]:
                    cap += (st_power[i] - st_demand[i])
                    st_power[i] = st_demand[i]

    print st_power

Reference: