class Vote::Condorcet::Schulze::Basic

Attributes

beat_couples[R]
candidates[R]
play_matrix[R]
potential_winners[R]
ranking[R]
result_matrix[R]
ties[R]
vote_count[R]
vote_matrix[R]
winners_array[R]

Public Class Methods

do(vote_matrix, candidate_count = nil) click to toggle source

All-in-One class method to get a calculated SchulzeBasic object

# File lib/vote/condorcet/schulze/basic.rb, line 14
def self.do(vote_matrix, candidate_count = nil)
  instance = new
  instance.load vote_matrix, candidate_count
  instance.run
  instance
end
new() click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 8
def initialize
  @beat_couples = []
  @ties = []
end

Public Instance Methods

load(vote_matrix, candidate_count = nil) click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 21
def load(vote_matrix, candidate_count = nil)
  input = if vote_matrix.is_a?(Vote::Condorcet::Schulze::Input)
            vote_matrix
          else
            Vote::Condorcet::Schulze::Input.new(vote_matrix, candidate_count)
          end
  @vote_matrix = input.matrix
  @candidate_count = input.candidates
  @candidates = (0..@candidate_count - 1).to_a
  @vote_count = input.voters
  self
end
run() click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 34
def run
  play
  result
  calculate_winners
  rank
  calculate_beat_couples
  calculate_potential_winners
end

Private Instance Methods

build_play_matrix() click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 51
def build_play_matrix
  ::Matrix.scalar(@candidate_count, 0).extend(Vote::Matrix)
end
calculate_beat_couples() click to toggle source

calculates @beat_couples and @ties in roder to display results afterward

# File lib/vote/condorcet/schulze/basic.rb, line 109
def calculate_beat_couples
  return if @calculated_beat_couples

  ranking.each_with_index do |_val, idx|
    ranking.each_with_index do |_val2, idx2|
      next if idx == idx2
      next @beat_couples << [idx, idx2] if play_matrix[idx, idx2] > play_matrix[idx2, idx]
      calculate_ties(idx, idx2)
    end
  end
  @calculated_beat_couples = true
end
calculate_potential_winners() click to toggle source

you should call calculate_winners first

# File lib/vote/condorcet/schulze/basic.rb, line 104
def calculate_potential_winners
  @potential_winners ||= winners_array.map.with_index { |val, idx| idx if val > 0 }.compact
end
calculate_ties(idx, idx2) click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 122
def calculate_ties(idx, idx2)
  return unless in_tie?(idx, idx2)
  return if @ties.any? { |tie| ([idx, idx2] - tie).empty? }
  found_tie = tie_by_idx(idx)
  return found_tie << idx2 if found_tie
  found_tie = tie_by_idx(idx2)
  return found_tie << idx if found_tie
  @ties << [idx, idx2]
end
calculate_winners() click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 88
def calculate_winners
  @winners_array = Array.new(@candidate_count, 0)
  @winners_array.each_with_index do |_el, idx|
    row = @play_matrix.row(idx)
    column = @play_matrix.column(idx)
    if row.each_with_index.all? { |r, index| r >= column[index] }
      @winners_array[idx] = 1
    end
  end
end
find_matches_with_wins() click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 55
def find_matches_with_wins
  @candidate_count.times do |i|
    @candidate_count.times do |j|
      next if i == j
      if @vote_matrix[i, j] > @vote_matrix[j, i]
        @play_matrix[i, j] = @vote_matrix[i, j]
      else
        @play_matrix[i, j] = 0
      end
    end
  end
end
find_strongest_paths() click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 68
def find_strongest_paths
  @candidate_count.times do |i|
    @candidate_count.times do |j|
      next if i == j
      @candidate_count.times do |k|
        next if (i == k) || (j == k)
        @play_matrix[j, k] = [@play_matrix[j, k], [@play_matrix[j, i], @play_matrix[i, k]].min].max
      end
    end
  end
end
in_tie?(idx, idx2) click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 136
def in_tie?(idx, idx2)
  @play_matrix[idx, idx2] == @play_matrix[idx2, idx] &&
    @ranking[idx] == @ranking[idx2] &&
    @winners_array[idx] == @winners_array[idx2]
end
play() click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 45
def play
  @play_matrix = build_play_matrix
  find_matches_with_wins
  find_strongest_paths
end
rank() click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 99
def rank
  @ranking = @result_matrix.row_vectors.map { |rm| rm.inject(0) { |a, e| a + e } }
end
result() click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 80
def result
  @result_matrix = ::Matrix.scalar(@candidate_count, 0).extend(Vote::Matrix)
  @result_matrix.each_with_index do |e, x, y|
    next if x == y
    @result_matrix[x, y] = e + 1 if @play_matrix[x, y] > @play_matrix[y, x]
  end
end
tie_by_idx(idx) click to toggle source
# File lib/vote/condorcet/schulze/basic.rb, line 132
def tie_by_idx(idx)
  @ties.find { |tie| tie.any? { |el| el == idx } }
end