Skip to content
Tomer Naydnov
← All workEARLIER ENGINEERING / SOURCE STUDY

THE RULES BEHIND THE SOFTWARE

The Coalition Race

A policy-driven C++ simulation of agents, offers and coalition formation.

ENGINEERING / EXPLAINED
RECORDED FIXTURESTwo ways to finish.

Majority threshold: 61 of 120 mandates.

TRACE 01A majority forms.
A
50
B
70
TRACE 03Everyone joins. No majority.
A
60
B
60
Final states from committed tests/01.out and tests/03.out.
Parsed source records, not a new simulation.

Visualized from committed fixture data. Source review below.

CONTEXT
University coursework
MY ROLE
Sole developer
TIMELINE
2022
EVIDENCE
Source reviewed · illustrative diagrams

AT A GLANCE

A majority is not the only ending

A coursework simulation represents a 120-mandate parliament as a weighted graph. Agents choose neighboring parties to approach, parties collect and evaluate offers, and each joining party extends a coalition and creates a new agent. JSON snapshots make every simulation step inspectable.

My contribution +

I developed this project as university coursework. This case covers my implementation and the engineering decisions behind it.

WHAT THE SYSTEM HANDLES

The interesting parts.

01

Separate whom to approach from whom to join

Agent selection policies consider edge weight or party mandates. Party join policies choose the last offer or the offering coalition with the largest mandate total.

Implementation details
  • Policies are selected from JSON configuration.
  • Parties progress through Waiting, CollectingOffers and Joined states.
02

Grow a coalition through local decisions

Each simulation step advances agents and then parties. After a delayed offer-collection period, a joining party adds mandates to its selected coalition and gains a cloned agent.

Implementation details
  • A new agent immediately takes a step after being cloned.
  • Execution ends when a coalition reaches at least 61 mandates or all parties have joined.
03

Inspect the trace, including unsuccessful majorities

The CLI writes the initial state and every subsequent state as JSON. A separate Python script renders graph snapshots with party, mandate, state and coalition labels.

Implementation details
  • Three committed input/output fixture pairs show concrete traces; these were parsed, not rerun.
  • Fixture 03 ends with two 60-mandate coalitions: all parties joined, but neither reached a majority.

STRUCTURE & JUDGMENT

How the parts fit.

JSON configuration

Parties, agents, policies and graph

→ Parser + validation

Parser + validation

120 mandates and symmetric matrix

→ Simulation

Simulation

Agent step, party step, termination

→ Selection / join policies / Graph + Party + Coalition / JSON snapshots

Selection / join policies

Independent virtual strategies

→ Graph + Party + Coalition

Graph + Party + Coalition

Offers, states and mandate totals

JSON snapshots

Recorded state after each step

→ Python graph viewer

Python graph viewer

NetworkX / Matplotlib plots

  • C++11
  • Strategy interfaces
  • Rule of Five
  • nlohmann JSON
  • Make / g++
  • Python
  • NetworkX / Matplotlib

Two strategy boundaries for two decisions

SelectionPolicy chooses which neighboring party an agent approaches; JoinPolicy decides which offer a party accepts. Parser constructs the requested concrete strategies.

WHY IT MATTERSThe two choices can vary independently while the simulation lifecycle stays the same. This design rationale is inferred from source.

Make polymorphic ownership explicit

Agent and Party implement destructors, copy and move operations for their owned policy pointers. Copying clones the virtual policy; moves transfer ownership and clear the source pointer.

WHY IT MATTERSAgent cloning and container operations exercise C++ resource-management mechanics instead of relying on shallow copies of owned pointers.

Record intermediate states instead of only a winner

Main saves the initial state and each simulation step; Parser includes parties, agents, coalition membership, mandates and graph edges in the trace.

WHY IT MATTERSA reviewer can see why a coalition grew and distinguish a majority from the all-parties-joined stopping condition.

Scope, limitations & what I would revisit

  • Termination does not guarantee a majority: the committed third fixture ends at 60 versus 60 because every party has joined. This is not a general coalition impossibility solver.
  • There is no separate no-progress termination condition. A disconnected configuration can leave unjoined parties without further offers while no coalition reaches 61; this is a source-derived risk, not an executed reproduction.
  • Mandates selection initializes its candidate using a different eligibility condition from the later loop. That can retain an ineligible initial candidate, so optimal or universally correct selection is not established.
  • Validation consists of source review and inspection of three committed traces, not a new compile or asserted test run. The Python viewer opens graph plots; it is not an interactive web simulator.