list(map(parse, s.split('\t'))) for s in ballots_data.split('\n') if s
]
print(ballots_marks)

ballots_marks_temp = [[3, 1, 2], [3, 1, 2], [3, 2, 1]]


def to_ballot(array):
    a = [x[0] for x in sorted(zip(candidates, array), key=lambda x: -x[1])]
    return {"ballot": [x for x in a]}


def to_ballot_list(array):
    a = [x[0] for x in sorted(zip(candidates, array), key=lambda x: -x[1])]
    return {"ballot": [[x] for x in a]}


from pyvotecore.schulze_method import SchulzeMethod
from pyvotecore.schulze_stv import SchulzeSTV
from pyvotecore.condorcet import CondorcetHelper
#a = SchulzeMethod(list(map(to_ballot_list, ballots_marks)), ballot_notation = CondorcetHelper.BALLOT_NOTATION_GROUPING).as_dict()
#print(a)
#b = STV(list(map(to_ballot, ballots_marks)), required_winners=2).as_dict()
#print(b)
c = SchulzeSTV(list(map(to_ballot_list, ballots_marks)),
               required_winners=6,
               ballot_notation=SchulzeSTV.BALLOT_NOTATION_GROUPING).as_dict()
print(c)
d = STV(list(map(to_ballot, ballots_marks)), required_winners=6).as_dict()
print(d)
Example #2
0
def initiate_nextphase(consensus):
    logger = initiate_nextphase.get_logger()
    logger.info('Initiating Next Phase for: {0}'.format(
        consensus.content_object.summary))

    consensus.phase.curphase = consensus.phase.curphase.nextphase
    consensus.phasename = consensus.phase.curphase.phasename

    mygroups = MyGroup.objects.filter(topic=consensus.content_object.parent)
    num_members = mygroups.count()

    if consensus.phase.curphase.nextphase == None:
        #get the group settings
        settings, is_new = GroupSettings.objects.get_or_create(
            topic=consensus.content_object.parent)
        #iterate decisions made
        consensus.content_object.parent.decisions += 1
        consensus.content_object.parent.save()
        #if this question does not pass consensus we do not accept, however ignore reporting
        #this gives people an opportunity to not agree with the need for the question itself
        consensus.consensus_percent = get_consensus(consensus)
        consensus.reporting_percent = float(
            UpDownVote.objects.filter(
                parent=consensus).count()) / float(num_members)
        cons_passed = test_if_passes(consensus.consensus_percent,
                                     consensus.reporting_percent,
                                     settings,
                                     ignore_reporting=False)

        winner = []
        passes = False
        #if we accept all winners no need for ranking
        if consensus.winners is not None:
            #get nominations and ranked votes
            nominations = Consensus.objects.filter(
                parent_pk=consensus.content_object.pk)
            #currently supports single winner, in the future we check here for multiple winner or single winner
            confirmed = ConfirmRankedVote.objects.filter(parent=consensus,
                                                         confirm=True)
            ballot_dict = defaultdict(int)
            user_has_ranked = []
            for conf in confirmed:
                user_has_ranked.append(conf.user)
                rv = tuple([
                    i.nom_cons.pk for i in RankedVote.objects.filter(
                        user=conf.user, parent=consensus).order_by(
                            'ranked_vote')
                ])
                ballot_dict[rv] += 1
            #for those that didnt rank vote, we can sample from their updownvotes
            for user in [
                    i.user for i in UpDownVote.objects.filter(parent=consensus)
            ]:
                if user not in user_has_ranked:
                    user_ranks = []
                    print nominations
                    for nom in nominations:
                        try:
                            vote = UpDownVote.objects.get(parent=nom,
                                                          user=user)
                            user_ranks.append(vote)
                        except:
                            print 'novote: ' + str(nom)
                    user_ranks = sorted(user_ranks, key=lambda x: x.vote)
                    user_ranks.reverse()
                    rv = tuple([i.parent.pk for i in user_ranks])
                    ballot_dict[rv] += 1

            #load up the vote dict for python-vote-core
            blist = []
            for k, v in ballot_dict.items():
                ballot = [[i] for i in k]
                if ballot != []:
                    blist.append({'count': v, 'ballot': ballot})
            print 'calc schulze'
            #right now there is only single winner schulze, add mechanism in for multi later on
            noms_passed = False
            if blist != []:
                #scz = SchulzeMethod(blist, ballot_notation="grouping").as_dict()
                scz = SchulzeSTV(blist,
                                 required_winners=consensus.winners,
                                 ballot_notation="grouping").as_dict()
                print scz
                schulze_winners = scz['winners']
                #make sure it passes consensus also
                for nom in nominations:
                    nom.consensus_percent = get_consensus(nom)
                    nom.reporting_percent = float(
                        UpDownVote.objects.filter(
                            parent=nom).count()) / float(num_members)
                    nom.save()
                    noms_passed = test_if_passes(nom.consensus_percent,
                                                 nom.reporting_percent,
                                                 settings,
                                                 ignore_reporting=True)
                    if noms_passed == True and nom.pk in schulze_winners:
                        passes = True
                        winner.append(nom.pk)
                        print 'set winner via schulze and passing'
            #there was no ranked winner or the ranked winner failed to consense (weird side case), cycle through all and choose
        if passes == False:
            #if this is None, accept all winners
            if consensus.winners == None:
                num_winners = len(nominations)
            else:
                num_winners = consensus.winners
            consensii = []
            for nom in nominations:
                val = (get_consensus(nom), nom)
                consensii.append(val)
                nom.consensus_percent = val[0]
                nom.reporting_percent = float(
                    UpDownVote.objects.filter(
                        parent=nom).count()) / float(num_members)
                nom.save()
            consensii = sorted(consensii, key=lambda x: x[0])
            consensii.reverse()
            for nom_cons, nom in consensii[0:num_winners]:
                ##calculate reporting percentage, the best is the winner
                noms_passed = test_if_passes(nom_cons,
                                             nom.reporting_percent,
                                             settings,
                                             ignore_reporting=True)
                if noms_passed:
                    winner.append(nom.pk)
                    passes = True
                    print 'noms passed ' + str(noms_passed)
        #if we still haven't
        if passes == True and cons_passed == True:
            consensus.phasename = 'pass'
        else:
            consensus.phasename = 'fail'

        #what to do if there is no winner?
        #decision failed, no one voted in time
        rd = RankedDecision(passed=passes and cons_passed,
                            winner=winner,
                            parent=consensus,
                            consensus_percent=consensus.consensus_percent,
                            reporting_percent=consensus.reporting_percent,
                            submit_date=datetime.datetime.now(),
                            algorithm='Schulze Method Single Winner')
        rd.save()

        consensus.phase.complete = True
        consensus.phase.active = False
    else:
        initiate_nextphase.apply_async(args=[consensus],
                                       eta=consensus.phase.decision_dt)

    consensus.phase.save()
    consensus.save()

    logger.info('Next Phase Transition {0} completed'.format(
        consensus.content_object.summary))
    def test_part_2_of_5_example(self):

        # Generate data
        input = [
            {
                "count": 60,
                "ballot": [["a"], ["b"], ["c"], ["d"], ["e"]]
            },
            {
                "count": 45,
                "ballot": [["a"], ["c"], ["e"], ["b"], ["d"]]
            },
            {
                "count": 30,
                "ballot": [["a"], ["d"], ["b"], ["e"], ["c"]]
            },
            {
                "count": 15,
                "ballot": [["a"], ["e"], ["d"], ["c"], ["b"]]
            },
            {
                "count": 12,
                "ballot": [["b"], ["a"], ["e"], ["d"], ["c"]]
            },
            {
                "count": 48,
                "ballot": [["b"], ["c"], ["d"], ["e"], ["a"]]
            },
            {
                "count": 39,
                "ballot": [["b"], ["d"], ["a"], ["c"], ["e"]]
            },
            {
                "count": 21,
                "ballot": [["b"], ["e"], ["c"], ["a"], ["d"]]
            },
            {
                "count": 27,
                "ballot": [["c"], ["a"], ["d"], ["b"], ["e"]]
            },
            {
                "count": 9,
                "ballot": [["c"], ["b"], ["a"], ["e"], ["d"]]
            },
            {
                "count": 51,
                "ballot": [["c"], ["d"], ["e"], ["a"], ["b"]]
            },
            {
                "count": 33,
                "ballot": [["c"], ["e"], ["b"], ["d"], ["a"]]
            },
            {
                "count": 42,
                "ballot": [["d"], ["a"], ["c"], ["e"], ["b"]]
            },
            {
                "count": 18,
                "ballot": [["d"], ["b"], ["e"], ["c"], ["a"]]
            },
            {
                "count": 6,
                "ballot": [["d"], ["c"], ["b"], ["a"], ["e"]]
            },
            {
                "count": 54,
                "ballot": [["d"], ["e"], ["a"], ["b"], ["c"]]
            },
            {
                "count": 57,
                "ballot": [["e"], ["a"], ["b"], ["c"], ["d"]]
            },
            {
                "count": 36,
                "ballot": [["e"], ["b"], ["d"], ["a"], ["c"]]
            },
            {
                "count": 24,
                "ballot": [["e"], ["c"], ["a"], ["d"], ["b"]]
            },
            {
                "count": 3,
                "ballot": [["e"], ["d"], ["c"], ["b"], ["a"]]
            },
        ]
        output = SchulzeSTV(
            input,
            required_winners=3,
            ballot_notation=SchulzeSTV.BALLOT_NOTATION_GROUPING).as_dict()

        # Run tests
        self.assertEqual(output['winners'], set(['a', 'd', 'e']))