diff --git a/docs/_modules/pabutools/analysis/category.html b/docs/_modules/pabutools/analysis/category.html index 81b87ff6..8c848068 100644 --- a/docs/_modules/pabutools/analysis/category.html +++ b/docs/_modules/pabutools/analysis/category.html @@ -324,7 +324,9 @@

Source code for pabutools.analysis.category

                 app_cost_per_category[category] += project.cost
         for category in categories:
             proportional_app_cost_per_category[category] += (
-                app_cost_per_category[category] / app_total_cost * profile.multiplicity(ballot)
+                app_cost_per_category[category]
+                / app_total_cost
+                * profile.multiplicity(ballot)
             )
     for category in categories:
         proportional_app_cost_per_category[category] /= profile.num_ballots()
diff --git a/docs/_modules/pabutools/analysis/votersatisfaction.html b/docs/_modules/pabutools/analysis/votersatisfaction.html
index cdbc9ef3..03945931 100644
--- a/docs/_modules/pabutools/analysis/votersatisfaction.html
+++ b/docs/_modules/pabutools/analysis/votersatisfaction.html
@@ -424,7 +424,7 @@ 

Source code for pabutools.analysis.votersatisfaction

hist_data[-1] += sat_profile.multiplicity(ballot) else: hist_data[ - math.ceil(satisfaction*(num_bins-1)/max_satisfaction) + math.ceil(satisfaction * (num_bins - 1) / max_satisfaction) ] += sat_profile.multiplicity(ballot) for i in range(len(hist_data)): hist_data[i] = hist_data[i] / profile.num_ballots() diff --git a/docs/_modules/pabutools/election/instance.html b/docs/_modules/pabutools/election/instance.html index 7596d96f..8a50e932 100644 --- a/docs/_modules/pabutools/election/instance.html +++ b/docs/_modules/pabutools/election/instance.html @@ -367,7 +367,9 @@

Source code for pabutools.election.instance

     return sum(p.cost for p in projects)
-
[docs]def max_budget_allocation_cardinality(projects: Iterable[Project], budget_limit: Number) -> int: +
[docs]def max_budget_allocation_cardinality( + projects: Iterable[Project], budget_limit: Number +) -> int: """ Returns the maximum number of projects that can be chosen with respect to the budget limit. @@ -396,7 +398,9 @@

Source code for pabutools.election.instance

     return selected
-
[docs]def max_budget_allocation_cost(projects: Iterable[Project], budget_limit: Number) -> Number: +
[docs]def max_budget_allocation_cost( + projects: Iterable[Project], budget_limit: Number +) -> Number: """ Returns the maximum total cost over all subsets of projects with respect to the budget limit. @@ -420,9 +424,7 @@

Source code for pabutools.election.instance

     }
     if p_vars:
         mip_model.objective = maximize(xsum(p_vars[p] * p.cost for p in projects))
-        mip_model += (
-            xsum(p_vars[p] * p.cost for p in projects) <= budget_limit
-        )
+        mip_model += xsum(p_vars[p] * p.cost for p in projects) <= budget_limit
         mip_model.optimize()
         max_cost = mip_model.objective.x
         return frac(max_cost)
diff --git a/docs/_modules/pabutools/election/pabulib.html b/docs/_modules/pabutools/election/pabulib.html
index d7f43fc2..dd98db19 100644
--- a/docs/_modules/pabutools/election/pabulib.html
+++ b/docs/_modules/pabutools/election/pabulib.html
@@ -277,7 +277,7 @@ 

Source code for pabutools.election.pabulib

     CumulativeProfile,
     AbstractCumulativeProfile,
     OrdinalProfile,
-    AbstractOrdinalProfile
+    AbstractOrdinalProfile,
 )
 
 import urllib.request
@@ -531,6 +531,7 @@ 

