/// <summary>
            /// Returns a random permutation with the given first second and third preferences.
            /// </summary>
            /// <param name="first"></param>
            /// <param name="second"></param>
            /// <param name="third"></param>
            /// <returns></returns>
            private List <int> GetRandPermutation(int first, int second, int third)
            {
                var indicies = DiscreteMath.GetIntList(PartyCount);

                var result = (from x in indicies
                              orderby
                                  (((x == first) ? 3 : 0) +
                                  ((x == second) ? 2 : 0) +
                                  ((x == third) ? 1 : 0)) descending, Rand.NextDouble()
                              select x).ToList();

                return(result);
            }
        public override Multiset <long> SampleElectorate(int voteCount)
        {
            var result = new HashMultiset <long>();

            var electorateOffset = new double[Dimensions.Length];

            for (int j = 0; j < Dimensions.Length; j++)
            {
                electorateOffset[j] = Rand.SampleNormal(0.0, Dimensions[j] / (2 * Math.Sqrt((double)this.DistrictMagnitude)));
            }

            for (int i = 0; i < voteCount; i++)
            {
                var voterCoords = new double[Dimensions.Length];

                for (int j = 0; j < Dimensions.Length; j++)
                {
                    voterCoords[j] = Rand.SampleNormal(electorateOffset[j], Dimensions[j]);
                }

                List <Tuple <double, int> > distancesByPartyIndex = new List <Tuple <double, int> >();

                for (int p = 0; p < PartyCount; p++)
                {
                    double x = 0.0;

                    for (int j = 0; j < Dimensions.Length; j++)
                    {
                        x += Math.Pow(parties[p].Coords[j] - voterCoords[j], 2.0);
                    }

                    distancesByPartyIndex.Add(new Tuple <double, int>(Math.Sqrt(x), p));
                }

                var prefOrder = (from x in distancesByPartyIndex orderby x.Item1 ascending select x.Item2).ToList();

                var index = DiscreteMath.GetIndexByPermutation(prefOrder);

                result[index]++;
            }

            return(result);
        }
            public HashMultiset <Int64> ToMultiset(int totalVotes)
            {
                var result = new HashMultiset <Int64>();

                for (int i = 0; i < PartyCount; i++)
                {
                    for (int j = 0; j < PartyCount; j++)
                    {
                        for (int k = 0; k < PartyCount; k++)
                        {
                            if (i != j && j != k && i != k)
                            {
                                result[DiscreteMath.GetIndexByPermutation(GetRandPermutation(i, j, k))] += (int)(VotesByParty[i, j, k] * (double)totalVotes);
                            }
                        }
                    }
                }

                return(result);
            }
Exemple #4
0
 public override Multiset <long> SampleElectorate(int voteCount)
 {
     return(DiscreteMath.SampleMultisetUrn(DiscreteMath.FactorialInt64(this.PartyCount), voteCount, AlphaGenerator()));
 }
        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);
        }
        public static PreferenceFile FromStream(Stream strm)
        {
            var result = new PreferenceFile();
            var csv    = CSVReader.ReadFromStream(strm).ToList();

            var headerRow = csv[0];
            var current   = headerRow.IndexOf("CURRENT");
            var prev      = headerRow.IndexOf("PREVIOUS");
            var weight    = headerRow.IndexOf("WEIGHT");

            var parties = headerRow.ToList();

            parties.Remove("CURRENT");
            parties.Remove("PREVIOUS");
            parties.Remove("WEIGHT");

            result.partyNames = parties;

            var partiesIndex = (from x in parties select headerRow.IndexOf(x)).ToList();

            for (int i = 1; i < csv.Count; i++)
            {
                var row = csv[i];

                List <double> rawScores = new List <double>();

                for (int j = 0; j < parties.Count; j++)
                {
                    rawScores.Add(double.Parse(row[partiesIndex[j]]));
                }

                var actualVote = parties.IndexOf(row[current]);
                var prevVote   = parties.IndexOf(row[prev]);

                if (row[weight].Trim() == string.Empty)
                {
                    continue;
                }

                var currentWeight = double.Parse(row[weight]);

                var indicies = DiscreteMath.GetIntList(parties.Count);

                var preferenceOrder = (from x in indicies
                                       orderby(actualVote == x ? 1 : 0) descending, rawScores[x] descending, Rand.NextDouble() descending
                                       select x).ToList();

                var secondPreference = preferenceOrder[1];
                var thirdPreference  = preferenceOrder[2];

                var info = new PreferenceInformation();

                info.FirstIndex  = actualVote;
                info.SecondIndex = secondPreference;
                info.ThirdIndex  = thirdPreference;
                info.Weight      = currentWeight;

                result.preferenceInformation.Add(info);
            }

            return(result);
        }