/// <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); }
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); }