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