Пример #1
0
        /// <summary>
        /// Converts a set of candidates and ballots to a graph of wins and ties.
        /// </summary>
        /// <param name="ballots">Ranked ballots in the election.</param>
        public PairwiseGraph(BallotSet ballots)
        {
            // Initialize candidate graph
            HashSet <Candidate> candidates = (ballots as IEnumerable <CountedBallot>).SelectMany(x => x.Votes.Select(y => y.Candidate)).ToHashSet();

            foreach (Candidate c in candidates)
            {
                nodes[c] = new Dictionary <Candidate, decimal>();
                foreach (Candidate d in candidates.Except(new[] { c }))
                {
                    nodes[c][d] = 0.0m;
                }
            }

            void BuildGraph()
            {
                List <CountedBallot> bList = ballots.ToList();

                int threadCount = Environment.ProcessorCount;

                PairwiseGraph[] subsets = new PairwiseGraph[threadCount];

                PairwiseGraph CountSubsets(int start, int end)
                {
                    PairwiseGraph g = new PairwiseGraph();

                    foreach (Candidate c in candidates)
                    {
                        g.nodes[c] = new Dictionary <Candidate, decimal>();
                        foreach (Candidate d in candidates.Except(new[] { c }))
                        {
                            g.nodes[c][d] = 0.0m;
                        }
                    }

                    // Iterate each ballot and count who wins and who ties.
                    // This can support tied ranks and each ballot is O(SUM(1..n)) and o(n).
                    //foreach (CountedBallot b in ballots)
                    for (int i = start; i <= end; i++)
                    {
                        CountedBallot       b        = bList[i];
                        HashSet <Candidate> ranked   = b.Votes.Select(x => x.Candidate).ToHashSet();
                        HashSet <Candidate> unranked = candidates.Except(ranked).ToHashSet();

                        // Iterate to compare each pair.
                        Stack <Vote> votes = new Stack <Vote>(b.Votes);
                        while (votes.Count > 0)
                        {
                            Vote v = votes.Pop();
                            foreach (Vote u in votes)
                            {
                                // Who is ranked first?  No action if a tie.
                                if (v.Beats(u))
                                {
                                    g.nodes[v.Candidate][u.Candidate] += b.Count;
                                }
                                else if (u.Beats(v))
                                {
                                    g.nodes[u.Candidate][v.Candidate] += b.Count;
                                }
                            }
                            // Defeat all unranked candidates
                            foreach (Candidate c in unranked)
                            {
                                g.nodes[v.Candidate][c] += b.Count;
                            }
                        }
                    }
                    return(g);
                }

                // First divide all the processes up for background run
                Parallel.For(0, threadCount, (i, state) =>
                             subsets[i] = CountSubsets(bList.Count() * i / threadCount, (bList.Count() * (i + 1) / threadCount) - 1));
                // Add them all together
                foreach (PairwiseGraph g in subsets)
                {
                    AddGraph(g);
                }
            }

            BuildGraph();
        }