Commit 7521c0c1 by ziho

Merge branch 'master' of http://62.234.201.16/hzhao/elo-rating

parents eaa8837a 47248c8d
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import random\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class Player:\n",
" def __init__(self,name,rating):\n",
" self.name=name\n",
" self.rating=rating\n",
" self.wins=0\n",
" self.losses=0\n",
" self.draw=0\n",
" self.num_game=0\n",
" \n",
"\n",
"class EloRatingSystem:\n",
" WIN=1\n",
" LOSS=0\n",
" DRAW=0.5\n",
" def __init__(self,base_rating=1500,recordSaveFile='gameRecord.txt'):\n",
" self.base_rating=base_rating\n",
" self.players={}\n",
" \n",
" self.saveFile=recordSaveFile\n",
" \n",
" self.readFlag=False\n",
" \n",
" def addModel(self,name):\n",
" p=Player(name,self.base_rating)\n",
" self.players[name]=p\n",
" return p\n",
" \n",
" def addModels(self,models):\n",
" for m in models:\n",
" self.addModel(m)\n",
" print('add model to system:{}'.format(models))\n",
" \n",
" def check(self,name,online=True):\n",
" if name not in self.players:\n",
" if online:\n",
" print('{} not in player list,please use <addmodel> to add it'.format(name))\n",
" return False\n",
" return True\n",
" \n",
"\n",
" def playgame(self,p1,p2,winrate,numgames=1,online=True):\n",
" '''\n",
" result [int]: \n",
" 假设没有平局,赢了算1,输了算0,平局是0.5\n",
" '''\n",
" self.readFlag=True\n",
" if not self.check(p1,online) or not self.check(p2,online):\n",
" return\n",
" \n",
" if online:\n",
" #只是避免把文件里读出来的再写回去\n",
" with open(self.saveFile,'a') as f:\n",
" f.write('{},{},{},{}\\n'.format(p1,p2,winrate,numgames))\n",
" \n",
" player1=self.players[p1]\n",
" player2=self.players[p2]\n",
" \n",
" p1_win=int(numgames*winrate)\n",
" p2_win=numgames-p1_win\n",
"\n",
" player1.wins+=p1_win\n",
" player2.losses+=p1_win\n",
" player2.wins+=p2_win\n",
" player1.losses+=p2_win\n",
" player1.num_game+=numgames\n",
" player2.num_game+=numgames\n",
" \n",
" R1=player1.rating\n",
" R2=player2.rating \n",
" \n",
" def expectScore(rating1,rating2):\n",
" #base on https://en.wikipedia.org/wiki/Elo_rating_system\n",
" #same function as E1=1/(1+10**((rating1-rating2)/400))\n",
" Q1=10**(rating1/400)\n",
" Q2=10**(rating2/400)\n",
" E1=Q1/(Q1+Q2)\n",
" E2=Q2/(Q1+Q2)\n",
" return E1,E2\n",
" \n",
" def choose_k(rating):\n",
" #参考FIDE:https://gobase.org/studying/articles/elo/\n",
" #另有EGD规则:http://europeangodatabase.eu/EGD/EGF_rating_system.php\n",
" if rating<2000:\n",
" return 30\n",
" elif rating>2400:\n",
" return 10\n",
" else:\n",
" return 130-rating/20\n",
" \n",
" \n",
" E1,E2=expectScore(R1,R2)\n",
" \n",
" k=choose_k(R1)\n",
" player1.rating=R1+k*(winrate-E1)\n",
" k=choose_k(R2)\n",
" player2.rating=R2+k*(1-winrate-E2)\n",
" \n",
" if player1.rating<0:\n",
" player1.rating=50\n",
" elif player2.rating<0:\n",
" player2.rating=50\n",
" \n",
" if online:\n",
" #print('{}\\'s rating:{}->{} ; {}\\'s rating:{}->{}'.format(p1,R1,player1.rating,p2,R2,player2.rating))\n",
" pass \n",
" \n",
" def readRecords(self,filename):\n",
" if self.readFlag:\n",
" print('[warning] system is running! will not do anything')\n",
" return\n",
" self.readFlag=True\n",
" with open(filename,'r') as f:\n",
" lines=f.readlines()\n",
" for l in lines:\n",
" record=l.split(',')\n",
" self.playgame(record[0],record[1],float(record[2]),int(record[3]),False)\n",
" self.summary()\n",
" \n",
" def summary(self):\n",
" players=list(self.players.values())\n",
" def sortKey(p):\n",
" return p.rating\n",
" players.sort(key=sortKey,reverse=True)\n",
" \n",
" print('{:<10s}{:<10s}{:<10s}{:<10s}{:<10s}'.format('model','rating','games','wins','losses'))\n",
" for p in players:\n",
" print('{:<10s}{:<10.2f}{:<10d}{:<10d}{:<10d}'.format(str(p.name),p.rating,p.num_game,p.wins,p.losses))\n",
" \n",
" def getPlayers(self,sortByRank=False):\n",
" players=list(self.players.values())\n",
" if sortByRank: \n",
" def sortKey(p):\n",
" return p.rating\n",
" players.sort(key=sortKey,reverse=True)\n",
" return players \n",
" \n",
" def getRating(self):\n",
" return [p.rating for p in list(self.players.values())]\n",
" \n",
" def getNearPlayer(self,name):\n",
" #获取同等级的对手,以供匹配,相差200分以内吧\n",
" res=[]\n",
" if not self.check(name):\n",
" return\n",
" R=self.players[name].rating\n",
" for p in self.players.values():\n",
" if abs(p.rating-R)<200 and p.name!=name:\n",
" res.append(p.name)\n",
" if len(res)==0:\n",
" return None\n",
" return res\n",
" \n",
" "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"models=[str(i) for i in range (0,50000,1000)]\n",
"models\n",
"\n",
"def pk(model1,model2,num_games):\n",
" winrate=1-0.5**(abs(int(model1)-int(model2))/1000) #假设新模型以一定概率战胜旧模型\n",
" res=random.choices([elo.WIN,elo.DRAW,elo.LOSS],weights=[winrate,0,1-winrate],k=1) \n",
" if int(model1)>int(model2):\n",
" return res[0]\n",
" else:\n",
" return 1-res[0]"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"add model to system:['0', '1000', '2000', '3000', '4000', '5000', '6000', '7000', '8000', '9000', '10000', '11000', '12000', '13000', '14000', '15000', '16000', '17000', '18000', '19000', '20000', '21000', '22000', '23000', '24000', '25000', '26000', '27000', '28000', '29000', '30000', '31000', '32000', '33000', '34000', '35000', '36000', '37000', '38000', '39000', '40000', '41000', '42000', '43000', '44000', '45000', '46000', '47000', '48000', '49000']\n",
"model rating games wins losses \n",
"0 1500.00 0 0 0 \n",
"1000 1500.00 0 0 0 \n",
"2000 1500.00 0 0 0 \n",
"3000 1500.00 0 0 0 \n",
"4000 1500.00 0 0 0 \n",
"5000 1500.00 0 0 0 \n",
"6000 1500.00 0 0 0 \n",
"7000 1500.00 0 0 0 \n",
"8000 1500.00 0 0 0 \n",
"9000 1500.00 0 0 0 \n",
"10000 1500.00 0 0 0 \n",
"11000 1500.00 0 0 0 \n",
"12000 1500.00 0 0 0 \n",
"13000 1500.00 0 0 0 \n",
"14000 1500.00 0 0 0 \n",
"15000 1500.00 0 0 0 \n",
"16000 1500.00 0 0 0 \n",
"17000 1500.00 0 0 0 \n",
"18000 1500.00 0 0 0 \n",
"19000 1500.00 0 0 0 \n",
"20000 1500.00 0 0 0 \n",
"21000 1500.00 0 0 0 \n",
"22000 1500.00 0 0 0 \n",
"23000 1500.00 0 0 0 \n",
"24000 1500.00 0 0 0 \n",
"25000 1500.00 0 0 0 \n",
"26000 1500.00 0 0 0 \n",
"27000 1500.00 0 0 0 \n",
"28000 1500.00 0 0 0 \n",
"29000 1500.00 0 0 0 \n",
"30000 1500.00 0 0 0 \n",
"31000 1500.00 0 0 0 \n",
"32000 1500.00 0 0 0 \n",
"33000 1500.00 0 0 0 \n",
"34000 1500.00 0 0 0 \n",
"35000 1500.00 0 0 0 \n",
"36000 1500.00 0 0 0 \n",
"37000 1500.00 0 0 0 \n",
"38000 1500.00 0 0 0 \n",
"39000 1500.00 0 0 0 \n",
"40000 1500.00 0 0 0 \n",
"41000 1500.00 0 0 0 \n",
"42000 1500.00 0 0 0 \n",
"43000 1500.00 0 0 0 \n",
"44000 1500.00 0 0 0 \n",
"45000 1500.00 0 0 0 \n",
"46000 1500.00 0 0 0 \n",
"47000 1500.00 0 0 0 \n",
"48000 1500.00 0 0 0 \n",
"49000 1500.00 0 0 0 \n"
]
}
],
"source": [
"elo=EloRatingSystem()\n",
"elo.addModels(models)\n",
"elo.summary()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"model rating games wins losses \n",
"48000 2420.39 698 506 192 \n",
"49000 2418.49 670 502 168 \n",
"47000 2363.03 780 482 298 \n",
"46000 2264.49 850 488 362 \n",
"45000 2215.11 762 444 318 \n",
"44000 2185.74 798 462 336 \n",
"43000 2170.56 818 470 348 \n",
"42000 2091.00 680 410 270 \n",
"40000 2032.70 778 440 338 \n",
"41000 2029.70 782 448 334 \n",
"39000 2002.24 768 426 342 \n",
"38000 1926.60 818 450 368 \n",
"36000 1923.38 782 436 346 \n",
"37000 1916.76 808 438 370 \n",
"35000 1827.42 770 424 346 \n",
"33000 1810.02 814 442 372 \n",
"34000 1767.18 814 424 390 \n",
"32000 1737.48 798 428 370 \n",
"31000 1731.06 750 396 354 \n",
"30000 1730.33 810 428 382 \n",
"29000 1621.78 800 408 392 \n",
"27000 1616.15 740 378 362 \n",
"28000 1570.02 836 424 412 \n",
"25000 1537.03 810 410 400 \n",
"24000 1533.98 832 426 406 \n",
"26000 1527.41 794 398 396 \n",
"23000 1460.27 812 402 410 \n",
"22000 1417.07 864 422 442 \n",
"20000 1343.24 862 404 458 \n",
"21000 1333.34 830 392 438 \n",
"19000 1319.81 850 412 438 \n",
"18000 1286.31 816 380 436 \n",
"17000 1265.46 832 404 428 \n",
"16000 1263.20 800 376 424 \n",
"14000 1195.94 836 382 454 \n",
"15000 1153.36 816 380 436 \n",
"12000 1114.91 754 338 416 \n",
"13000 1083.15 782 350 432 \n",
"11000 1067.94 830 368 462 \n",
"10000 972.21 782 358 424 \n",
"9000 960.96 880 388 492 \n",
"7000 908.83 812 348 464 \n",
"8000 881.56 900 402 498 \n",
"6000 762.80 832 338 494 \n",
"5000 735.52 812 338 474 \n",
"4000 688.69 816 326 490 \n",
"2000 638.93 788 304 484 \n",
"3000 566.54 826 328 498 \n",
"1000 460.25 820 292 528 \n",
"0 435.00 600 136 464 \n"
]
}
],
"source": [
"for i in range(5000): \n",
" players=elo.getPlayers(sortByRank=True) #选择分数相近的作为比赛对手\n",
" black=random.choice(players).name\n",
" matchList=elo.getNearPlayer(black)\n",
" if matchList: \n",
" white=random.choice(matchList)\n",
" else:\n",
" continue #谁都打不过,或者谁都打不过\n",
" \n",
" num=2\n",
" winrate=pk(black,white,num) #就比一局\n",
" elo.playgame(black,white,winrate,numgames=num)\n",
"\n",
"elo.summary()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"add model to system:['0', '1000', '2000', '3000', '4000', '5000', '6000', '7000', '8000', '9000', '10000', '11000', '12000', '13000', '14000', '15000', '16000', '17000', '18000', '19000', '20000', '21000', '22000', '23000', '24000', '25000', '26000', '27000', '28000', '29000', '30000', '31000', '32000', '33000', '34000', '35000', '36000', '37000', '38000', '39000', '40000', '41000', '42000', '43000', '44000', '45000', '46000', '47000', '48000', '49000']\n",
"model rating games wins losses \n",
"48000 2420.39 698 506 192 \n",
"49000 2418.49 670 502 168 \n",
"47000 2363.03 780 482 298 \n",
"46000 2264.49 850 488 362 \n",
"45000 2215.11 762 444 318 \n",
"44000 2185.74 798 462 336 \n",
"43000 2170.56 818 470 348 \n",
"42000 2091.00 680 410 270 \n",
"40000 2032.70 778 440 338 \n",
"41000 2029.70 782 448 334 \n",
"39000 2002.24 768 426 342 \n",
"38000 1926.60 818 450 368 \n",
"36000 1923.38 782 436 346 \n",
"37000 1916.76 808 438 370 \n",
"35000 1827.42 770 424 346 \n",
"33000 1810.02 814 442 372 \n",
"34000 1767.18 814 424 390 \n",
"32000 1737.48 798 428 370 \n",
"31000 1731.06 750 396 354 \n",
"30000 1730.33 810 428 382 \n",
"29000 1621.78 800 408 392 \n",
"27000 1616.15 740 378 362 \n",
"28000 1570.02 836 424 412 \n",
"25000 1537.03 810 410 400 \n",
"24000 1533.98 832 426 406 \n",
"26000 1527.41 794 398 396 \n",
"23000 1460.27 812 402 410 \n",
"22000 1417.07 864 422 442 \n",
"20000 1343.24 862 404 458 \n",
"21000 1333.34 830 392 438 \n",
"19000 1319.81 850 412 438 \n",
"18000 1286.31 816 380 436 \n",
"17000 1265.46 832 404 428 \n",
"16000 1263.20 800 376 424 \n",
"14000 1195.94 836 382 454 \n",
"15000 1153.36 816 380 436 \n",
"12000 1114.91 754 338 416 \n",
"13000 1083.15 782 350 432 \n",
"11000 1067.94 830 368 462 \n",
"10000 972.21 782 358 424 \n",
"9000 960.96 880 388 492 \n",
"7000 908.83 812 348 464 \n",
"8000 881.56 900 402 498 \n",
"6000 762.80 832 338 494 \n",
"5000 735.52 812 338 474 \n",
"4000 688.69 816 326 490 \n",
"2000 638.93 788 304 484 \n",
"3000 566.54 826 328 498 \n",
"1000 460.25 820 292 528 \n",
"0 435.00 600 136 464 \n"
]
}
],
"source": [
"#从比赛记录中读取\n",
"#每一行是一条记录: \n",
"#黑棋,白棋,胜率,比赛场次\n",
"\n",
"elo=EloRatingSystem()\n",
"elo.addModels(models)\n",
"elo.readRecords('gameRecord.txt')"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x261ff1ebeb8>]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"import matplotlib\n",
"import matplotlib.pyplot as plt\n",
"plt.plot([int(m) for m in models],[int(r) for r in elo.getRating()])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "py3(myenv)",
"language": "python",
"name": "base"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment