Пример #1
0
        /// <summary>
        /// Implementation to generate the ranking list for the provided set
        /// of votes for a specific task.
        /// </summary>
        /// <param name="task">The task that the votes are grouped under.</param>
        /// <returns>Returns a ranking list of winning votes.</returns>
        protected override RankResults RankTask(GroupedVotesByTask task)
        {
            RankResults winningChoices = new RankResults();

            // The groupVotes are used for getting the Wilson score
            var rankedVotes = GroupRankVotes.GroupByVoteAndRank(task);
            // The voterRankings are used for the runoff
            var voterRankings = GroupRankVotes.GroupByVoterAndRank(task);
            // The full choices list is just to keep track of how many we have left.
            var allChoices = GroupRankVotes.GetAllChoices(voterRankings);

            for (int i = 1; i <= 9; i++)
            {
                RankResult winner = GetWinningVote(voterRankings, rankedVotes);

                if (winner == null)
                {
                    break;
                }

                winningChoices.Add(winner);
                allChoices.Remove(winner.Option);

                if (!allChoices.Any())
                {
                    break;
                }

                voterRankings = RemoveChoiceFromVotes(voterRankings, winner.Option);
                rankedVotes   = RemoveChoiceFromRanks(rankedVotes, winner.Option);
            }

            return(winningChoices);
        }
Пример #2
0
        /// <summary>
        /// Implementation to generate the ranking list for the provided set
        /// of votes for a specific task.
        /// </summary>
        /// <param name="task">The task that the votes are grouped under.</param>
        /// <returns>Returns a ranking list of winning votes.</returns>
        protected override RankResults RankTask(GroupedVotesByTask task)
        {
            if (task == null)
            {
                throw new ArgumentNullException(nameof(task));
            }

            RankResults winningChoices = new RankResults();

            if (task.Any())
            {
                var voterRankings = GroupRankVotes.GroupByVoterAndRank(task);
                var allChoices    = GroupRankVotes.GetAllChoices(voterRankings);

                for (int i = 1; i <= 9; i++)
                {
                    RankResult winner = GetWinningVote(voterRankings, winningChoices);

                    if (winner == null)
                    {
                        break;
                    }

                    winningChoices.Add(winner);
                    allChoices.Remove(winner.Option);

                    if (!allChoices.Any())
                    {
                        break;
                    }
                }
            }

            return(winningChoices);
        }
Пример #3
0
        /// <summary>
        /// Fills the pairwise preferences.
        /// This goes through each voter's ranking options and updates an array indicating
        /// which options are preferred over which other options.  Each higher-ranked
        /// option gains one point in 'beating' a lower-ranked option.
        /// </summary>
        /// <param name="voterRankings">The voter rankings.</param>
        /// <param name="listOfChoices">The list of choices.</param>
        /// <returns>Returns a filled-in preferences array.</returns>
        private int[,] GetPairwisePreferences(IEnumerable<VoterRankings> voterRankings, List<string> listOfChoices)
        {
            int[,] pairwisePreferences = new int[listOfChoices.Count, listOfChoices.Count];

            var choiceIndexes = GroupRankVotes.GetChoicesIndexes(listOfChoices);

            foreach (var voter in voterRankings)
            {
                var rankedChoices = voter.RankedVotes.Select(v => v.Vote);
                var unrankedChoices = listOfChoices.Except(rankedChoices);

                foreach (var choice in voter.RankedVotes)
                {
                    // Each choice matching or beating the ranks of other ranked choices is marked.
                    foreach (var otherChoice in voter.RankedVotes)
                    {
                        if ((choice.Vote != otherChoice.Vote) && (choice.Rank <= otherChoice.Rank))
                        {
                            pairwisePreferences[choiceIndexes[choice.Vote], choiceIndexes[otherChoice.Vote]]++;
                        }
                    }

                    // Each choice is ranked higher than all unranked choices
                    foreach (var nonChoice in unrankedChoices)
                    {
                        pairwisePreferences[choiceIndexes[choice.Vote], choiceIndexes[nonChoice]]++;
                    }
                }
            }

            return pairwisePreferences;
        }
Пример #4
0
        /// <summary>
        /// Gets the least preferred choice.
        /// This is normally determined by selecting the option with the lowest Borda count.
        /// This is inverted because we don't want to convert ranks to Borda values (it gains us nothing).
        /// It then needs to be averaged across the number of instances of each vote, to
        /// account for unranked options.  This allows apples-to-apples comparisons against options
        /// that are ranked in all votes.
        /// We then need to scale it relative to the number of instances of that option appearing, to deal
        /// with truncated rankings (where there are more options than rankings allowed).
        /// An option ranked infrequently can be scaled up relative to its rate of occurance for
        /// a high likelihood of elimination.
        /// </summary>
        /// <param name="localRankings">The vote rankings.</param>
        /// <returns>Returns the vote string for the least preferred vote.</returns>
        private static string GetLeastPreferredChoice(List <VoterRankings> localRankings)
        {
            var groupVotes = GroupRankVotes.GroupByVoteAndRank(localRankings);

            var rankedVotes = from vote in groupVotes
                              select new { Vote = vote.VoteContent, Rank = RankScoring.LowerWilsonScore(vote.Ranks) };

            var worstVote = rankedVotes.MinObject(a => a.Rank);

            Debug.Write($"({worstVote.Rank:f5}) {worstVote.Vote}");

            return(worstVote.Vote);
        }
Пример #5
0
        /// <summary>
        /// Implementation to generate the ranking list for the provided set
        /// of votes for a specific task.
        /// </summary>
        /// <param name="task">The task that the votes are grouped under.</param>
        /// <returns>Returns a ranking list of winning votes.</returns>
        protected override RankResults RankTask(GroupedVotesByTask task)
        {
            var groupVotes = GroupRankVotes.GroupByVoteAndRank(task);

            var rankedVotes = from vote in groupVotes
                              select new { Vote = vote.VoteContent, Rank = RankVote(vote.Ranks) };

            var orderedVotes = rankedVotes.OrderByDescending(a => a.Rank);

            RankResults results = new RankResults();

            results.AddRange(orderedVotes.Select(a =>
                                                 new RankResult(a.Vote, $"BordaRank: [{a.Rank}]")));

            return(results);
        }
Пример #6
0
        /// <summary>
        /// Implementation to generate the ranking list for the provided set
        /// of votes for a specific task.
        /// </summary>
        /// <param name="task">The task that the votes are grouped under.</param>
        /// <returns>Returns a ranking list of winning votes.</returns>
        protected override RankResults RankTask(GroupedVotesByTask task)
        {
            // Can calculating the score easily by having all the rankings for
            // each vote grouped together.
            var groupVotes = GroupRankVotes.GroupByVoteAndRank(task);

            var rankedVotes = from vote in groupVotes
                              select new { Vote = vote.VoteContent, Rank = RankScoring.LowerWilsonScore(vote.Ranks) };

            var orderedVotes = rankedVotes.OrderByDescending(a => a.Rank);

            RankResults results = new RankResults();

            results.AddRange(orderedVotes.Select(a =>
                                                 new RankResult(a.Vote, $"Wilson: [{a.Rank:f5}]")));

            return(results);
        }
Пример #7
0
        /// <summary>
        /// Fills the pairwise preferences.
        /// This goes through each voter's ranking options and updates an array indicating
        /// which options are preferred over which other options.
        /// Each higher-ranked option gains the difference in ranking in 'beating' a lower-ranked option.
        /// </summary>
        /// <param name="voterRankings">The voter rankings.</param>
        /// <param name="listOfChoices">The list of choices.</param>
        /// <returns>Returns a filled-in preferences array.</returns>
        private static DistanceData GetPairwiseData(IEnumerable <VoterRankings> voterRankings, List <string> listOfChoices)
        {
            DistanceData data = new DistanceData
            {
                Paths = new int[listOfChoices.Count, listOfChoices.Count]
            };

            var choiceIndexes = GroupRankVotes.GetChoicesIndexes(listOfChoices);

            foreach (var voter in voterRankings)
            {
                var rankedChoices   = voter.RankedVotes.Select(v => v.Vote);
                var unrankedChoices = listOfChoices.Except(rankedChoices);

                foreach (var choice in voter.RankedVotes)
                {
                    foreach (var otherChoice in voter.RankedVotes)
                    {
                        // Each ranked vote that has a higher rank (lower number) than each
                        // alternative has the distance between the choices added to the
                        // corresponding table entry.
                        if (choice.Vote != otherChoice.Vote && choice.Rank < otherChoice.Rank)
                        {
                            data.Paths[choiceIndexes[choice.Vote], choiceIndexes[otherChoice.Vote]] += otherChoice.Rank - choice.Rank;
                        }
                    }

                    // All unranked options are considered to be at distance 0 from *all* ranked options.
                    // There is no relative preference, nor does it place unranked options 'beneath'
                    // ranked options, such that higher ranked options have greater distance from them.
                    // Unranked options are agnostic choices.
                    //foreach (var nonChoice in unrankedChoices)
                    //{
                    //    //data.Paths[choiceIndexes[choice.Vote], choiceIndexes[nonChoice]]++;
                    //}
                }

                // All unranked options are at distance 0 from each other, and thus have no effect
                // on the distance table.
            }

            return(data);
        }
Пример #8
0
        /// <summary>
        /// Implementation to generate the ranking list for the provided set
        /// of votes for a specific task, based on the Schulze algorithm.
        /// </summary>
        /// <param name="task">The task that the votes are grouped under.</param>
        /// <returns>Returns a ranking list of winning votes.</returns>
        protected override RankResults RankTask(GroupedVotesByTask task)
        {
            if (task == null)
                throw new ArgumentNullException(nameof(task));


            Debug.WriteLine(">>Pairwise Ranking<<");

            List<string> listOfChoices = GroupRankVotes.GetAllChoices(task);

            var voterRankings = GroupRankVotes.GroupByVoterAndRank(task);

            int[,] pairwisePreferences = GetPairwisePreferences(voterRankings, listOfChoices);

            int[,] pairwiseWinners = GetPairwiseWinners(pairwisePreferences, listOfChoices.Count);

            RankResults winningChoices = GetResultsInOrder(pairwiseWinners, listOfChoices);

            return winningChoices;
        }
Пример #9
0
        /// <summary>
        /// Implementation to generate the ranking list for the provided set
        /// of votes for a specific task.
        /// </summary>
        /// <param name="task">The task that the votes are grouped under.</param>
        /// <returns>Returns a ranking list of winning votes.</returns>
        protected override RankResults RankTask(GroupedVotesByTask task)
        {
            Debug.WriteLine(">>Normalized Borda Counting<<");

            //var voterCount = task.SelectMany(t => t.Value).Distinct().Count();

            var groupVotes = GroupRankVotes.GroupByVoteAndRank(task);

            var rankedVotes = from vote in groupVotes
                              select new { Vote = vote.VoteContent, Rank = RankVote(vote.Ranks) };

            var orderedVotes = rankedVotes.OrderBy(a => a.Rank);

            RankResults results = new RankResults();

            results.AddRange(orderedVotes.Select(a =>
                                                 new RankResult(a.Vote, $"BordaNorm: [{a.Rank:f5}]")));

            return(results);
        }
Пример #10
0
        /// <summary>
        /// Implementation to generate the ranking list for the provided set
        /// of votes for a specific task, based on the Schulze algorithm.
        /// </summary>
        /// <param name="task">The task that the votes are grouped under.</param>
        /// <returns>Returns a ranking list of winning votes.</returns>
        protected override RankResults RankTask(GroupedVotesByTask task)
        {
            if (task == null)
            {
                throw new ArgumentNullException(nameof(task));
            }

            List <string> listOfChoices = GroupRankVotes.GetAllChoices(task);

            var voterRankings = GroupRankVotes.GroupByVoterAndRank(task);

            int[,] pairwisePreferences = GetPairwisePreferences(voterRankings, listOfChoices);

            int[,] strongestPaths = GetStrongestPaths(pairwisePreferences, listOfChoices.Count);

            int[,] winningPaths = GetWinningPaths(strongestPaths, listOfChoices.Count);

            RankResults winningChoices = GetResultsInOrder(winningPaths, listOfChoices);

            return(winningChoices);
        }
Пример #11
0
        /// <summary>
        /// Implementation to generate the ranking list for the provided set
        /// of votes for a specific task, based on the Schulze algorithm.
        /// </summary>
        /// <param name="task">The task that the votes are grouped under.</param>
        /// <returns>Returns a ranking list of winning votes.</returns>
        protected override RankResults RankTask(GroupedVotesByTask task)
        {
            if (task == null)
            {
                throw new ArgumentNullException(nameof(task));
            }


            Debug.WriteLine(">>Distance U0 Scoring<<");

            List <string> listOfChoices = GroupRankVotes.GetAllChoices(task);

            var voterRankings = GroupRankVotes.GroupByVoterAndRank(task);

            DistanceData pairwiseData = GetPairwiseData(voterRankings, listOfChoices);

            DistanceData strengthData = GetStrongestPaths(pairwiseData, listOfChoices.Count);

            DistanceData winningPaths = GetWinningPaths(strengthData, listOfChoices.Count);

            RankResults winningChoices = GetResultsInOrder(winningPaths, listOfChoices);

            return(winningChoices);
        }