Quick Start#
Now that you have installed pabutools (if not, see Installation), you can start using the package!
On this page, we will guide you through a simple example.
Describing an Election#
Let’s begin by describing an election. We need to encode at least the projects, the budget limit, and the ballots of the voters.
Projects and Instances#
The fundamental elements are the projects, i.e., the
entities that will be voted upon. We define them using the class
Project
.
from pabutools.election import Project
p1 = Project("p1", 1) # The constructor takes the name and cost of the project
p2 = Project("p2", 1)
p3 = Project("p3", 3)
Next, we define an instance, which is a collection of projects along with additional information about the election. It stores all the information regarding the election, except for what concerns the voters.
An instance is an instantiation of the Instance
class. This class derives from the Python set class and can be used as one.
from pabutools.election import Instance
instance = Instance() # There are many optional parameters
instance.add(p1) # Use set methods to populate
instance.update([p2, p3])
instance.budget_limit = 3 # The instance stores the budget limit for the projects
Importantly, any Python comparison between two projects (e.g., equality) is based on the name of the projects. Since an instance is a set, adding a project Project(“p”, 1) and another project Project(“p”, 3) will result in an instance with a single project.
Ballots and Profiles#
The next essential components of a participatory budgeting election are the ballots. A ballot stores all the information provided by a voter. All the ballots are gathered into a profile.
For this example, we assume that voters submitted approval ballots. They are instantiated
using the class ApprovalBallot
as follows:
from pabutools.election import ApprovalBallot
b1 = ApprovalBallot([p1, p2]) # Initialize an approval ballot with two projects
b1.add(p2) # Add projects to the approval ballot using set methods
b2 = ApprovalBallot({p1, p2, p3})
b3 = ApprovalBallot({p3})
The ApprovalBallot
class inherits
from the Python set and can be used as one.
We can now define the approval profile:
from pabutools.election import ApprovalProfile
profile = ApprovalProfile([b1, b2]) # Initialize the profile with two ballots
profile.append(b3) # Use list methods to handle the profile
The approval profile is instantiated using the class
ApprovalProfile
, which inherits from
the Python class list.
Computing the Outcome of an Election#
The election is ready; now, let’s compute the winning projects. For this purpose, we will
use the module rules
.
Assuming we want to use the standard greedy method, which is commonly used in many cities around the world, we can compute the outcome of the election as follows:
from pabutools.election import Cost_Sat
from pabutools.rules import greedy_utilitarian_welfare
outcome = greedy_utilitarian_welfare(instance, profile, sat_class=Cost_Sat)
This computes the outcome of the greedy approximation of the utilitarian welfare using
the satisfaction measure
Cost_Sat
.
Satisfaction measures have not been discussed yet. Keep in mind that they describe the way
voters are assumed to assess the quality of a set of projects. For instance,
Cost_Sat
measures the
satisfaction of a voter as the total cost of the projects that have been selected and
that appear in the voter’s ballot. For more information, check out
satisfaction
.
Other methods can be used, such as Phragmén’s sequential rule or the method of equal shares.
from pabutools.election import Cost_Sat
from pabutools.rules import sequential_phragmen, method_of_equal_shares
outcome1 = sequential_phragmen(instance, profile)
outcome2 = method_of_equal_shares(instance, profile, sat_class=Cost_Sat)
All rules return a BudgetAllocation
object.
The BudgetAllocation
class inherits from
list
and behave similarly. It is used to store additional information about the
outcome (for visualisation/explanation purposes).