Skip to content

Conversation

@hodgesmr
Copy link

@hodgesmr hodgesmr commented Dec 10, 2025

Note: This strategy was ideated and developed with the assistance of Claude Code. I did not see an LLM policy in the repository, but I felt it was important to note that, given open source sensitivities to those tools. I did manual review, edits, and iterations on the implementation and testing.

Summary

This PR introduces BayesianForgiver, a strategy that uses Bayesian inference to model opponent behavior and make adaptive forgiveness decisions based on uncertainty.

Motivation

While the Axelrod library contains many strategies, none use Bayesian opponent modeling to inform decision-making. Existing forgiveness strategies use fixed thresholds or probabilities, regardless of confidence in their assessment of the opponent.

BayesianForgiver introduces uncertainty-aware decision making to the IPD strategy landscape.

Key Features

BayesianForgiver maintains a Beta distribution representing beliefs about the opponent's cooperation probability. It uses both the mean (expected cooperation rate) and variance (uncertainty) to make decisions:

  • More cautious when uncertain about the opponent (requires stronger evidence of cooperation to forgive a defection)
  • More punishing when certain the opponent is hostile (confident exploitation)
  • Adaptive threshold that adjusts forgiveness based on confidence in opponent model

This approach provides noise resilience and adaptive behavior compared to fixed-threshold strategies.

Algorithm

  1. Maintain a Beta(α, β) distribution for opponent's cooperation probability
  2. Start with Beta(1, 1) - neutral/uniform prior
  3. Update after each round:
    • If opponent cooperates: α += 1
    • If opponent defects: β += 1
  4. Calculate statistics:
    • Mean cooperation probability: μ = α / (α + β)
    • Uncertainty (std dev): σ = √(αβ / ((α+β)²(α+β+1)))
  5. Adaptive forgiveness threshold:
    • threshold = base_threshold + uncertainty_factor × σ
  6. Decision:
    • If opponent cooperated last round: Cooperate (reciprocate)
    • If opponent defected last round:
      • If μ ≥ threshold: Cooperate (forgive)
      • Otherwise: Defect (punish)

Implementation Details

  • Computational complexity: O(1) per round (constant time Beta updates)
  • Memory depth: Infinite (uses full history via Bayesian updates)
  • Stochastic: No (deterministic given opponent history)
  • Parameters (optimized via grid search over 144 configurations):

prior_alpha=1.0
prior_beta=1.0
base_forgiveness_threshold=0.45 # Base component of forgiveness threshold
uncertainty_factor=2.5 # Increases caution under uncertainty (raises threshold early)


## Testing

All tests pass:
```bash
python -m pytest axelrod/tests/strategies/test_bayesian_forgiver.py
# 32 passed in 4.35s

Tests cover:

  • Initial strategy behavior
  • Behavior against classic strategies (TFT, Grudger, Cooperator, Defector, etc.)
  • Response to various opponent patterns (alternating, mixed, single defection)
  • Parameter customization
  • Clone and reset functionality

@drvinceknight
Copy link
Member

Thanks for this.

The CI is failing because line 140 of this file is not hit by a test.

 axelrod/strategies/bayesian_forgiver.py                             34      1    97%   140

@hodgesmr
Copy link
Author

Thanks @drvinceknight - added the necessary test and also ran the required black formatter.

@@ -1,12 +1,12 @@
$\\phi$:
$\phi$:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you help me understand what is happening with this file @hodgesmr ? Was this done by running https://github.com/Axelrod-Python/Axelrod/blob/dev/axelrod/classifier.py#L91 ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff is from the commit: c2619eb

I was following the documentation for adding a new strategy: "To classify the new strategy, run rebuild_classifier_table: python rebuild_classifier_table.py"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. Cool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants