Example #1
0
  def countBallots(self):
    "Count the votes using Condorcet voting."

    # self.pMat[i][j]: number of votes ranking candidate i over candidate j
    self.computePMat()

    # Even though the Smith Set isn't needed for all completion methods
    # it provides interesting info, so compute it always.
    self.computeSmithSet()

    if len(self.smithSet) == 1:
      c0 = self.smithSet[0]
    else:
      # Do the completion
      if self.completion == "Schwartz Sequential Dropping":
        c0 = self.SchwartzSequentialDropping()
      elif self.completion in ["IRV on Smith Set", "Borda on Smith Set"]:
        # Copy ballots and get rid of candidates not in Smith set
        withdrawList = []
        for c in range(self.b.numCandidates):
          if (c not in self.smithSet):
            withdrawList.append(c)
        dirtyBallots = self.b.copy()
        dirtyBallots.withdrawn = withdrawList
        dirtyBallots.numSeats = 1
        cleanBallots = dirtyBallots.getCleanBallots()
        if self.completion == "IRV on Smith Set":
          self.e = IRV(cleanBallots)
          self.e.strongTieBreakMethod = self.strongTieBreakMethod
          self.e.runElection()
        elif self.completion == "Borda on Smith Set":
          self.e = Borda(cleanBallots)
          self.e.strongTieBreakMethod = self.strongTieBreakMethod
          self.e.runElection()
        assert(len(self.e.winners) == 1)
        # The Smith set is sorted.  The winner just determined is the index
        # of the winner in the Smith set.
        cIndex = list(self.e.winners)[0]
        c0 = self.smithSet[cIndex]
      else:
        assert(0)

    self.winners = set([c0])
Example #2
0
    def countBallots(self):
        "Count the votes using Condorcet voting."

        # self.pMat[i][j]: number of votes ranking candidate i over candidate j
        self.computePMat()

        # Even though the Smith Set isn't needed for all completion methods
        # it provides interesting info, so compute it always.
        self.computeSmithSet()

        if len(self.smithSet) == 1:
            c0 = self.smithSet[0]
        else:
            # Do the completion
            if self.completion == "Schwartz Sequential Dropping":
                c0 = self.SchwartzSequentialDropping()
            elif self.completion in ["IRV on Smith Set", "Borda on Smith Set"]:
                # Copy ballots and get rid of candidates not in Smith set
                withdrawList = []
                for c in range(self.b.numCandidates):
                    if (c not in self.smithSet):
                        withdrawList.append(c)
                dirtyBallots = self.b.copy()
                dirtyBallots.withdrawn = withdrawList
                dirtyBallots.numSeats = 1
                cleanBallots = dirtyBallots.getCleanBallots()
                if self.completion == "IRV on Smith Set":
                    self.e = IRV(cleanBallots)
                    self.e.strongTieBreakMethod = self.strongTieBreakMethod
                    self.e.runElection()
                elif self.completion == "Borda on Smith Set":
                    self.e = Borda(cleanBallots)
                    self.e.strongTieBreakMethod = self.strongTieBreakMethod
                    self.e.runElection()
                assert (len(self.e.winners) == 1)
                # The Smith set is sorted.  The winner just determined is the index
                # of the winner in the Smith set.
                cIndex = list(self.e.winners)[0]
                c0 = self.smithSet[cIndex]
            else:
                assert (0)

        self.winners = set([c0])
