-
Notifications
You must be signed in to change notification settings - Fork 0
/
borda.py
174 lines (142 loc) · 5.92 KB
/
borda.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import numpy as np
import matplotlib as plt
import csv
from sys import argv
class Player:
def __init__(self):
self.preferences = []
self.choice = []
def getPref(self):
return self.preferences
def setPref(self,pref):
self.preferences = list(pref)
def utilityCandidate(self,i): #Calculates player's utility for i-th candidate
return len(self.preferences)-self.preferences.index(i)
def calculateResult(self,choices):
m = len(self.preferences)
result = [0 for i in range(m)]
for i in range(len(choices)):
for j in range(m):
result[choices[i][j]] += (m-j-1) # borda rule score
return result
def canChange(self,choices,i): # returns change to increase utility (or nothing)
result = self.calculateResult(choices) # results of starting choices
winner = result.index(max(result)) # winner of starting choices
inChoice = choices[i]
if winner == inChoice[0]: # skip players that their choice is winning
return inChoice
m = len(self.preferences)-1
choice = choices[i][:]
others = choice[1:] # every candidate except wanted winner
othersScores = [result[j] for j in others]
o = others[:] # duplicate others list for key function
others.sort(key = lambda j: othersScores[o.index(j)]) # sort others by score
othersScores.sort()
choice = choice[:1]+others
choices[i] = choice
newResult = self.calculateResult(choices) # results of new choices
newWinner = newResult.index(max(newResult)) # winner of new choices
if self.utilityCandidate(newWinner)>self.utilityCandidate(winner):
return choice
return inChoice
def csvToTable(csvName):
with open(csvName, 'r', encoding='utf-8-sig') as read_obj:
# Return a reader object which will
# iterate over lines in the given csvfile
csv_reader = csv.reader(read_obj)
# convert string to list
list_of_csv = list(csv_reader)
list_of_csv = [[int(i) for i in x] for x in list_of_csv]
return list_of_csv
def createRandomGame(n,m,seed):
lista = []
#lista = [[0, 2, 1, 3],[1, 0, 2, 3],[1, 0, 3, 2],[2, 0, 3, 1]]
for i in range(n):
lista.append(np.random.RandomState(seed+8*i).permutation(m))
return lista
def brd(game):
n,m = np.asarray(game).shape
players,choices = [],[]
for i in range(n):
players.append(Player())
players[i].setPref(game[i])
choices.append(players[i].getPref())
players[i].choice = choices[i]
resultStart = players[0].calculateResult(choices) # results of starting choices
print()
for t in range(1000):
isPlayer = False
for p in players:
i = players.index(p)
choice = p.choice
newChoice = p.canChange(choices[:],i) # changed (or not) choice
if choice != newChoice: # if choice is changed
p.choice = newChoice
choices[i] = newChoice
isPlayer = True
break # go to next round
if isPlayer == False: # no player wants to change
print("Nash Equilibrium, ended at",t,"iterations.")
print()
resultEnd = players[0].calculateResult(choices)
return choices, t, resultStart, resultEnd
print("Limit exceeded, nothing found",i)
def main(argv):
if argv[1] == "random":
n,m = int(argv[2]),int(argv[3])
game = createRandomGame(n,m,0)
choices = brd(game)
for i in range(len(choices[0])):
print(choices[0][i])
elif argv[1] == "csv":
game = csvToTable(argv[2])
choices = brd(game)
for i in range(len(choices[0])):
print(choices[0][i])
elif argv[1] == "test":
n_list = [5,10,20,40]
m_list = [5,10,15,20]
print("Testing for", str(n_list)[1:-1], "players")
print("and", str(m_list)[1:-1], "candidates")
choice_data = [[],[],[],[],[],[],[]]
for n in n_list:
for m in m_list:
for i in range(20):
game = createRandomGame(n,m,i)
choiceStart = game
c = brd(game) # output of brd
resultStart = c[2]
resultEnd = c[3]
winnerStart = resultStart.index(max(resultStart))
winnerEnd = resultEnd.index(max(resultEnd))
choice_data[0].append(n) # no. of players
choice_data[1].append(m) # no. of candidates
choice_data[2].append(c[2]) # starting choices
choice_data[3].append(c[0]) # final strategy
choice_data[4].append(winnerStart)
choice_data[5].append(winnerEnd)
choice_data[6].append(c[1]) # no. of iterations
# get data for report
#c,s,c2,s2 = 0,0,0,0
#for i in range(len(choice_data[6])):
# num = choice_data[6][i]
# c+=1
# s+=num
# if num != 0:
# c2+=1
# s2+=num
#print(s/c)
#print(s2/c2)
#
#c,s = 0,0
#for i in range(len(choice_data[2])):
# rStart = choice_data[2][i]
# wStart = choice_data[4][i]
# wEnd = choice_data[5][i]
# print(rStart[wEnd]-rStart[wStart], wStart, wEnd)
choice_out_data = np.array(choice_data,dtype=object).T.tolist()
with open("out.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerows(choice_out_data)
if __name__ == "__main__":
main(argv)