Source code for pabutools.election.pabulib

         file_path: str
             The path to the output file.
     """
+
     def update_meta_value(meta_dict, inst_meta, field, mandatory=False):
         if field in inst_meta:
             meta_dict[field] = inst_meta[field]
@@ -664,10 +665,15 @@ 

Source code for pabutools.election.pabulib

             f.write(f"{key};{value}\n")
         f.write("PROJECTS\n" + ";".join(project_keys) + "\n")
         for project_dict in project_dicts:
-            f.write(";".join([str(project_dict.get(key, "None")) for key in project_keys]) + "\n")
+            f.write(
+                ";".join([str(project_dict.get(key, "None")) for key in project_keys])
+                + "\n"
+            )
         f.write("VOTES\n" + ";".join(vote_keys) + "\n")
         for vote_dict in vote_dicts:
-            f.write(";".join([str(vote_dict.get(key, "None")) for key in vote_keys]) + "\n")
+            f.write(
+                ";".join([str(vote_dict.get(key, "None")) for key in vote_keys]) + "\n"
+            )
 
diff --git a/docs/_modules/pabutools/election/satisfaction/additivesatisfaction.html b/docs/_modules/pabutools/election/satisfaction/additivesatisfaction.html index f4bdf9f2..9884948e 100644 --- a/docs/_modules/pabutools/election/satisfaction/additivesatisfaction.html +++ b/docs/_modules/pabutools/election/satisfaction/additivesatisfaction.html @@ -268,7 +268,13 @@

Source code for pabutools.election.satisfaction.additivesatisfaction

AbstractApprovalBallot, AbstractCardinalBallot, ) -from pabutools.election.instance import Instance, Project, total_cost, max_budget_allocation_cardinality, max_budget_allocation_cost +from pabutools.election.instance import ( + Instance, + Project, + total_cost, + max_budget_allocation_cardinality, + max_budget_allocation_cost, +) from pabutools.fractions import frac from typing import TYPE_CHECKING @@ -496,7 +502,11 @@

Source code for pabutools.election.satisfaction.additivesatisfaction

[docs] def preprocessing( self, instance: Instance, profile: AbstractProfile, ballot: AbstractBallot ): - return {"max_budget_allocation_card": max_budget_allocation_cardinality(ballot, instance.budget_limit)}
+ return { + "max_budget_allocation_card": max_budget_allocation_cardinality( + ballot, instance.budget_limit + ) + }
def cost_sat_func( @@ -616,7 +626,11 @@

Source code for pabutools.election.satisfaction.additivesatisfaction

[docs] def preprocessing( self, instance: Instance, profile: AbstractProfile, ballot: AbstractBallot ): - return {"max_budget_allocation_cost": max_budget_allocation_cost(ballot, instance.budget_limit)}
+ return { + "max_budget_allocation_cost": max_budget_allocation_cost( + ballot, instance.budget_limit + ) + }
def relative_cost_approx_normaliser_sat_func( @@ -651,9 +665,7 @@

Source code for pabutools.election.satisfaction.additivesatisfaction

""" if precomputed_values["normalizer"] == 0: return 0 - return frac( - int(project in ballot) * project.cost, precomputed_values["normalizer"] - ) + return frac(int(project in ballot) * project.cost, precomputed_values["normalizer"])
[docs]class Relative_Cost_Approx_Normaliser_Sat(AdditiveSatisfaction): @@ -683,7 +695,9 @@

Source code for pabutools.election.satisfaction.additivesatisfaction

