private void ComputePCA(VotingRules.VotingSituation situation)
        {
            var channels = new double[situation.PartyCount][];

            for (int i = 0; i < situation.PartyCount; i++)
            {
                channels[i] = new double[situation.Electorates.Count];
            }

            for (int i = 0; i < situation.Electorates.Count; i++)
            {
                var electorate = situation.Electorates[i];

                int[] voteCounts = new int[situation.PartyCount];     // Number of votes for each party.

                foreach (var index in electorate.VoteCounts)
                {
                    var preferenceOrder = situation.GetPreferenceOrderByIndex(index);

                    voteCounts[preferenceOrder[0]] += electorate.VoteCounts[index];
                }

                for (int j = 0; j < situation.PartyCount; j++)
                {
                    channels[j][i] = voteCounts[j];
                }
            }

            var m = PrincipalComponentAnalysis.CalculateMatrix(channels, situation.Electorates.Count);

            VarExplainedByComponentOfFirstPrefScores = m.VarianceExplainedByComponent;
        }
        public override List <int> CalculateResults(VotingSituation situation)
        {
            var baseRule = new ProportionalByDistrictVotingRule()
            {
                Apportionment = Apportionment
            };
            var newSituation = new VotingSituation();

            newSituation.PartyCount = situation.PartyCount;
            newSituation.Electorates.AddRange(situation.Electorates);

            int LargeDistrictSize = TotalSeats - situation.Electorates.Count;

            if (LargeDistrictSize > 0)
            {
                var newElectorate = new ElectorateVotes();
                newElectorate.Magnitude  = LargeDistrictSize;
                newElectorate.VoteCounts = new HashMultiset <Int64>();

                foreach (var smallDistrict in situation.Electorates)
                {
                    foreach (var prefOrder in smallDistrict.VoteCounts)
                    {
                        newElectorate.VoteCounts[prefOrder] += smallDistrict.VoteCounts[prefOrder];
                    }
                }

                newSituation.Electorates.Add(newElectorate);
            }

            return(baseRule.CalculateResults(newSituation));
        }
        public static SimulationResults ComputeSimulation(VotingRules.VotingSituation situation, VotingRules.VotingRule rule)
        {
            var seatResults = rule.CalculateResults(situation);

            // Calculate number of votes for each party.
            int[] voteCounts = new int[seatResults.Count];     // Number of votes for each party.

            return(ComputeSimulationScores(seatResults, situation.GetTotalVotesByParty().ToArray(), true, false, situation));
        }
        public List <int> CalculateResults(int partyCount, Multiset <Int64> votingSituation, List <List <int> > preferenceOrders)
        {
            // For legacy purposes.

            var situation = new VotingSituation();

            situation.PartyCount             = partyCount;
            situation.LegacyPreferenceOrders = preferenceOrders;
            situation.Electorates.Add(new ElectorateVotes()
            {
                VoteCounts = votingSituation, Magnitude = 1
            });

            return(CalculateResults(situation));
        }
Exemple #5
0
        public static VotingSituation FromInfo(IEnumerable <HashMultiset <Int64> > districts, int partyCount, int districtMagnitude)
        {
            var electorates = new List <ElectorateVotes>();

            foreach (var d in districts)
            {
                var ev = new ElectorateVotes();

                ev.Magnitude  = districtMagnitude;
                ev.VoteCounts = d;

                electorates.Add(ev);
            }

            var result = new VotingSituation();

            result.Electorates = electorates;
            result.PartyCount  = partyCount;

            return(result);
        }
        public override List <int> CalculateResults(VotingSituation situation)
        {
            List <int> results = new int[situation.PartyCount].ToList();

            foreach (var electorate in situation.Electorates)
            {
                if (electorate.Magnitude != 1)
                {
                    throw new NotSupportedException();
                }

                int[] voteCounts = new int[situation.PartyCount];     // Number of votes for each party.

                foreach (var index in electorate.VoteCounts)
                {
                    var preferenceOrder = situation.GetPreferenceOrderByIndex(index);

                    voteCounts[preferenceOrder[0]] += electorate.VoteCounts[index];
                }

                int maxScore = 0;
                int maxIndex = 0;

                for (int i = 0; i < situation.PartyCount; i++)
                {
                    if (voteCounts[i] > maxScore)
                    {
                        maxScore = voteCounts[i];
                        maxIndex = i;
                    }
                }

                results[maxIndex]++;
            }

            return(results);
        }
 public abstract List <int> CalculateResults(VotingSituation situation);
Exemple #8
0
        public override List <int> CalculateResults(VotingSituation situation)
        {
            List <int> results = new int[situation.PartyCount].ToList();

            foreach (var electorate in situation.Electorates)
            {
                int    electedRepresentitives = 0;
                bool[] isExcluded             = new bool[situation.PartyCount];

                double   quota             = ((double)electorate.VoteCounts.Weight) / (1.0 + (double)electorate.Magnitude);
                double[] preferenceWeights = new double[situation.PreferenceOrdersCount];

                for (int i = 0; i < preferenceWeights.Length; i++)
                {
                    preferenceWeights[i] = 1.0;
                }

                List <List <int> > preferenceOrders = new List <List <int> >();

                foreach (var index in electorate.VoteCounts)
                {
                    var preferenceOrder = situation.GetPreferenceOrderByIndex(index);

                    preferenceOrders.Add(preferenceOrder);
                }

                for (int round = 0; round < situation.PartyCount; round++)
                {
                    int winnersThisRound = 0;

                    double[] votesByParty = new double[situation.PartyCount];
                    //int[] votedForIndex = new int[situation.PreferenceOrdersCount];
                    //Dictionary<Int64, int> votesForIndexLookup = new Dictionary<long, int>(situation.PreferenceOrdersCount);
                    List <int> votesForIndex = new List <int>();

                    //for (int i = 0; i < votedForIndex.Length; i++)
                    //{
                    //    votedForIndex[i] = -1;
                    //}

                    int index2 = 0;
                    foreach (var index in electorate.VoteCounts)
                    {
                        var preferenceOrder = preferenceOrders[index2];

                        var firstNonExcludedPreference = (from x in preferenceOrder where !isExcluded[x] select x).First();

                        votesByParty[firstNonExcludedPreference] += preferenceWeights[index] * (double)electorate.VoteCounts[index];
                        //votedForIndex[index] = firstNonExcludedPreference;
                        //votesForIndexLookup.Add(index, firstNonExcludedPreference);
                        votesForIndex.Add(firstNonExcludedPreference);

                        index2++;
                    }


                    for (int i = 0; i < situation.PartyCount; i++)
                    {
                        if ((!isExcluded[i]) && votesByParty[i] > quota)
                        {
                            double multiplier   = (votesByParty[i] - quota) / votesByParty[i];
                            double removedVotes = 0.0;

                            int prefOrderIndex = 0;
                            foreach (var prefOrder in electorate.VoteCounts)
                            {
                                if (votesForIndex[prefOrderIndex] == i)
                                {
                                    removedVotes += preferenceWeights[prefOrder] * (double)electorate.VoteCounts[prefOrder];
                                    preferenceWeights[prefOrder] *= multiplier;
                                }

                                prefOrderIndex++;
                            }

                            var removedVotes2 = removedVotes * (1.0 - multiplier);

                            //foreach (var x in votesForIndexLookup)
                            //{
                            //    if (x.Value == i)
                            //    {
                            //        preferenceWeights[x.Key] *= multiplier;
                            //    }
                            //}

                            //for (int j = 0; j < votedForIndex.Length; j++)
                            //{
                            //    if (votedForIndex[j] == i)
                            //    {
                            //        preferenceWeights[i] *= multiplier;
                            //    }
                            //}

                            // By commenting out this line, we allow for multiple seats per party per district.
                            //isExcluded[i] = true;
                            results[i]++;

                            winnersThisRound++;
                            electedRepresentitives++;

                            if (electedRepresentitives >= electorate.Magnitude)
                            {
                                goto endElectorate;
                            }
                        }
                    }

                    if (winnersThisRound == 0)
                    {
                        if ((from x in isExcluded where x == false select x).Count() + electedRepresentitives == electorate.Magnitude)
                        {
                            // The number of remaining candidates
                            // is equal to the number we want to elect
                            // we shouldn't ever get here
                            // but it seems like there is a problem with
                            // floating point math...
                            // TODO: Look into this.

                            throw new Exception();

                            for (int i = 0; i < results.Count; i++)
                            {
                                if (!isExcluded[i])
                                {
                                    results[i]++;
                                }
                            }

                            goto endElectorate;
                        }

                        int    lowestIndex = 0;
                        double lowestVotes = double.MaxValue;

                        for (int i = 0; i < situation.PartyCount; i++)
                        {
                            if (!isExcluded[i])
                            {
                                if (votesByParty[i] < lowestVotes)
                                {
                                    lowestVotes = votesByParty[i];
                                    lowestIndex = i;
                                }
                            }
                        }

                        isExcluded[lowestIndex] = true;
                    }
                }
endElectorate:
                continue;
            }

            return(results);
        }
Exemple #9
0
        public override List <int> CalculateResults(VotingSituation situation)
        {
            List <int> results = new int[situation.PartyCount].ToList();

            foreach (var electorate in situation.Electorates)
            {
                int[] voteCounts = new int[situation.PartyCount];     // Number of votes for each party.

                foreach (var index in electorate.VoteCounts)
                {
                    var preferenceOrder = situation.GetPreferenceOrderByIndex(index);

                    voteCounts[preferenceOrder[0]] += electorate.VoteCounts[index];
                }

                List <int> localResults = new int[situation.PartyCount].ToList();

                var indicies = Enumerable.Range(0, situation.PartyCount).ToArray();

                double[] voteCounts2 = (from x in voteCounts select Math.Abs((double)x + ((Rand.NextDouble() - 0.5) / (double)voteCounts.Sum()))).ToArray();

                double standardDivisor = (double)voteCounts2.Sum() / (double)electorate.Magnitude;
                var    standardQuota   = (from x in voteCounts2 select(double) x / standardDivisor).ToArray();
                var    lowerQuota      = (from x in standardQuota select Math.Floor(x)).ToList();
                var    upperQuota      = (from x in standardQuota select Math.Ceiling(x)).ToList();
                var    fractionalQuota = (from x in indicies select standardQuota[x] - lowerQuota[x]).ToList();

                double MD = standardDivisor;

                switch (Apportionment)
                {
                case ApportionmentMethod.StLague:
                    for (int i = 0; i < electorate.Magnitude; i++)
                    {
                        double maxQuot  = 0.0;
                        int    maxIndex = 0;

                        for (int j = 0; j < situation.PartyCount; j++)
                        {
                            var quot = ((double)voteCounts[j]) / (2.0 * ((double)localResults[j]) + 1.0);

                            if (quot > maxQuot)
                            {
                                maxQuot  = quot;
                                maxIndex = j;
                            }
                        }

                        localResults[maxIndex]++;
                    }

                    break;

                case ApportionmentMethod.Hill:
                    //while (true)
                    //{
                    //    var candidateQuota = (from x in voteCounts2 select (double)x / MD).ToArray();
                    //    var candidateQuotaLo = (from x in candidateQuota select (int)Math.Floor(x)).ToArray();
                    //    var candidateQuotaHi = (from x in candidateQuota select (int)Math.Ceiling(x)).ToArray();
                    //    var candidateQuotaGeo = (from i in indicies select Math.Sqrt((double)candidateQuotaLo[i] * (double)candidateQuotaHi[i])).ToArray();
                    //    //var candidate = (from i in indicies select candidateQuota[i] > candidateQuotaGeo[i] ? (int)upperQuota[i] : (int)lowerQuota[i]).ToArray();
                    //    var candidate = (from i in indicies select standardQuota[i] > candidateQuotaGeo[i] ? (int)upperQuota[i] : (int)lowerQuota[i]).ToArray();

                    //    if (candidate.Sum() == electorate.Magnitude)
                    //    {
                    //        for (int i = 0; i < situation.PartyCount; i++)
                    //        {
                    //            localResults[i] += candidate[i];
                    //        }
                    //    }

                    //    if (localResults.Sum() > 0)
                    //    {
                    //        break;
                    //    }

                    //    MD = standardDivisor * Rand.NextDouble();
                    //}
                    for (int i = 0; i < electorate.Magnitude; i++)
                    {
                        double maxQuot  = 0.0;
                        int    maxIndex = 0;

                        for (int j = 0; j < situation.PartyCount; j++)
                        {
                            var geoMean = Math.Sqrt(Math.Pow((double)localResults[j], 2.0) + Math.Pow((double)(localResults[j] + 1), 2.0));
                            var quot    = ((double)voteCounts[j]) / geoMean;

                            if (quot > maxQuot)
                            {
                                maxQuot  = quot;
                                maxIndex = j;
                            }
                        }

                        localResults[maxIndex]++;
                    }

                    break;

                case ApportionmentMethod.Jefferson:
                    //while (localResults.Sum() == 0)
                    //{
                    //    var candidateQuota = (from x in voteCounts2 select (int)Math.Floor((double)x / MD)).ToArray();

                    //    if (candidateQuota.Sum() == electorate.Magnitude)
                    //    {
                    //        for (int i = 0; i < situation.PartyCount; i++)
                    //        {
                    //            localResults[i] += candidateQuota[i];
                    //        }
                    //    }

                    //    MD = standardDivisor * Rand.NextDouble();
                    //}

                    var           matrix  = new double[situation.PartyCount, electorate.Magnitude];
                    List <double> mValues = new List <double>();

                    for (int i = 0; i < situation.PartyCount; i++)
                    {
                        var pcVotes = voteCounts2[i];

                        for (int j = 0; j < electorate.Magnitude; j++)
                        {
                            var value = ((double)pcVotes) / ((double)(j + 1));

                            matrix[i, j] = value;
                            mValues.Add(value);
                        }
                    }

                    //List<int> localResults2 = new List<int>();

                    var cutoff = (from x in mValues orderby x descending select x).Take(electorate.Magnitude).Min();
                    var cCount = (from x in mValues where x >= cutoff select x).Count();

                    for (int i = 0; i < situation.PartyCount; i++)
                    {
                        int seatCount = 0;

                        for (int j = 0; j < electorate.Magnitude; j++)
                        {
                            if (matrix[i, j] >= cutoff)
                            {
                                seatCount++;
                            }
                        }
                        localResults[i] = (seatCount);
                    }


                    break;

                case ApportionmentMethod.Hamilton:
                    for (int i = 0; i < situation.PartyCount; i++)
                    {
                        localResults[i] = (int)lowerQuota[i];
                    }

                    foreach (var i in (from x in indicies orderby fractionalQuota[x] descending select x))
                    {
                        if (electorate.Magnitude > localResults.Sum())
                        {
                            localResults[i]++;
                        }
                        else
                        {
                            break;
                        }
                    }

                    break;

                default:
                    throw new Exception();
                }

                // Copy district results to global results.
                for (int i = 0; i < situation.PartyCount; i++)
                {
                    results[i] += localResults[i];
                }
            }

            return(results);
        }
        public static SimulationResults ComputeSimulationScores(List <int> results, int[] voteCounts, bool computeShapleyShubikPowerIndex, bool computeBanzhafPowerIndex, VotingRules.VotingSituation situation)
        {
            // Number of parties = results.Count

            var simResult = new SimulationResults();

            simResult.SeatResults = results;
            simResult.Result      = results;

            // Index calculation

            simResult.GallagherIndex = 0.0;
            //simResult.EntropyIndex = 0.0;
            //simResult.MaxDisprop = 0.0;
            simResult.RaesIndex                = 0.0;
            simResult.LijphartIndex            = 0.0;
            simResult.LoosemoreHanbyIndex      = 0.0;
            simResult.EffectiveNumberOfParties = 0.0;

            List <double> seatsProp       = new List <double>();
            List <double> proportionFirst = new List <double>();
            List <double> deltas          = new List <double>();

            for (int i = 0; i < results.Count; i++)
            {
                double proportionSeats      = (double)simResult.Result[i] / (double)simResult.Result.Sum();
                double proportionFirstVotes = (double)voteCounts[i] / (double)voteCounts.Sum();
                double delta = proportionSeats - proportionFirstVotes;

                deltas.Add(delta);
                proportionFirst.Add(proportionFirstVotes);
                seatsProp.Add(proportionSeats);

                simResult.GallagherIndex += Math.Pow(delta, 2.0);

                var logDelta = Math.Log(delta);

                if (double.IsNaN(logDelta))
                {
                    logDelta = 0.0;
                }

                //simResult.EntropyIndex += delta * logDelta;
                //simResult.MaxDisprop = Math.Max(simResult.MaxDisprop, delta);

                simResult.RaesIndex                += Math.Abs(delta);
                simResult.LoosemoreHanbyIndex      += Math.Abs(delta);
                simResult.TrueDispropIndex         += Math.Abs(delta);
                simResult.LijphartIndex             = Math.Max(simResult.LijphartIndex, delta);
                simResult.EffectiveNumberOfParties += Math.Pow(proportionSeats, 2.0);
            }

            simResult.TrueDispropIndex         = simResult.TrueDispropIndex / (double)simResult.Result.Sum();
            simResult.GallagherIndex           = Math.Sqrt(simResult.GallagherIndex / 2.0);
            simResult.RaesIndex               /= (double)results.Count;
            simResult.LoosemoreHanbyIndex     /= 2;
            simResult.EffectiveNumberOfParties = 1.0 / simResult.EffectiveNumberOfParties;


            // For debugging.
            var seatsPropSum = seatsProp.Sum();
            var propFirstSum = proportionFirst.Sum();
            var deltaSum     = deltas.Sum();

            // Shapley Shubik power index

            if (computeShapleyShubikPowerIndex)
            {
                simResult.ShapleyShubikPowerIndex = new double[results.Count];

                // Naive method of computing Shapley Shubik.

                /*
                 * double permutationCount = Program.Factorial(partyList.Count);
                 *
                 * foreach (var x in Program.Permute(partyList))
                 * {
                 *  double powerTotal = 0.0;
                 *
                 *  foreach (var y in x)
                 *  {
                 *      int index = partyList.IndexOf(y);
                 *
                 *      powerTotal += seatsProp[index];
                 *
                 *      if (powerTotal > 0.5)
                 *      {
                 *          simResult.ShapleyShubikPowerIndex[index] += (1.0 / permutationCount);
                 *          break;
                 *      }
                 *  }
                 * }
                 */

                // Shapley Shubik power index (fast method).
                // http://hercules.us.es/~mbilbao/pdffiles/generat.pdf

                int n = results.Count;

                for (int i = 0; i < n; i++)
                {
                    double score         = 0.0;
                    double multiplierSum = 0.0; // Should sum to one.

                    // Returns whether or not the given set of parties wins.
                    Func <List <int>, bool> v = (List <int> set) =>
                    {
                        return((from x in set select seatsProp[x]).Sum() > 0.5);
                    };

                    var combinations = DiscreteMath.Combinations(DiscreteMath.GetIntList(results.Count)).ToList();

                    combinations.Add(new List <int>()); // Our combinations function does not include the empty set.

                    foreach (var S in combinations)
                    {
                        if (S.Contains(i))
                        {
                            // S == i
                            continue;
                        }

                        var unionSet = S.ToList();
                        unionSet.Add(i);

                        int s = S.Count;

                        double multiplier;

                        //multiplier = Program.Factorial(s) * Program.Factorial(n - s - 1) / Program.Factorial(n);

                        double a = DiscreteMath.Factorial(s);
                        double b = DiscreteMath.Factorial(n - (s + 1));
                        double c = DiscreteMath.Factorial(n);

                        multiplier = (a * b) / c;

                        multiplierSum += multiplier;

                        if (v(unionSet) && (!v(S)))
                        {
                            score += multiplier;
                        }
                    }

                    // TODO: Assert that multiplierSum = 1

                    simResult.ShapleyShubikPowerIndex[i] = score;
                }
            }

            // Banzhaf power index

            if (computeBanzhafPowerIndex)
            {
                simResult.BanzhafPowerIndex = new double[results.Count];

                int winningCombinationsCount = 0;

                foreach (var x in DiscreteMath.Combinations(DiscreteMath.GetIntList(results.Count)))
                {
                    double powerTotal = 0.0;

                    foreach (var y in x)
                    {
                        int index = y;

                        powerTotal += seatsProp[index];
                    }

                    if (powerTotal > 0.5)
                    {
                        winningCombinationsCount++;
                        foreach (var y in x)
                        {
                            int index = y;

                            double thisPartyPower = seatsProp[index];

                            if ((powerTotal - thisPartyPower) < 0.5)
                            {
                                // This is a critical voter.
                                simResult.BanzhafPowerIndex[index] += 1.0;
                            }
                        }
                    }
                }

                for (int i = 0; i < results.Count; i++)
                {
                    simResult.BanzhafPowerIndex[i] /= (double)winningCombinationsCount;
                }
            }

            if (situation != null)
            {
                simResult.ComputePCA(situation);
            }

            return(simResult);
        }
Exemple #11
0
        public override List <int> CalculateResults(VotingSituation situation)
        {
            List <int> results = new int[situation.PartyCount].ToList();

            var totalVotesByParty = situation.GetTotalVotesByParty();

            var totalVotes     = totalVotesByParty.Sum();
            var thresholdLimit = ((double)totalVotes) * Threshold;

            bool[] partyNotExcluded = new bool[situation.PartyCount];

            for (int i = 0; i < situation.PartyCount; i++)
            {
                if ((situation.MMPElectorateSeatsOverride != null) && situation.MMPElectorateSeatsOverride[i] > 0)
                {
                    partyNotExcluded[i] = true;
                }
                else if (totalVotesByParty[i] > thresholdLimit)
                {
                    partyNotExcluded[i] = true;
                }
                else
                {
                    partyNotExcluded[i] = false;
                }
            }

            int totalVotesAfterRemoval = 0;

            for (int i = 0; i < situation.PartyCount; i++)
            {
                if (partyNotExcluded[i])
                {
                    totalVotesAfterRemoval += totalVotesByParty[i];
                }
            }

            var seatTotal = situation.GetSeatTotal();

            for (int i = 0; i < seatTotal; i++)
            {
                double maxQuot  = 0.0;
                int    maxIndex = 0;

                for (int j = 0; j < situation.PartyCount; j++)
                {
                    if (partyNotExcluded[j])
                    {
                        var quot = ((double)totalVotesByParty[j]) / (2.0 * ((double)results[j]) + 1.0);

                        if (quot > maxQuot)
                        {
                            maxQuot  = quot;
                            maxIndex = j;
                        }
                    }
                }

                results[maxIndex]++;
            }

            return(results);
        }