Esempio n. 1
0
        // Not thread safe:  writes to nodes.
        // Only called during constructor.
        private void AddGraph(PairwiseGraph graph)
        {
            foreach (Candidate c in graph.Candidates)
            {
                if (!nodes.ContainsKey(c))
                {
                    nodes[c] = new Dictionary <Candidate, decimal>();
                }
            }

            Parallel.ForEach(graph.Candidates, c =>
            {
                // Merge the graph nodes for this candidate
                foreach (Candidate d in graph.Candidates)
                {
                    nodes[c].TryAdd(d, 0.0m);
                    if (graph.nodes[c].ContainsKey(d))
                    {
                        nodes[c][d] += graph.nodes[c][d];
                    }
                }
            });

            // This merger may disturb the graph, so fill in any gaps
            foreach (Candidate c in Candidates)
            {
                if (!nodes.ContainsKey(c))
                {
                    nodes[c] = new Dictionary <Candidate, decimal>();
                }
                foreach (Candidate d in Candidates)
                {
                    if (!nodes[c].Keys.Contains(d))
                    {
                        nodes[c][d] = 0.0m;
                    }
                }
            }
        }
 public RankedTabulationAnalytics(BallotSet ballots, int seats = 1) : base(ballots, seats)
 {
     topCycle      = new TopCycle(ballots);
     pairwiseGraph = null;
 }
Esempio n. 3
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();
        }
Esempio n. 4
0
 public PairwiseGraph(PairwiseGraph graph)
 {
     AddGraph(graph);
 }
Esempio n. 5
0
 /// <summary>
 /// Merge two PairwiseGraphs.
 /// </summary>
 /// <param name="g1">Graph 1</param>
 /// <param name="g2">Graph 2</param>
 public PairwiseGraph(PairwiseGraph g1, PairwiseGraph g2)
 {
     AddGraph(g1);
     AddGraph(g2);
 }
Esempio n. 6
0
 public TopCycle(PairwiseGraph graph, TopCycleSets set = TopCycleSets.smith)
 {
     defaultSet = set;
     this.graph = graph;
 }