Skip to main content

Consensus mathematics from West African dialogue traditions

Project description

palaver-math

Dialogue and consensus mathematics — West African palaver tradition as iterative convergence, coalition formation, and dialogue trees.

What This Does

palaver-math models group decision-making as iterative consensus convergence, inspired by the West African palaver (community dialogue under a baobab tree). It provides sessions where participants hold position vectors, vote on proposals, and gradually converge toward consensus. It detects convergence rates, predicts final consensus positions, finds coalitions (clusters of nearby positions), and builds dialogue trees. Use it for multi-agent consensus, deliberative democracy simulations, collaborative filtering, or any scenario where distributed actors need to agree.

The Cultural Root

In many West African traditions, a palaver is a community gathering under a tree where disputes are resolved through dialogue until consensus is reached. There is no vote — discussion continues until everyone agrees. The mathematical insight: consensus is an iterative convergence process where each participant's position drifts toward the group center weighted by influence. This is identical to distributed averaging algorithms in computer science and opinion dynamics in statistical physics.

Install

pip install palaver-math

Quick Start

from palavermath.session import PalaverSession
from palavermath.consensus import compute_center, consensus_distance, influence_weighted_center
from palavermath.convergence import convergence_rate, is_converging
from palavermath.coalition import find_coalitions, coalition_strength
from palavermath.dialogue import build_dialogue_tree, find_consensus_path

# Start a consensus session
session = PalaverSession(threshold=0.5, step_size=0.1)

# Add participants with positions (e.g., 2D policy space)
p1 = session.add_participant(position=[1.0, 0.0])   # Conservative
p2 = session.add_participant(position=[0.0, 1.0])   # Progressive
p3 = session.add_participant(position=[0.5, 0.5])   # Moderate

# Add proposals and vote
prop = session.add_proposal(position=[0.4, 0.4])
session.vote(participant_idx=0, proposal_idx=0)  # Accepts → shifts position

# Run the full consensus loop
result = session.compute_consensus()
print(f"Consensus reached: {result['consensus_reached']}")
print(f"Center: {result['center']}")
print(f"Distance: {result['distance']}")
print(f"Rounds: {result['rounds']}")

# Check convergence
history = session.history()
rate = convergence_rate(history)
print(f"Converging: {is_converging(history)}")

# Find coalitions
participants = session.participants()
coalitions = find_coalitions(participants, threshold=0.8)
for c in coalitions:
    print(f"Coalition of {len(c)} participants, strength: {coalition_strength(c):.2f}")

# Dialogue tree
statements = [
    {"statement": "We should build the road", "parent_id": None},
    {"statement": "But what about the river?", "parent_id": 0},
    {"statement": "We can build a bridge", "parent_id": 1},
]
tree = build_dialogue_tree(statements)
path = find_consensus_path(tree)

API Reference

session module

PalaverSession

class PalaverSession:
    def __init__(self, threshold=1.0, step_size=0.1, max_rounds=1000)
    def add_participant(self, position)  int  # Returns participant index
    def add_proposal(self, position)  int     # Returns proposal index
    def vote(self, participant_idx, proposal_idx)  None
    def compute_consensus(self)  dict  # {consensus_reached, center, distance, rounds, positions}
    def participants(self)  list[dict]
    def history(self)  list  # history[round][participant][dim]
    def round(self)  int

consensus module

compute_center(participants) → list[float]

Geometric centroid of participant positions.

consensus_distance(participants) → float

Average Euclidean distance from each participant to the center. Measures spread: 0 = perfect agreement.

influence_weighted_center(participants, weights=None) → list[float]

Weighted centroid where participants may carry different influence.

convergence module

convergence_rate(session_history) → float

Average per-step change in consensus distance. Negative = converging.

predict_consensus(session, max_steps=100) → list[float]

Predict where the session will converge by running the convergence loop.

is_converging(session_history) → bool

True if the last few rounds show decreasing consensus distance.

coalition module

find_coalitions(participants, threshold) → list[list]

Groups where every pair is within threshold distance (single-linkage clustering).

coalition_strength(coalition) → float

0–1 cohesion score. 1.0 = everyone shares the same position.

merge_adjacent(coalitions, threshold) → list[list]

Merge coalitions whose centroids are within threshold.

dialogue module

DialogueNode

@dataclass
class DialogueNode:
    statement: str
    responses: list[DialogueNode]
    depth: int

build_dialogue_tree(statements) → DialogueNode

Build a tree from flat statement records with statement, parent_id, responses.

find_consensus_path(tree) → list[DialogueNode]

Shortest root-to-leaf path (BFS). Consensus = reaching a leaf.

How It Works

Consensus Session: Each participant holds a position vector. When a participant accepts a proposal, their position shifts toward the proposal by step_size. The session runs rounds until consensus distance drops below threshold or max_rounds is hit.

Convergence: Tracks the average distance from all participants to the geometric center over time. If this distance is decreasing, the group is converging.

Coalitions: Uses single-linkage clustering — two participants are in the same coalition if any path of within-threshold hops connects them.

Dialogue Trees: Statements form a tree. Consensus path = shortest root-to-leaf path, representing the most efficient route to a conclusion.

The Math

Consensus Distance: D = (1/n) Σᵢ ||pᵢ − c|| where c = (1/n) Σᵢ pᵢ is the centroid.

Position Update: pᵢ(t+1) = pᵢ(t) + α · (q − pᵢ(t)) where q is the accepted proposal and α is the step size. This is gradient descent toward the proposal.

Convergence Rate: r = (1/T) Σₜ (D(t+1) − D(t)). Negative r means converging.

Coalition Strength: s = 1 − (1/(k·d_max)) Σᵢ<ⱼ ||pᵢ − pⱼ|| normalized to [0, 1].

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

palaver_math-0.1.0.tar.gz (13.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

palaver_math-0.1.0-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file palaver_math-0.1.0.tar.gz.

File metadata

  • Download URL: palaver_math-0.1.0.tar.gz
  • Upload date:
  • Size: 13.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for palaver_math-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c962127549a2f72afdfa7bfea58308832ba945e98b8c62447ca7c081d63bb962
MD5 da2fd5f5004c73e2594a7ada8a434685
BLAKE2b-256 7bc11687eda2b3976d81edc794e587b6a910c6b25513ec1afdc1222e2daf93db

See more details on using hashes here.

File details

Details for the file palaver_math-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: palaver_math-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for palaver_math-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ec406f34fd9503d2909bbec7897397fa311c62b90fc47988c49c6eecf808aab8
MD5 adc793143f14f2c599385cea3a14a4ef
BLAKE2b-256 da8b90fb2960ccc7cc7c8aeb86ca2524125a4d39ef1929a5a623b6f360661b3e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page