《社交網絡》裏的評分公式——ELO排名系統

  《社交網絡》裏的Mark Zackburg被女友甩後,在舍友的啓發下,充分發揮了技術宅男自娛自樂的惡搞天分,作出了Facemash網站,對學校女生的相貌進行排名打分,結果網站訪問流量過大,直接把學校網絡搞癱瘓了。Facemask大受歡迎的關鍵就在於Zackburg基友Eduardo寫在窗戶上的排名公式,看電影之時就對這個排名公式很是感興趣,上網瞭解下,才發現這條公式就是大名鼎鼎的ELO等級分制度ELO的應用很是普遍,大部分棋類比賽,如今流行的Moba遊戲,像11平臺的DOTA天梯系統,都是採用ELO等級分。算法

  之後作競技類的遊戲排行榜能夠用ELO來排名,更真實地反映玩家的實力。閒來無事,作了個flash的Facemask,挺有意思的。網絡

 

ELO的實現代碼app

package
{
    
    /**
     * Elo排名算法
     * @author ShuchangLiu
     */
    public class EloRating
    {
        public static const ELO_RESULT_WIN:int = 1;
        public static const ELO_RESULT_LOSS:int = -1;
        public static const ELO_RESULT_TIE:int = 0;
        
        public static const ELO_RATING_DEFAULT:int = 1500;
        
        protected var rating1:int;
        protected var rating2:int;
        protected var score1:Number;
        protected var score2:Number;
        
        public function EloRating(rating1:int = ELO_RATING_DEFAULT, rating2:int = ELO_RATING_DEFAULT):void
        {
            this.rating1 = rating1;
            this.rating2 = rating2;
        }
        
        /**
         * @param result ELO_RESULT_WIN or ELO_RESULT_LOSS or ELO_RESULT_TIE
         */        
        public function setResult(result:int):void {
            var cscore1:Number = computeScore(this.rating2, this.rating1);
            var cscore2:Number = computeScore(this.rating1, this.rating2);
            
            if (result == ELO_RESULT_WIN) {
                this.rating1 = this.rating1 + (computeK(this.rating1) * (1 - cscore1));
                this.rating2 = this.rating2 + (computeK(this.rating2) * (0 - cscore2));
            }else if(result == ELO_RESULT_LOSS) {
                this.rating1 = this.rating1 + (computeK(this.rating1) * (0 - cscore1));
                this.rating2 = this.rating2 + (computeK(this.rating2) * (1 - cscore2));
            }else{
                // Assume tie
                this.rating1 = this.rating1 + (computeK(this.rating1) * (0.5 - cscore1));
                this.rating2 = this.rating2 + (computeK(this.rating2) * (0.5 - cscore2));
            }
        }
        
        protected function computeScore($rating1:int, $rating2:int):Number {
            return (1 / (1 + Math.pow(10, ($rating1 - $rating2) / 400)));
        }
        
        protected function computeK(rating:int):int {
            if(rating>=2400){
                return 16;
            }else if(rating >= 2100){
                return 24;
            }else{
                return 36;
            }
        }
        
        /** A的獲勝指望*/
        public function getScore1():Number {
            this.score1 = computeScore(this.rating2, this.rating1);
            return this.score1;
        }
        
        /** B的獲勝指望*/
        public function getScore2():Number {
            this.score2 = computeScore(this.rating1, this.rating2);
            return this.score2;
        }
        
        /** A的排名等級*/
        public function getRating1():int {
            return this.rating1;
        }
        
        /** B的排名等級*/
        public function getRating2():int {
            return this.rating2;
        }
        
        
        
    }
}

 

ELO介紹網站

ELO等級分制度是指由匈牙利美國物理學家Elo建立的一個衡量各種對弈活動水平的評價方法,是當今對弈水平評估的公認的權威方法。被普遍用於國際象棋圍棋足球籃球等運動。網絡遊戲英雄聯盟魔獸世界內的競技對戰系統也採用此分級制度。this

歷史

ELO等級分制度是基於統計學的一個評估棋手水平的方法。美國國際象棋協會在1960年首先使用這種計分方法。因爲它比先前的方法更公平客觀,這種方法很快流行開來。1970年國際棋聯正式開始使用等級分制度。spa

Elo模型原先採用正態分佈。可是實踐顯明棋手的表現並不是呈正態分佈,因此如今的等級分計分系統一般使用的是Logistic distributioncode

計分方法

假設棋手A和B的當前等級分分別爲R_AR_B,則按Logistic distribution A對B的勝率指望值當爲htm

E_A = \frac 1 {1 + 10^{(R_B - R_A)/400}}.

相似B對A的勝率爲blog

E_B = \frac 1 {1 + 10^{(R_A - R_B)/400}}.

假如一位棋手在比賽中的真實得分S_A(勝=1分,和=0.5分,負=0分)和他的勝率指望值E_A不一樣,則他的等級分要做相應的調整。具體的數學公式爲遊戲

R_A^\prime = R_A + K(S_A - E_A).

公式中R_AR_A^\prime分別爲棋手調整先後的等級分。在大師級比賽中K一般爲16。

例如,棋手A等級分爲1613,與等級分爲1573的棋手B戰平。若K取32,則A的勝率指望值爲\frac 1 {1 + 10^{(1573 - 1613)/400}},約爲0.5573,於是A的新等級分爲1613 + 32 · (0.5 − 0.5573) = 1611.166

國際象棋中的等級分

國際象棋中,等級分和棋聯稱號的大體對應爲

  • 2500分以上:國際特級大師
  • 2400-2499分:國際大師
  • 2300-2399分:棋聯大師 

 

其餘參考:

ELO等級分計算公式詳解

相關文章
相關標籤/搜索