Example #3
0
class Condorcet(NonIterative, MethodPlugin):
  "Implement Condorcet voting with several options for completion methods"
  
  methodName = "Condorcet"
  longMethodName = "Condorcet Voting"
  onlySingleWinner = True
  status = 1

  htmlBody = """
<p>Condorcet voting elects the candidate who wins all pairwise
elections against the other candidates.  In relatively rare
situations, a cycle will occur where no Condorcet winner exists (i.e.,
every candidte is beaten by at least one other candidate).  The set
of candidates in the cycle is called the Smith set.  In this instance,
a "completion method" is used to choose the winner from the Smith set.
There are three choices for the completion method:</p>

<ul>
<li> Schwartz sequential dropping
<li> Instant runoff voting on the Smith set
<li> Borda count on the Smith set
</ul>
"""

  htmlHelp = (MethodPlugin.htmlBegin % (longMethodName, longMethodName)) +\
             htmlBody + MethodPlugin.htmlEnd

  def __init__(self, b):
    NonIterative.__init__(self, b)
    MethodPlugin.__init__(self)

    self.completion = "Schwartz Sequential Dropping"
    self.createGuiOptions(["completionMethod"])
    self.e = None
    self.smithSet = []
    self.SSDinfo = ""
    self.pMat = []
    self.dMat = []
    
  def preCount(self):
    NonIterative.preCount(self)

    assert(self.completion in ["Schwartz Sequential Dropping",
                               "IRV on Smith Set",
                               "Borda on Smith Set"])

    self.optionsMsg = "Using %s for the completion method." % self.completion

  def computePMat(self):
    "Compute the pairwise comparison matrix."

    # Intialize space
    self.pMat = []
    for c in range(self.b.numCandidates):
      self.pMat.append([0] * self.b.numCandidates)

    # Compute pMat
    for i in xrange(self.b.numWeightedBallots):
      weight, ballot = self.b.getWeightedBallot(i)
      remainingC = range(self.b.numCandidates)
      for c in ballot:
        remainingC.remove(c)
        for d in remainingC:
          self.pMat[c][d] += weight

  def computeSmithSet(self):
    "Compute the Smith set."

    dMat = []
    for c in range(self.b.numCandidates):
      dMat.append([0] * self.b.numCandidates)

    # compute the Smith set
    # Adapted from code posted by Markus Schulze at
    # http://groups.yahoo.com/group/election-methods-list/message/6493
    self.smithSet = range(self.b.numCandidates)
    for c in range(self.b.numCandidates):
      for d in range(self.b.numCandidates):
        if c != d:
          if self.pMat[c][d] >= self.pMat[d][c]:
            dMat[c][d] = True
          else:
            dMat[c][d] = False
    for c in range(self.b.numCandidates):
      for d in range(self.b.numCandidates):
        if c != d:
          for k in range(self.b.numCandidates):
            if c != k and d != k:
              if dMat[d][c] and dMat[c][k]:
                dMat[d][k] = True
    for c in range(self.b.numCandidates):
      for d in range(self.b.numCandidates):
        if c != d:
          if ( (not dMat[c][d]) and
               dMat[d][c] and
               (c in self.smithSet) ):
            self.smithSet.remove(c)
    self.smithSet.sort()

  def SchwartzSequentialDropping(self):
    "Complete with SSD."

    # Initialize the defeats matrix: dMat[i][j] gives the magnitude of i's
    # defeat of j. If i doesn't defeat j, then dMat[i][j] == 0.
    self.dMat = []
    for c in range(self.b.numCandidates):
      self.dMat.append([0] * self.b.numCandidates)

    for c in range(self.b.numCandidates):
      for d in range(self.b.numCandidates):
        self.dMat[c][d] = self.pMat[c][d]
    for c in range(self.b.numCandidates):
      for d in range(c):
        if self.pMat[c][d] > self.pMat[d][c]: 
          self.dMat[d][c] = 0
        if self.pMat[c][d] < self.pMat[d][c]: 
          self.dMat[c][d] = 0
        if self.pMat[c][d] == self.pMat[d][c]: 
          self.dMat[c][d] = self.dMat[d][c] = 0

    # Determine "beatpath" magnitudes array: dMat[i][j] will be the
    # maximum beatpath magnitudes array. The i,j entry is the greatest
    # magnitude of any beatpath from i to j. A beatpath's magnitude is
    # the magnitude of its weakest defeat.

    changing = 1
    while changing:
      changing = 0
      for c in range(self.b.numCandidates):
        for d in range(self.b.numCandidates):
          for k in range(self.b.numCandidates):
            dmin = min (self.dMat[c][d], self.dMat[d][k])
            if self.dMat[c][k] < dmin:
              self.dMat[c][k] = dmin
              changing = 1

    ctng = range(self.b.numCandidates)[:]
    for c in ctng[:]:
      for d in ctng[:]:
        if self.dMat[d][c] > self.dMat[c][d] and c in ctng:
          ctng.remove(c)

    if len(ctng) > 1:
      ctng.sort()
      self.SSDinfo = """
Candidates remaining after SSD: %s

Tie broken randomly.""" % self.b.joinList(ctng)
      (c0, desc) = self.breakStrongTie(ctng)
    else:
      self.SSDinfo = ""
      c0 = ctng[0]

    return c0

  def countBallots(self):
    "Count the votes using Condorcet voting."

    # self.pMat[i][j]: number of votes ranking candidate i over candidate j
    self.computePMat()

    # Even though the Smith Set isn't needed for all completion methods
    # it provides interesting info, so compute it always.
    self.computeSmithSet()

    if len(self.smithSet) == 1:
      c0 = self.smithSet[0]
    else:
      # Do the completion
      if self.completion == "Schwartz Sequential Dropping":
        c0 = self.SchwartzSequentialDropping()
      elif self.completion in ["IRV on Smith Set", "Borda on Smith Set"]:
        # Copy ballots and get rid of candidates not in Smith set
        withdrawList = []
        for c in range(self.b.numCandidates):
          if (c not in self.smithSet):
            withdrawList.append(c)
        dirtyBallots = self.b.copy()
        dirtyBallots.withdrawn = withdrawList
        dirtyBallots.numSeats = 1
        cleanBallots = dirtyBallots.getCleanBallots()
        if self.completion == "IRV on Smith Set":
          self.e = IRV(cleanBallots)
          self.e.strongTieBreakMethod = self.strongTieBreakMethod
          self.e.runElection()
        elif self.completion == "Borda on Smith Set":
          self.e = Borda(cleanBallots)
          self.e.strongTieBreakMethod = self.strongTieBreakMethod
          self.e.runElection()
        assert(len(self.e.winners) == 1)
        # The Smith set is sorted.  The winner just determined is the index
        # of the winner in the Smith set.
        cIndex = list(self.e.winners)[0]
        c0 = self.smithSet[cIndex]
      else:
        assert(0)

    self.winners = set([c0])
