Advertisement
Guest User

Untitled

a guest
Mar 7th, 2015
39
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.45 KB | None | 0 0
  1. import numpy as np
  2. import random
  3. import scipy.stats as stats
  4. import itertools
  5.  
  6. class Main:
  7.     def __init__(self, threshold):
  8.         self.threshold = threshold
  9.  
  10.     def flatten(self, lst):
  11.         return [x for y in lst for x in y]
  12.  
  13.     def almost_int(self, x):
  14.         return abs(x - round(x))<=0.00001
  15.  
  16.     def bader_ofer_help(self, fractional_results):
  17.         parties = list(fractional_results) # give consistent order to parties
  18.         fractional_mand = np.array([fractional_results[party] for party in parties])
  19.         tot_mandates = fractional_mand.sum()
  20.         assert (self.almost_int(tot_mandates))
  21.         result = np.floor(fractional_mand)
  22.         leftover_mand = int(tot_mandates - result.sum())
  23.         print (tot_mandates, result.sum(), leftover_mand)
  24.         for i in range(leftover_mand):
  25.             bader_ofer_scores = fractional_mand / (result+1)
  26.             odef_winner = np.argmax(bader_ofer_scores)
  27.             result[odef_winner] += 1
  28.         result = {parties[i] : result[i] for i in range(len(result))}
  29.         return result
  30.  
  31.     def bader_ofer(self, unnorm_percs, unnorm_odafim):
  32.         tot_percs = sum(unnorm_percs.values())
  33.         percs = { party: unnorm_percs[party] * 120 / tot_percs for party in unnorm_percs }
  34.         odafim = set([ (x,y) for x,y in unnorm_odafim.items() if x in percs and y in percs ])
  35.         no_odafim = set(percs) - set(self.flatten(odafim))
  36.         bader_ofer_step1 = {party : percs[party] for party in no_odafim}
  37.         bader_ofer_step1.update({pair : percs[pair[0]] + percs[pair[1]] for pair in odafim })
  38.         step1_res = self.bader_ofer_help(bader_ofer_step1)
  39.         simu_result = {party : step1_res[party] for party in no_odafim}
  40.         for pair in odafim:
  41.             norm_factor2 = step1_res[pair] / (percs[pair[0]] + percs[pair[1]])
  42.             pair_bader_ofer = {party : percs[party] * norm_factor2 for party in pair}
  43.             simu_result.update(self.bader_ofer_help(pair_bader_ofer))
  44.         return simu_result
  45.  
  46.     def run_simulation(self, survey, odafim1, odafim2, sigma):
  47.         noise_multiplier = 0.05
  48.         #assert int(noise_multiplier) == noise_multiplier
  49.         #assert set(self.flatten(odafim)) <= set(survey)
  50.         #no_odafim = set(survey) - set(self.flatten(odafim))
  51.         parties = list(survey) # ordered list of parties
  52.         tot_mandates = sum(survey.values())
  53.         print ("total=",tot_mandates)
  54.         #assert int(tot_mandates) == tot_mandates
  55.         total = {party : list() for party in parties}
  56.         alt_gains = {party : list() for party in parties}
  57.         num_simulations = 10000
  58.         for _ in range(num_simulations):
  59.             noisy_survey = {}
  60.             lower = 0.0
  61.             upper = 1.0
  62.             shuffled_parties = [ p for p in survey if p != 'other' ]
  63.             random.shuffle(shuffled_parties)
  64.             while True:
  65.                 error = False
  66.                 for party in shuffled_parties:
  67.                     party_perc = survey[party]
  68.                     party_std = sigma[party] #np.sqrt(party_perc * (1 - party_perc) / 500) if sigma is None or party not in sigma else sigma[party]
  69.                     low = (lower - party_perc)/party_std
  70.                     upp = (upper - party_perc)/party_std
  71.                     noisy_survey[party] = stats.truncnorm.rvs(low, upp, loc = party_perc, scale = party_std)
  72.                     upper -= noisy_survey[party]
  73.                     if upper < 0:
  74.                         error = True
  75.                         break
  76.                 if not error:
  77.                     break
  78.             noisy_survey['other'] = 1 - sum(noisy_survey.values())
  79.             #print ("noisy", survey, noisy_survey)
  80.             assert all([v>=0 for v in noisy_survey.values()])
  81.             #norm_factor1 = tot_mandates / sum(noisy_survey.values())
  82.             #noisy_survey = {party : noisy_survey[party] * norm_factor1 for party in noisy_survey}
  83.             simu_result1 = self.perform_bader_ofer(noisy_survey, odafim1)
  84.             simu_result2 = self.perform_bader_ofer(noisy_survey, odafim2)
  85. ##            bader_ofer_step1 = {party : noisy_survey[party] for party in no_odafim}
  86. ##            bader_ofer_step1.update({pair : noisy_survey[pair[0]] + noisy_survey[pair[1]] for pair in odafim})
  87. ##            step1_res = bader_ofer(bader_ofer_step1)
  88. ##            simu_result = {party : step1_res[party] for party in no_odafim}
  89. ##            for pair in odafim:
  90. ##                norm_factor2 = step1_res[pair] / (noisy_survey[pair[0]] + noisy_survey[pair[1]])
  91. ##                pair_bader_ofer = {party : noisy_survey[party] * norm_factor2 for party in pair}
  92. ##                simu_result.update(bader_ofer(pair_bader_ofer))
  93.             for party in parties:
  94.                 total[party].append(simu_result1[party])
  95.                 alt_gains[party].append(simu_result2[party] - simu_result1[party])
  96.         result = {party : sum(total[party]) / num_simulations for party in parties}
  97.         total_gains = {party : sorted(alt_gains[party]) for party in parties}
  98.         return result, total_gains
  99.  
  100.     def compare_simulations(self, survey, odafim1, odafim2, sigma = None):    
  101.         normal_results, alt_gains = self.run_simulation(survey, odafim1, odafim2, sigma)
  102.         return alt_gains
  103.    
  104.     def perform_bader_ofer(self, percs, surplus_vote_agreements):
  105.         totalpercs = sum(percs.values())
  106.         ahuz_hasima = self.threshold * totalpercs
  107.         passed_votes = 0
  108.         notpassed_votes = 0
  109.         for party in percs.keys():
  110.             if party != 'other' and percs[party] >= ahuz_hasima:
  111.                 passed_votes += percs[party]
  112.             else:
  113.                 notpassed_votes += percs[party]
  114.    
  115.         moded = passed_votes / 120
  116.         mands = {}
  117.         for party, perc in percs.items():
  118.             if party != 'other' and perc >= ahuz_hasima:
  119.                 mands[party] = int(perc / moded)
  120.             else:
  121.                 mands[party] = 0
  122.  
  123.         #print (totalpercs, ahuz_hasima, mands)
  124.         leftover = 120 -  sum(mands.values())
  125.    
  126.         jointmands = {}
  127.         for party, mand in mands.items():
  128.             if party in surplus_vote_agreements.keys() or party in surplus_vote_agreements.values():
  129.                 for p1, p2 in surplus_vote_agreements.items():
  130.                     if p1 == party or p2 == party:
  131.                         jointparty = '+'.join([p1, p2])
  132.                         if p1 in mands and p2 in mands:
  133.                             jointmands[jointparty] = mands[p1] + mands[p2]
  134.                         elif p1 in mands:
  135.                             jointmands[jointparty] = mands[p1]
  136.                         elif p2 in mands:
  137.                             jointmands[jointparty] = mands[p2]
  138.                         else:
  139.                             jointmands[jointparty] = 0
  140.             else:
  141.                 jointmands[party] = mand
  142.    
  143.         partymodeds = {}
  144.         for party, perc in percs.items():
  145.             if party in surplus_vote_agreements.keys() or party in surplus_vote_agreements.values():
  146.                 for p1, p2 in surplus_vote_agreements.items():
  147.                     if p1 == party or p2 == party:
  148.                         jointparty = '+'.join([p1, p2])
  149.                         perc1 = percs[p1] if p1 in percs and percs[p1] >= ahuz_hasima else 0
  150.                         perc2 = percs[p2] if p2 in percs and percs[p2] >= ahuz_hasima else 0
  151.                         partymodeds[jointparty] = (perc1 + perc2) / (jointmands[jointparty] + 1)
  152.             else:
  153.                 if party != 'other' and perc >= ahuz_hasima:
  154.                     partymodeds[party] = perc / (mands[party] + 1)
  155.                 else:
  156.                     partymodeds[party] = 0
  157.    
  158.         given = {}
  159.         for i in range(0, leftover):
  160.             maxparty = None
  161.             for party, moded in partymodeds.items():
  162.                 if maxparty == None or partymodeds[party] > partymodeds[maxparty]:
  163.                     maxparty = party
  164.    
  165.             if maxparty in given:
  166.                 given[maxparty] += 1
  167.             else:
  168.                 given[maxparty] = 1
  169.    
  170.             jointmands[maxparty] += 1
  171.             if '+' in maxparty:
  172.                 parties = maxparty.split('+')
  173.                 perc1 = percs[parties[0]] if parties[0] in percs else 0
  174.                 perc2 = percs[parties[1]] if parties[1] in percs else 0
  175.                 partymodeds[maxparty] = (perc1 + perc2) / (jointmands[maxparty] + 1)
  176.             else:
  177.                 partymodeds[maxparty] = percs[maxparty] / (jointmands[maxparty] + 1)
  178.    
  179.         finalmands = {}
  180.         for party, mand in jointmands.items():
  181.             if '+' in party:
  182.                 parties = party.split('+')
  183.                 party1 = parties[0]
  184.                 party2 = parties[1]
  185.                 perc1 = percs[party1] if party1 in percs else 0
  186.                 perc2 = percs[party2] if party2 in percs else 0
  187.                 if jointmands[party] == 0:
  188.                     finalmands[party1] = 0
  189.                     finalmands[party2] = 0
  190.                 else:
  191.                     moded = (perc1 + perc2) / jointmands[party]
  192.                     mands1 = int(perc1 / moded)
  193.                     mands2 = int(perc2 / moded)
  194.                     finalmands[party1] = mands1
  195.                     finalmands[party2] = mands2
  196.                 if party in given  and (perc1 >= ahuz_hasima or perc2 >= ahuz_hasima):
  197.                     #print (party, given[party], mands1, mands2)
  198.                     togive = mand - mands1 - mands2
  199.                     for i in range(0, togive):
  200.                         moded1 = perc1 / (mands1 + 1)
  201.                         moded2 = perc2 / (mands2 + 1)
  202.                         if (moded1 > moded2 or finalmands[party2] == 0) and finalmands[party1] > 0:
  203.                             finalmands[party1] += 1
  204.                             mands1 += 1
  205.                         elif finalmands[party2] > 0:
  206.                             finalmands[party2] += 1
  207.                             mands2 += 1
  208.                 else:
  209.                     finalmands[party1] = mands[party1] if party1 in mands else 0
  210.                     finalmands[party2] = mands[party2] if party2 in mands else 0
  211.             else:
  212.                 finalmands[party] = mand
  213.    
  214.         if sum(finalmands.values()) != 120:
  215.             print ("percs", percs)
  216.             print ("surplus", surplus_vote_agreements)
  217.             print (sum(finalmands.values()), finalmands)
  218.         assert(sum(finalmands.values()) == 120)
  219.         return finalmands
  220.  
  221. surplus1 = {'likud': 'bayityehudi', 'kadima': 'amshalem', 'shas': 'yahadut', 'tenuah':'meretz', 'avoda':'yeshatid', 'hadash':'balad', 'dor':'tsedek' }
  222. percs1 = {'likud': 885163, 'yeshatid': 543458, 'avoda': 432118, 'bayityehudi': 345985, 'shas': 331868,
  223.          'yahadut': 195892, 'tenuah': 189167, 'meretz': 172403, 'raamtaal': 138450, 'hadash': 113439,
  224.          'balad': 97030, 'kadima': 78974}
  225. percs1['other'] = 3792742-sum(percs1.values())
  226. total = sum(percs1.values())
  227. #for party in percs:
  228. #    percs[party] /= total
  229.  
  230. m = Main(0.02)
  231. result1 = sorted(m.perform_bader_ofer(percs1, surplus1).items(), key=lambda x:x[1], reverse = True)
  232. result2 = m.bader_ofer(percs1, surplus1)
  233. for party, mands in result1:
  234.     print (party, mands, result2[party] if party in result2 else 0, mands - result2[party] if party in result2 else mands)
  235.  
  236. percs2= {'Habayit Hayehudi': 0.0902930187208, 'Yishai': 0.0352718824652, 'Koolanu': 0.0636297779456,
  237.          'Meretz': 0.0405248349533, 'Mahane Tzioni': 0.185939738678, 'Likud': 0.173951818714,
  238.          'Shas': 0.0556348566752, 'Joint': 0.0994893720348,
  239.          'Yahadut Hatorah': 0.0530899600436, 'Yisrael Beitenu': 0.003115436853772964, 'Yesh Atid': 0.0978238584891}
  240. sigma2= {'Habayit Hayehudi': 0.0026946387023503897, 'Yishai': 0.001980196402268915, 'Koolanu': 0.0032029934725094074,
  241.          'Meretz': 0.0015336773868115173, 'Mahane Tzioni': 0.004136856480205219, 'Likud': 0.0033931191177079393,
  242.          'Shas': 0.00249721964962137, 'Joint': 0.0019367576476034803,
  243.          'Yahadut Hatorah': 0.0011624738029221557, 'Yisrael Beitenu': 0.003115436853772964, 'Yesh Atid': 0.00390300273922642}
  244. percs2['other'] = 1 - sum(percs2.values())
  245. surplus2= {'Likud': 'Habayit Hayehudi', 'Shas': 'Yahadut Hatorah', 'Koolanu': 'Yisrael Beitenu', 'Meretz': 'Mahane Tzioni'}
  246. m = Main(0.0325)
  247. percs2b = dict([(party, percs2[party]*120) for party in percs2])
  248. for party, mands in sorted(m.perform_bader_ofer(percs2b, surplus2).items(), key=lambda x:x[1], reverse = True):
  249.     print (party, mands)
  250.  
  251. surplus2b= {'Likud': 'Habayit Hayehudi', 'Shas': 'Yahadut Hatorah', 'Koolanu': 'Yisrael Beitenu', 'Meretz': 'Joint', 'Yesh Atid':'Mahane Tzioni'}
  252. for party, gains in sorted(m.compare_simulations(percs2, surplus2, surplus2b, sigma2).items()):
  253.     print (party, sum(gains)/len(gains))
  254.     for key, group in itertools.groupby(gains):
  255.         print("-", key, len(list(group))/len(gains))
  256.  
  257. percs3={ 'Kadima': 758032, 'Likud': 729054, 'YisraelBeitenu':394577, 'Avoda':334900, 'Shas':286300, 'Yahadut':147954, 'RaamTaal':113954, 'IhudLeumi':112570, 'Bayityehudi':96765, 'Hadash':112130, 'Meretz':99611, 'Balad':83739 }
  258. surplus3={'Avoda':'Meretz', 'Likud':'YisraelBeitenu', 'Kadima':'Yerukim', 'Bayityehudi':'IhudLeumi', 'Gil':'Tsabar','Shas':'Yahadut','Hadash':'RaamTaal', 'YisraelHazaka':'YerukaMemad'}
  259. percs3['other'] = 3373490 - sum(percs3.values())
  260. m = Main(0.02)
  261. for party, mands in sorted(m.perform_bader_ofer(percs3, surplus3).items(), key=lambda x:x[1], reverse = True):
  262.     print (party, mands)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement