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)
        {
            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);
        }
Beispiel #3
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);
        }
Beispiel #4
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);
        }