[docs] def preprocessing( self, instance: Instance, profile: AbstractProfile, ballot: AbstractBallot ): - return {"normalizer": min(total_cost([p for p in ballot]), instance.budget_limit)}
+ return { + "normalizer": min(total_cost([p for p in ballot]), instance.budget_limit) + } def effort_sat_func( diff --git a/docs/_modules/pabutools/election/satisfaction/satisfactionprofile.html b/docs/_modules/pabutools/election/satisfaction/satisfactionprofile.html index 9c3c2f45..e113149e 100644 --- a/docs/_modules/pabutools/election/satisfaction/satisfactionprofile.html +++ b/docs/_modules/pabutools/election/satisfaction/satisfactionprofile.html @@ -300,14 +300,16 @@

Source code for pabutools.election.satisfaction.satisfactionprofile

---------- instance : :py:class:`~pabutools.election.instance.Instance` The instance corresponding to the satisfaction profile. + sat_class : type[:py:class:`~pabutools.election.satisfaction.satisfactionmeasure.SatisfactionMeasure`] + The satisfaction class used to generate the satisfaction profile. """ def __init__( - self, - init: Iterable[SatisfactionMeasure] = (), - instance: Instance = None, - profile: Profile = None, - sat_class: type[SatisfactionMeasure] = None, + self, + init: Iterable[SatisfactionMeasure] = (), + instance: Instance = None, + profile: Profile = None, + sat_class: type[SatisfactionMeasure] = None, ) -> None: list.__init__(self, init) GroupSatisfactionMeasure.__init__(self) @@ -331,9 +333,13 @@

Source code for pabutools.election.satisfaction.satisfactionprofile

) else: self.extend_from_profile(profile, sat_class) + if sat_class is None and isinstance(init, SatisfactionProfile): + self.sat_class = init.sat_class + else: + self.sat_class = sat_class
[docs] def extend_from_profile( - self, profile: Profile, sat_class: type[SatisfactionMeasure] + self, profile: Profile, sat_class: type[SatisfactionMeasure] ) -> None: """ Extends the satisfaction profile with the profile passed as argument using the satisfaction class passed as @@ -373,6 +379,7 @@

Source code for pabutools.election.satisfaction.satisfactionprofile

result = getattr(super(cls, self), name)(*args) if isinstance(result, list) and not isinstance(result, cls): result = cls(result, instance=self.instance) + result.sat_class = self.sat_class return result inner.fn_name = name @@ -425,27 +432,33 @@

Source code for pabutools.election.satisfaction.satisfactionprofile

A satisfaction class to use for converting a potentially given profile. Can only be used if either the `profile` or the `multiprofile` argument are also used. Note that we need here the class of the satisfaction measure, and not an instance of it. + inner_sat_class : type[:py:class:`~pabutools.election.satisfaction.satisfactionmeasure.SatisfactionMeasure`] + The satisfaction class that needs to be stored in the `sat_class` attribute. Rarely useful (but needed for + deepcopy). Attributes ---------- instance : :py:class:`~pabutools.election.instance.Instance` The instance corresponding to the satisfaction profile. + sat_class : type[:py:class:`~pabutools.election.satisfaction.satisfactionmeasure.SatisfactionMeasure`] + The satisfaction class used to generate the satisfaction profile. """ def __init__( - self, - init: Iterable[SatisfactionMeasure] | dict[SatisfactionMeasure, int] = None, - instance: Instance = None, - profile: Profile = None, - multiprofile: MultiProfile = None, - sat_class: type[SatisfactionMeasure] = None, + self, + init: Iterable[SatisfactionMeasure] | dict[SatisfactionMeasure, int] = None, + instance: Instance = None, + profile: Profile = None, + multiprofile: MultiProfile = None, + sat_class: type[SatisfactionMeasure] = None, + inner_sat_class: type[SatisfactionMeasure] = None ) -> None: if init is None: init = {} Counter.__init__(self, init) GroupSatisfactionMeasure.__init__(self) if instance is None: - if isinstance(init, SatisfactionMultiProfile): + if isinstance(init, SatisfactionMultiProfile) or isinstance(init, SatisfactionProfile): instance = init.instance elif profile and profile.instance: instance = profile.instance @@ -471,9 +484,16 @@

Source code for pabutools.election.satisfaction.satisfactionprofile

self.extend_from_profile(profile, sat_class) if multiprofile is not None: self.extend_from_multiprofile(multiprofile, sat_class) + if inner_sat_class: + self.sat_class = inner_sat_class + else: + if sat_class is None and (isinstance(init, SatisfactionMultiProfile) or isinstance(init, SatisfactionProfile)): + self.sat_class = init.sat_class + else: + self.sat_class = sat_class
[docs] def extend_from_profile( - self, profile: Profile, sat_class: type[SatisfactionMeasure] + self, profile: Profile, sat_class: type[SatisfactionMeasure] ) -> None: """ Extends the satisfaction multiprofile with the profile passed as argument using the satisfaction class passed as @@ -504,7 +524,7 @@

Source code for pabutools.election.satisfaction.satisfactionprofile

self[element] = 1
[docs] def extend_from_multiprofile( - self, profile: MultiProfile, sat_class: type[SatisfactionMeasure] + self, profile: MultiProfile, sat_class: type[SatisfactionMeasure] ) -> None: """ Extends the satisfaction multiprofile with the multiprofile passed as argument using the satisfaction class @@ -537,6 +557,7 @@

Source code for pabutools.election.satisfaction.satisfactionprofile

result, instance=self.instance, ) + result.sat_class = self.sat_class return result inner.fn_name = name @@ -546,7 +567,7 @@

Source code for pabutools.election.satisfaction.satisfactionprofile

wrap_method_closure(n) def __reduce__(self): - return self.__class__, (dict(self), self.instance, None, None, None)
+ return self.__class__, (dict(self), self.instance, None, None, None, self.sat_class)
SatisfactionMultiProfile._wrap_methods( diff --git a/docs/genindex.html b/docs/genindex.html index 1e1b9b71..d79514d7 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -1540,6 +1540,12 @@

S

  • (Relative_Cost_Sat method)
  • (SatisfactionMeasure method) +
  • + +
  • sat_class (SatisfactionMultiProfile attribute) + +
  • satisfaction_histogram() (in module pabutools.analysis.votersatisfaction) @@ -1556,10 +1562,10 @@

    S

  • (CumulativeMultiProfile method)
  • -
  • sequential_phragmen() (in module pabutools.rules.phragmen) -
    • +
    • sequential_phragmen() (in module pabutools.rules.phragmen) +
    • setdefault() (ApprovalMultiProfile method)
        diff --git a/docs/objects.inv b/docs/objects.inv index e66a3d4a..851c1f72 100644 Binary files a/docs/objects.inv and b/docs/objects.inv differ diff --git a/docs/reference/election/satisfaction.html b/docs/reference/election/satisfaction.html index 61ca39d1..7565ee67 100644 --- a/docs/reference/election/satisfaction.html +++ b/docs/reference/election/satisfaction.html @@ -316,6 +316,7 @@

        Contents

      • SatisfactionMultiProfile