Example #4
0
class Condorcet(NonIterative, MethodPlugin):
    "Implement Condorcet voting with several options for completion methods"

    methodName = "Condorcet"
    longMethodName = "Condorcet Voting"
    onlySingleWinner = True
    status = 1

    htmlBody = """
<p>Condorcet voting elects the candidate who wins all pairwise
elections against the other candidates.  In relatively rare
situations, a cycle will occur where no Condorcet winner exists (i.e.,
every candidte is beaten by at least one other candidate).  The set
of candidates in the cycle is called the Smith set.  In this instance,
a "completion method" is used to choose the winner from the Smith set.
There are three choices for the completion method:</p>

<ul>
<li> Schwartz sequential dropping
<li> Instant runoff voting on the Smith set
<li> Borda count on the Smith set
</ul>
"""

    htmlHelp = (MethodPlugin.htmlBegin % (longMethodName, longMethodName)) +\
               htmlBody + MethodPlugin.htmlEnd

    def __init__(self, b):
        NonIterative.__init__(self, b)
        MethodPlugin.__init__(self)

        self.completion = "Schwartz Sequential Dropping"
        self.createGuiOptions(["completionMethod"])
        self.e = None
        self.smithSet = []
        self.SSDinfo = ""
        self.pMat = []
        self.dMat = []

    def preCount(self):
        NonIterative.preCount(self)

        assert (self.completion in [
            "Schwartz Sequential Dropping", "IRV on Smith Set",
            "Borda on Smith Set"
        ])

        self.optionsMsg = "Using %s for the completion method." % self.completion

    def computePMat(self):
        "Compute the pairwise comparison matrix."

        # Intialize space
        self.pMat = []
        for c in range(self.b.numCandidates):
            self.pMat.append([0] * self.b.numCandidates)

        # Compute pMat
        for i in range(self.b.numWeightedBallots):
            weight, ballot = self.b.getWeightedBallot(i)
            remainingC = range(self.b.numCandidates)
            for c in ballot:
                remainingC.remove(c)
                for d in remainingC:
                    self.pMat[c][d] += weight

    def computeSmithSet(self):
        "Compute the Smith set."

        dMat = []
        for c in range(self.b.numCandidates):
            dMat.append([0] * self.b.numCandidates)

        # compute the Smith set
        # Adapted from code posted by Markus Schulze at
        # http://groups.yahoo.com/group/election-methods-list/message/6493
        self.smithSet = range(self.b.numCandidates)
        for c in range(self.b.numCandidates):
            for d in range(self.b.numCandidates):
                if c != d:
                    if self.pMat[c][d] >= self.pMat[d][c]:
                        dMat[c][d] = True
                    else:
                        dMat[c][d] = False
        for c in range(self.b.numCandidates):
            for d in range(self.b.numCandidates):
                if c != d:
                    for k in range(self.b.numCandidates):
                        if c != k and d != k:
                            if dMat[d][c] and dMat[c][k]:
                                dMat[d][k] = True
        for c in range(self.b.numCandidates):
            for d in range(self.b.numCandidates):
                if c != d:
                    if ((not dMat[c][d]) and dMat[d][c]
                            and (c in self.smithSet)):
                        self.smithSet.remove(c)
        self.smithSet.sort()

    def SchwartzSequentialDropping(self):
        "Complete with SSD."

        # Initialize the defeats matrix: dMat[i][j] gives the magnitude of i's
        # defeat of j. If i doesn't defeat j, then dMat[i][j] == 0.
        self.dMat = []
        for c in range(self.b.numCandidates):
            self.dMat.append([0] * self.b.numCandidates)

        for c in range(self.b.numCandidates):
            for d in range(self.b.numCandidates):
                self.dMat[c][d] = self.pMat[c][d]
        for c in range(self.b.numCandidates):
            for d in range(c):
                if self.pMat[c][d] > self.pMat[d][c]:
                    self.dMat[d][c] = 0
                if self.pMat[c][d] < self.pMat[d][c]:
                    self.dMat[c][d] = 0
                if self.pMat[c][d] == self.pMat[d][c]:
                    self.dMat[c][d] = self.dMat[d][c] = 0

        # Determine "beatpath" magnitudes array: dMat[i][j] will be the
        # maximum beatpath magnitudes array. The i,j entry is the greatest
        # magnitude of any beatpath from i to j. A beatpath's magnitude is
        # the magnitude of its weakest defeat.

        changing = 1
        while changing:
            changing = 0
            for c in range(self.b.numCandidates):
                for d in range(self.b.numCandidates):
                    for k in range(self.b.numCandidates):
                        dmin = min(self.dMat[c][d], self.dMat[d][k])
                        if self.dMat[c][k] < dmin:
                            self.dMat[c][k] = dmin
                            changing = 1

        ctng = range(self.b.numCandidates)[:]
        for c in ctng[:]:
            for d in ctng[:]:
                if self.dMat[d][c] > self.dMat[c][d] and c in ctng:
                    ctng.remove(c)

        if len(ctng) > 1:
            ctng.sort()
            self.SSDinfo = """
Candidates remaining after SSD: %s

Tie broken randomly.""" % self.b.joinList(ctng)
            (c0, desc) = self.breakStrongTie(ctng)
        else:
            self.SSDinfo = ""
            c0 = ctng[0]

        return c0

    def countBallots(self):
        "Count the votes using Condorcet voting."

        # self.pMat[i][j]: number of votes ranking candidate i over candidate j
        self.computePMat()

        # Even though the Smith Set isn't needed for all completion methods
        # it provides interesting info, so compute it always.
        self.computeSmithSet()

        if len(self.smithSet) == 1:
            c0 = self.smithSet[0]
        else:
            # Do the completion
            if self.completion == "Schwartz Sequential Dropping":
                c0 = self.SchwartzSequentialDropping()
            elif self.completion in ["IRV on Smith Set", "Borda on Smith Set"]:
                # Copy ballots and get rid of candidates not in Smith set
                withdrawList = []
                for c in range(self.b.numCandidates):
                    if (c not in self.smithSet):
                        withdrawList.append(c)
                dirtyBallots = self.b.copy()
                dirtyBallots.withdrawn = withdrawList
                dirtyBallots.numSeats = 1
                cleanBallots = dirtyBallots.getCleanBallots()
                if self.completion == "IRV on Smith Set":
                    self.e = IRV(cleanBallots)
                    self.e.strongTieBreakMethod = self.strongTieBreakMethod
                    self.e.runElection()
                elif self.completion == "Borda on Smith Set":
                    self.e = Borda(cleanBallots)
                    self.e.strongTieBreakMethod = self.strongTieBreakMethod
                    self.e.runElection()
                assert (len(self.e.winners) == 1)
                # The Smith set is sorted.  The winner just determined is the index
                # of the winner in the Smith set.
                cIndex = list(self.e.winners)[0]
                c0 = self.smithSet[cIndex]
            else:
                assert (0)

        self.winners = set([c0])