Gerrymandering using Constraint Programming
Alireza Soroudi, PhD
Lead Data Scientist @ bluecrux || SMIEEE || Optimization expert in Supply chain management|| Healthcare management || Lab Digitalization || Power and Energy systems || Developer || Author / Speaker || (views are mine)
As the U.S. presidential election approaches, the buzz around gerrymandering grows louder. Gerrymandering—the crafty art of redrawing electoral districts to tip the scales in favor of a particular party—is as intriguing as it is controversial. But what if we could use constraint programming to simulate and understand this phenomenon? Let's embark on a computational adventure to see how this can happen!
Let's assume we know the votes of individuals based on their locations. The question is how to manipulate the electoral district boundaries to advantage a party, group, or socioeconomic class within the constituency.
As usual, I try to demonstrate it using a simplified example:
The sample population size is 50 (20 people will vote for yellow party and 30 people will vote for grey party).
There should be 5 districts (for simplicity they should be of the same size = 10)
Some ways of districting is as follows: in all these cases the grey party wins.
Is there any way we can help the yellow party win the election ?
Problem requirements
Problem Formulation
Winr Binary variable region r won by yellow
Anr Binary variable assigning cell n to region r
Snr Binary variable assigning cell n to region r as the source
flow_{n,j,r} Integer variable moving from cell n to cell j to region r
Python code:
def main() -> None:
# Creates the model.
model = cp_model.CpModel()
assign = {(n,r): model.NewBoolVar(f"assign_{n}_{r}") for n in nodes
for r in regions}
source = {(n,r): model.NewBoolVar(f"source_{n}_{r}") for n in nodes
for r in regions}
win = {r: model.NewBoolVar( f"win_{r}")
for r in regions}
flow = {(i,j,r): model.NewIntVar(0,10,f"flow_{i}_{j}_{r}") for i in nodes
for j in nodes for r in regions if check(i,j,data)}
for r in regions:
expressions = [source[n,r] for n in nodes]
model.AddExactlyOne(expressions)
expressions_assign = [assign[n,r] for n in nodes]
model.Add(sum(expressions_assign) == 10)
expressions_winD = [assign[n,r] for n in nodes if data[n][2]==0]
expressions_winR = [assign[n,r] for n in nodes if data[n][2]==1]
model.Add(sum(expressions_winD) != sum(expressions_winR))
model.Add(sum(expressions_winD) > sum(expressions_winR)).OnlyEnforceIf(win[r])
model.Add(sum(expressions_winD) < sum(expressions_winR)).OnlyEnforceIf(win[r].Not())
for n in nodes:
expressions_nodal = [source[n,r] for r in regions]
model.AddAtMostOne(expressions_nodal)
expressions_assign = [assign[n,r] for r in regions]
model.Add(sum(expressions_assign) ==1)
for (n,r) in assign:
model.Add( 10*source[n,r] - assign[n,r] == sum(flow[n,j,r]-flow[j,n,r] for j in nodes if check(n,j,data) ) )
model.Add(source[n,r]<= assign[n,r])
for (i,j,r) in flow:
model.Add(flow[i,j,r] <= 10*assign[i,r])
model.Add(flow[i,j,r] <= 10*assign[j,r])
model.Add(sum(win[r] for r in regions)== 0)
solver = cp_model.CpSolver()
solver.parameters.subsolvers[:] = ['core', 'pseudo_costs', 'no_lp']
solver.parameters.max_time_in_seconds = 1200
solver.parameters.num_search_workers = 4
status = solver.solve(model)
print(solver.StatusName(status))
print(solver.ObjectiveValue(), solver.BestObjectiveBound())
Results:
Let's make the grey party winner by 3 to 2
Let's make the grey party winner by 4 to 1
Let's make the yellow party winner by 3 to 2
But what if we are now allowed to put two cells too far away in a region ?
max allowed distance = 5 cells
We can add more constraints to avoid this situation:
Gerrymandering can significantly impact election outcomes and is a topic of ongoing debate regarding its fairness and effect on democratic representation.
Gerrymandering is more than just a political strategy; it's a fascinating problem that sits at the intersection of mathematics, computer science, and ethics. By using constraint programming, we can not only understand how gerrymandering happens but also explore ways to detect and prevent it.
Your post inspired us to write an article about using a redistricting model to either aggregate communities of interest or gerrymander districts, depending on your interpretation. See https://www.solvermax.com/blog/gerrymandering-made-easy
PhD, Industrial Engineering. Operations Research & Data Science. Mathematical and Statistical modeling. Supply Chain & Logistics
1 个月Thank you for sharing. Just one thing to point out that it’d be better if you state the variables and the space the defined on before stating the constraints
International vagabond and vagrant at sprachspiegel.com, Economist and translator - Fisheries Economics Advisor
1 个月you may find this paper to be relevant https://alandmiller.com/bizarreness.pdf
Postdoctoral Researcher, Reliability and Maintenance Engineering
1 个月Interesting
Solving Unsolvable Problems
1 个月Excellent subject. My former student Harm Manders suggested this to me years ago.