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")
        self.widget.connect('map',self.compute,None)
        self.entries=entries

    def compute(self,widget,data=None):
        self.widget.set_text('computing result')
        self.getdata()
        self.floyd_warshall()
        print self.candidates
        print self.d
        print 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.d[i,j] < self.d[j,i]:
                                    isnew = False
                    if isnew:
                        winners.append(i)
                        hasnew = True
        print winners
        s=""
        for i in winners:
            s += self.candidates[i]+'\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

Reply via email to