vse_sim.simulation
1import csv 2import os 3import random 4from uuid import uuid4 5 6from .debug_dump import debug, setDebug 7from .decorators import autoassign 8from .methods import ( 9 IRNR, 10 V321, 11 Borda, 12 BulletyApprovalWith, 13 Irv, 14 IrvPrime, 15 Mav, 16 Mj, 17 Plurality, 18 Rp, 19 Schulze, 20 Score, 21 Srv, 22) 23from .strategies import LazyChooser, OssChooser, ProbChooser, beHon, beStrat, beX, truth 24from .voter_models import PolyaModel # noqa: F401 - used by doctests 25 26 27def uniquify(seq): 28 # order preserving 29 checked = [] 30 for e in seq: 31 if e not in checked: 32 checked.append(e) 33 return checked 34 35 36class CsvBatch: 37 @autoassign 38 def __init__( 39 self, 40 model, 41 methods, 42 nvot, 43 ncand, 44 niter, 45 baseName=None, 46 media=truth, 47 seed=None, 48 force=False, 49 ): 50 """A harness function which creates niter elections from model and finds three kinds 51 of utility for all methods given. 52 53 for instance: 54 55 >>> csvs = CsvBatch(PolyaModel(), [[Score(), baseRuns], [Mav(), medianRuns]], nvot=5, ncand=4, niter=3) 56 >>> len(csvs.rows) 57 60 58 """ 59 rows = [] 60 emodel = str(model) 61 if seed is None: 62 seed = (baseName or "") + str(niter) 63 self.seed = seed 64 random.seed(seed) 65 try: 66 from git import Repo 67 68 repo = Repo(os.getcwd()) 69 if not force: 70 assert not repo.is_dirty() 71 self.repo_version = repo.head.commit.hexsha 72 except Exception: 73 self.repo_version = "unknown repo version" 74 for i in range(niter): 75 eid = uuid4() 76 electorate = model(nvot, ncand) 77 for method, chooserFuns in methods: 78 results = method.resultsTable( 79 eid, emodel, ncand, electorate, chooserFuns, media=media 80 ) 81 rows.extend(results) 82 debug(i, results[1:3]) 83 self.rows = rows 84 if baseName: 85 self.saveFile(baseName) 86 87 def saveFile(self, baseName="SimResults"): 88 """print the result of doVse in an accessible format. 89 for instance: 90 91 csvs.saveFile() 92 """ 93 i = 1 94 while os.path.isfile(baseName + str(i) + ".csv"): 95 i += 1 96 keys = ["vse", "method", "chooser", *list(self.rows[0].keys())] 97 for n in range(4): 98 keys.extend([f"tallyName{str(n)}", f"tallyVal{str(n)}"]) 99 keys = uniquify(keys) 100 path = baseName + str(i) + ".csv" 101 with open(path, "w") as myFile: 102 print( 103 f"# {dict(media=self.media.__name__, version=self.repo_version, seed=self.seed, model=self.model, methods=self.methods, nvot=self.nvot, ncand=self.ncand, niter=self.niter)}", 104 file=myFile, 105 ) 106 107 dw = csv.DictWriter(myFile, keys, restval="NA") 108 dw.writeheader() 109 for r in self.rows: 110 dw.writerow(r) 111 return path 112 113 @property 114 def results(self): 115 """Return this batch as a pandas-backed ``VseResults`` object.""" 116 from .dataframe import VseResults 117 118 return VseResults.from_rows(self.rows) 119 120 @property 121 def dataframe(self): 122 """Return this batch's rows as a pandas DataFrame.""" 123 return self.to_dataframe() 124 125 @property 126 def df(self): 127 """Alias for ``dataframe``.""" 128 return self.dataframe 129 130 def to_dataframe(self, copy=True): 131 """Return this batch's rows as a pandas DataFrame.""" 132 return self.results.to_dataframe(copy=copy) 133 134 def summarize(self, group_by=("method", "chooser"), sort_by="mean_vse", ascending=False): 135 """Return a pandas DataFrame summarizing VSE scores for this batch.""" 136 return self.results.summarize( 137 group_by=group_by, 138 sort_by=sort_by, 139 ascending=ascending, 140 ) 141 142 def report(self, group_by=("method", "chooser")): 143 """Return common pandas report tables for this batch.""" 144 return self.results.report(group_by=group_by) 145 146 def plot_vse(self, *args, **kwargs): 147 """Plot summarized VSE scores for this batch.""" 148 return self.results.plot_vse(*args, **kwargs) 149 150 151medianRuns = [ 152 OssChooser([beHon, ProbChooser([(1 / 2, beStrat), (1 / 2, beHon)])]), 153 ProbChooser([(1 / 4, beX), (3 / 4, beHon)]), 154 ProbChooser([(1 / 2, beX), (1 / 2, beHon)]), 155 ProbChooser([(3 / 4, beX), (1 / 4, beHon)]), 156 ProbChooser([(0.5, beStrat), (0.5, beHon)]), 157 ProbChooser([(1 / 3, beStrat), (1 / 3, beHon), (1 / 3, beX)]), 158 LazyChooser(), 159 ProbChooser([(1 / 2, LazyChooser()), (1 / 2, beHon)]), 160] 161 162baseRuns = [ 163 OssChooser([beHon, ProbChooser([(1 / 2, beStrat), (1 / 2, beHon)])]), 164 ProbChooser([(1 / 4, beStrat), (3 / 4, beHon)]), 165 ProbChooser([(1 / 2, beStrat), (1 / 2, beHon)]), 166 ProbChooser([(3 / 4, beStrat), (1 / 4, beHon)]), 167] 168 169allSystems = [ 170 [Score(1000), baseRuns], 171 [Score(10), baseRuns], 172 [Score(2), baseRuns], 173 [Score(1), baseRuns], 174 [BulletyApprovalWith(0.6), baseRuns], 175 [Srv(10), baseRuns], 176 [Srv(2), baseRuns], 177 [Plurality(), baseRuns], 178 [Borda(), baseRuns], 179 [Irv(), baseRuns], 180 [IrvPrime(), baseRuns], 181 [Schulze(), baseRuns], 182 [Rp(), baseRuns], 183 [V321(), baseRuns], 184 [Mav(), medianRuns], 185 [Mj(), medianRuns], 186 [IRNR(), baseRuns], 187] 188 189# request from Mark: "SRV0-2, SRV0-3, SRV0-4, SRV0-5, SRV0-6, SRV0-7, SRV0-8, SRV0-9, SRV0-10, Score0-10, 321, Approval, IRV and plurality" 190markMethods = [ 191 [Srv(2), baseRuns], 192 [Srv(3), baseRuns], 193 [Srv(4), baseRuns], 194 [Srv(5), baseRuns], 195 [Srv(6), baseRuns], 196 [Srv(7), baseRuns], 197 [Srv(8), baseRuns], 198 [Srv(9), baseRuns], 199 [Score(10), baseRuns], 200 [V321(), baseRuns], 201 [BulletyApprovalWith(0.6), baseRuns], 202 [Irv(), baseRuns], 203 [Plurality(), baseRuns], 204] 205 206 207def run_simulation( 208 model, 209 methods, 210 nvot, 211 ncand, 212 niter, 213 baseName=None, 214 media=truth, 215 seed=None, 216 force=False, 217): 218 """Run a simulation and return a pandas-backed ``VseResults`` object.""" 219 batch = CsvBatch( 220 model, 221 methods, 222 nvot=nvot, 223 ncand=ncand, 224 niter=niter, 225 baseName=baseName, 226 media=media, 227 seed=seed, 228 force=force, 229 ) 230 return batch.results 231 232 233def run_simulation_dataframe(*args, **kwargs): 234 """Run a simulation and return its result rows as a pandas DataFrame.""" 235 return run_simulation(*args, **kwargs).dataframe 236 237 238__all__ = [ 239 "CsvBatch", 240 "allSystems", 241 "baseRuns", 242 "markMethods", 243 "medianRuns", 244 "run_simulation", 245 "run_simulation_dataframe", 246 "uniquify", 247] 248 249# usage example: 250# >>> from vse import * 251# >>> vses = CsvBatch(KSModel(dcdecay=(1,3),wcdecay=(1.5,3), dccut = .2, wcalpha=1.5), 252# allSystems, nvot=40, ncand=6, niter=15000, baseName="target", 253# media=fuzzyMediaFor()) 254 255if __name__ == "__main__": 256 import doctest 257 258 setDebug(False) 259 doctest.testmod()
class
CsvBatch:
37class CsvBatch: 38 @autoassign 39 def __init__( 40 self, 41 model, 42 methods, 43 nvot, 44 ncand, 45 niter, 46 baseName=None, 47 media=truth, 48 seed=None, 49 force=False, 50 ): 51 """A harness function which creates niter elections from model and finds three kinds 52 of utility for all methods given. 53 54 for instance: 55 56 >>> csvs = CsvBatch(PolyaModel(), [[Score(), baseRuns], [Mav(), medianRuns]], nvot=5, ncand=4, niter=3) 57 >>> len(csvs.rows) 58 60 59 """ 60 rows = [] 61 emodel = str(model) 62 if seed is None: 63 seed = (baseName or "") + str(niter) 64 self.seed = seed 65 random.seed(seed) 66 try: 67 from git import Repo 68 69 repo = Repo(os.getcwd()) 70 if not force: 71 assert not repo.is_dirty() 72 self.repo_version = repo.head.commit.hexsha 73 except Exception: 74 self.repo_version = "unknown repo version" 75 for i in range(niter): 76 eid = uuid4() 77 electorate = model(nvot, ncand) 78 for method, chooserFuns in methods: 79 results = method.resultsTable( 80 eid, emodel, ncand, electorate, chooserFuns, media=media 81 ) 82 rows.extend(results) 83 debug(i, results[1:3]) 84 self.rows = rows 85 if baseName: 86 self.saveFile(baseName) 87 88 def saveFile(self, baseName="SimResults"): 89 """print the result of doVse in an accessible format. 90 for instance: 91 92 csvs.saveFile() 93 """ 94 i = 1 95 while os.path.isfile(baseName + str(i) + ".csv"): 96 i += 1 97 keys = ["vse", "method", "chooser", *list(self.rows[0].keys())] 98 for n in range(4): 99 keys.extend([f"tallyName{str(n)}", f"tallyVal{str(n)}"]) 100 keys = uniquify(keys) 101 path = baseName + str(i) + ".csv" 102 with open(path, "w") as myFile: 103 print( 104 f"# {dict(media=self.media.__name__, version=self.repo_version, seed=self.seed, model=self.model, methods=self.methods, nvot=self.nvot, ncand=self.ncand, niter=self.niter)}", 105 file=myFile, 106 ) 107 108 dw = csv.DictWriter(myFile, keys, restval="NA") 109 dw.writeheader() 110 for r in self.rows: 111 dw.writerow(r) 112 return path 113 114 @property 115 def results(self): 116 """Return this batch as a pandas-backed ``VseResults`` object.""" 117 from .dataframe import VseResults 118 119 return VseResults.from_rows(self.rows) 120 121 @property 122 def dataframe(self): 123 """Return this batch's rows as a pandas DataFrame.""" 124 return self.to_dataframe() 125 126 @property 127 def df(self): 128 """Alias for ``dataframe``.""" 129 return self.dataframe 130 131 def to_dataframe(self, copy=True): 132 """Return this batch's rows as a pandas DataFrame.""" 133 return self.results.to_dataframe(copy=copy) 134 135 def summarize(self, group_by=("method", "chooser"), sort_by="mean_vse", ascending=False): 136 """Return a pandas DataFrame summarizing VSE scores for this batch.""" 137 return self.results.summarize( 138 group_by=group_by, 139 sort_by=sort_by, 140 ascending=ascending, 141 ) 142 143 def report(self, group_by=("method", "chooser")): 144 """Return common pandas report tables for this batch.""" 145 return self.results.report(group_by=group_by) 146 147 def plot_vse(self, *args, **kwargs): 148 """Plot summarized VSE scores for this batch.""" 149 return self.results.plot_vse(*args, **kwargs)
@autoassign
CsvBatch( model, methods, nvot, ncand, niter, baseName=None, media=<function truth>, seed=None, force=False)
38 @autoassign 39 def __init__( 40 self, 41 model, 42 methods, 43 nvot, 44 ncand, 45 niter, 46 baseName=None, 47 media=truth, 48 seed=None, 49 force=False, 50 ): 51 """A harness function which creates niter elections from model and finds three kinds 52 of utility for all methods given. 53 54 for instance: 55 56 >>> csvs = CsvBatch(PolyaModel(), [[Score(), baseRuns], [Mav(), medianRuns]], nvot=5, ncand=4, niter=3) 57 >>> len(csvs.rows) 58 60 59 """ 60 rows = [] 61 emodel = str(model) 62 if seed is None: 63 seed = (baseName or "") + str(niter) 64 self.seed = seed 65 random.seed(seed) 66 try: 67 from git import Repo 68 69 repo = Repo(os.getcwd()) 70 if not force: 71 assert not repo.is_dirty() 72 self.repo_version = repo.head.commit.hexsha 73 except Exception: 74 self.repo_version = "unknown repo version" 75 for i in range(niter): 76 eid = uuid4() 77 electorate = model(nvot, ncand) 78 for method, chooserFuns in methods: 79 results = method.resultsTable( 80 eid, emodel, ncand, electorate, chooserFuns, media=media 81 ) 82 rows.extend(results) 83 debug(i, results[1:3]) 84 self.rows = rows 85 if baseName: 86 self.saveFile(baseName)
A harness function which creates niter elections from model and finds three kinds of utility for all methods given.
for instance:
>>> csvs = CsvBatch(PolyaModel(), [[Score(), baseRuns], [Mav(), medianRuns]], nvot=5, ncand=4, niter=3)
>>> len(csvs.rows)
60
def
saveFile(self, baseName='SimResults'):
88 def saveFile(self, baseName="SimResults"): 89 """print the result of doVse in an accessible format. 90 for instance: 91 92 csvs.saveFile() 93 """ 94 i = 1 95 while os.path.isfile(baseName + str(i) + ".csv"): 96 i += 1 97 keys = ["vse", "method", "chooser", *list(self.rows[0].keys())] 98 for n in range(4): 99 keys.extend([f"tallyName{str(n)}", f"tallyVal{str(n)}"]) 100 keys = uniquify(keys) 101 path = baseName + str(i) + ".csv" 102 with open(path, "w") as myFile: 103 print( 104 f"# {dict(media=self.media.__name__, version=self.repo_version, seed=self.seed, model=self.model, methods=self.methods, nvot=self.nvot, ncand=self.ncand, niter=self.niter)}", 105 file=myFile, 106 ) 107 108 dw = csv.DictWriter(myFile, keys, restval="NA") 109 dw.writeheader() 110 for r in self.rows: 111 dw.writerow(r) 112 return path
print the result of doVse in an accessible format. for instance:
csvs.saveFile()
results
114 @property 115 def results(self): 116 """Return this batch as a pandas-backed ``VseResults`` object.""" 117 from .dataframe import VseResults 118 119 return VseResults.from_rows(self.rows)
Return this batch as a pandas-backed VseResults object.
dataframe
121 @property 122 def dataframe(self): 123 """Return this batch's rows as a pandas DataFrame.""" 124 return self.to_dataframe()
Return this batch's rows as a pandas DataFrame.
def
to_dataframe(self, copy=True):
131 def to_dataframe(self, copy=True): 132 """Return this batch's rows as a pandas DataFrame.""" 133 return self.results.to_dataframe(copy=copy)
Return this batch's rows as a pandas DataFrame.
def
summarize( self, group_by=('method', 'chooser'), sort_by='mean_vse', ascending=False):
135 def summarize(self, group_by=("method", "chooser"), sort_by="mean_vse", ascending=False): 136 """Return a pandas DataFrame summarizing VSE scores for this batch.""" 137 return self.results.summarize( 138 group_by=group_by, 139 sort_by=sort_by, 140 ascending=ascending, 141 )
Return a pandas DataFrame summarizing VSE scores for this batch.
allSystems =
[[<vse_sim.Score.<locals>.Score0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Score.<locals>.Score0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Score.<locals>.Score0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Score.<locals>.Score0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.BulletyApprovalWith.<locals>.BulletyApproval object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Plurality object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Borda object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Irv object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.IrvPrime object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Schulze object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Rp object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.V321 object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Mav object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.LazyChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Mj object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.LazyChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.IRNR object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]]]
baseRuns =
[<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]
markMethods =
[[<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Srv.<locals>.Srv0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Score.<locals>.Score0to object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.V321 object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.BulletyApprovalWith.<locals>.BulletyApproval object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Irv object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]], [<vse_sim.Plurality object>, [<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>]]]
medianRuns =
[<vse_sim.OssChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.ProbChooser object>, <vse_sim.LazyChooser object>, <vse_sim.ProbChooser object>]
def
run_simulation( model, methods, nvot, ncand, niter, baseName=None, media=<function truth>, seed=None, force=False):
208def run_simulation( 209 model, 210 methods, 211 nvot, 212 ncand, 213 niter, 214 baseName=None, 215 media=truth, 216 seed=None, 217 force=False, 218): 219 """Run a simulation and return a pandas-backed ``VseResults`` object.""" 220 batch = CsvBatch( 221 model, 222 methods, 223 nvot=nvot, 224 ncand=ncand, 225 niter=niter, 226 baseName=baseName, 227 media=media, 228 seed=seed, 229 force=force, 230 ) 231 return batch.results
Run a simulation and return a pandas-backed VseResults object.
def
run_simulation_dataframe(*args, **kwargs):
234def run_simulation_dataframe(*args, **kwargs): 235 """Run a simulation and return its result rows as a pandas DataFrame.""" 236 return run_simulation(*args, **kwargs).dataframe
Run a simulation and return its result rows as a pandas DataFrame.
def
uniquify(seq):