Hi! Found a bug in the previous, the ranking used d[] instead of p[]. It is fixed. This version also displays p[n-1,n] vs p[n, n-1] to show how serious the beat is, but I cannot interpret it. What does it actually mean? :)
2010/4/25 Árpád Magosányi <[email protected]> > Hi! > > Here is a Schulze implementation, written in python, using gtk. > Please someone confirm whether the last step of ranking candidates done > correctly. It is in class Result, function compute. > It gives correct result for the Tennessee example, but I am not sure. > > It is specifically written for situations like a village meeting: lot of > people, one computer, and the result should be known instantly. > Voting is done by directly asking for relative preferences, so pairwise > matrix is entered directly. > In config tab you can give the number of candidates (default=5) > In vote tab you give the names, and the pairwise matrix. The matrix gives > the number of voters who preferred the candidate listed in the row caption > to the candidate in the row corresponding to the column. > Clicking on the result tab gives the ranking of the candidates. > >
#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright [email protected] GNU GPL import pygtk pygtk.require('2.0') import gtk import pango class Hello: def hello(self,widget,data=None): print "hello" def delete_event(self,widget,event,data=None): return False def destroy(self,widget,data=None): gtk.main_quit() def __init__(self,children): self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.connect("delete_event", self.delete_event) self.window.connect("destroy", self.destroy) self.window.set_border_width(10) self.notebook = gtk.Notebook() self.window.add(self.notebook) self.notebook.show() self.window.show() self.children=children for w,n in children: self.add(w.widget,n) def main(self): gtk.main() def add(self,widget,name): self.notebook.add(widget) self.notebook.set_tab_label_text(widget,name) widget.show() class Config: def __init__(self,slave): self.slave=slave self.widget=gtk.HBox() self.label=gtk.Label("mennyi") self.widget.add(self.label) self.entry=gtk.Entry() self.entry.insert_text('5') self.widget.add(self.entry) self.button=gtk.Button("Legyen") self.button.connect('clicked',self.config,None) self.widget.add(self.button) self.label.show() self.entry.show() self.button.show() def config(self,widget,data=None): ns=self.entry.get_chars(0,-1) if ns == '': ns = '0' n=int(ns) print ns,n self.slave.config(n) class Entries: def __init__(self, number=5): self.number=number self.widget=gtk.Table(rows=number,columns=number+1) self.populate() self.widget.show() def populate(self,fr=0): fd=pango.FontDescription("Sans 20") self.children=[] for i in range(fr,self.number): cs=[] e=gtk.Entry() e.modify_font(fd) cs.append(e) e.set_property("width-chars",30) e.show() self.widget.attach(e,0,1,i,i+1) for j in range(fr,self.number): if i == j: e=gtk.Label(' - ') else: e=gtk.Entry() e.set_property("width-chars",3) cs.append(e) e.modify_font(fd) e.show() self.widget.attach(e,1+j,2+j,i,i+1,xoptions=0) self.children.append(cs) def harvest(self): l=[] for i in self.children: ll=[] for j in i: if j.__class__ == gtk.Label: ll.append("0") else: ll.append(j.get_chars(0,-1)) l.append(ll) return l def config(self,num): l=self.harvest() parent=self.widget.parent self.widget.destroy() self.number=num self.widget=gtk.Table(rows=self.number,columns=self.number+1) self.populate() x=0 for i in l[:self.number]: y=0 for j in i[:self.number+1]: k=self.children[x][y] if k.__class__ != gtk.Label: k.insert_text(j) y += 1 x += 1 parent.add(self.widget) parent.set_tab_label_text(self.widget,'vote') self.widget.show() class Result: def __init__(self,entries): self.widget=gtk.Label("ide jon\n az eredmeny") fd=pango.FontDescription("Sans 20") self.widget.modify_font(fd) self.widget.connect('map',self.compute,None) self.entries=entries def printmat(self,m): l=[] for i in range(len(self.candidates)): ll=[] for j in range(len(self.candidates)): if i == j: ll.append('-') else: ll.append('%s'%m[i,j]) l.append(','.join(ll)) print '\n'.join(l) def compute(self,widget,data=None): self.widget.set_text('computing result') self.getdata() self.floyd_warshall() print self.candidates self.printmat(self.d) self.printmat(self.p) C = len(self.candidates) winners=[] hasnew = True while hasnew: hasnew = False for i in range(C): if i not in winners: isnew = True for j in range(C): if j not in winners: if i != j: if self.p[i,j] < self.p[j,i]: isnew = False if isnew: winners.append(i) hasnew = True print winners s="" for i in range(len(winners)): s += self.candidates[winners[i]] if i > 0: s += ",by %s:%s"%(self.p[winners[i],winners[i-1]],self.p[winners[i-1],winners[i]]) s += "\n" print s self.widget.set_text(s) def getdata(self): l=self.entries.harvest() candidates=[] d={} x=0 for line in l: candidates.append(line[0]) y=0 for pr in line[1:]: if pr == '': pr = '0' d[x,y]=int(pr) y+=1 x+=1 self.candidates=candidates self.d=d def floyd_warshall(self): candidates=self.candidates C=len(candidates) d=self.d p={} for i in range(C): for j in range(C): if i != j: if d[i,j] > d[j,i]: p[i,j] = d[i,j] else: p[i,j] = 0 for i in range(C): for j in range(C): if i != j: for k in range(C): if i != k: if j != k: p[j,k] = max(p[j,k],min(p[j,i],p[i,k])) self.p = p def main(go=False): e=Entries() c=Config(e) r=Result(e) hello = Hello([(c,'config'),(e,'vote'),(r,"result")]) if go: hello.main() return hello if __name__ == "__main__": main(True)
---- Election-Methods mailing list - see http://electorama.com/em for list info
