Metadata-Version: 2.4
Name: si-superinstance
Version: 0.1.0
Summary: Exhaustive ternary strategy search — the spreadsheet moment for AI decisions
Author: SuperInstance
License: MIT
Project-URL: Repository, https://github.com/SuperInstance/superinstance-spreadsheet
Keywords: ternary,evolution,strategy,decision,exhaustive-search,agent
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# si-superinstance

[![PyPI](https://img.shields.io/pypi/v/si-superinstance.svg)](https://pypi.org/project/si-superinstance/)
[![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

**Exhaustive ternary strategy search — in 1ms, not 1 epoch.**

## The Problem

You have N decision dimensions, each with 3 choices: avoid (-1), neutral (0), choose (+1). How do you find the best strategy?

If N=4, there are exactly 3⁴ = 81 strategies. You could **enumerate every single one** and rank them. No gradient descent. No training loop. No hyperparameters. Just evaluate all 81 in a millisecond and sort.

That's what this library does.

## The Insight

Ternary genomes {-1, 0, +1} create tiny, fully enumerable strategy spaces. The search cost is O(3ᴺ) — exponential in theory, but in practice:
- N=4 → 81 strategies → instant
- N=6 → 729 strategies → milliseconds
- N=8 → 6,561 strategies → still under a second
- N=10 → 59,049 strategies → ~1 second

**You don't need machine learning when you can just try everything.**

## Quick Start

```python
from superinstance import exhaustive, Strategy, Environment

# Define your decision problem as a payoff matrix
env = Environment.payoff_matrix([
    [3, 0],   # Action 0: high reward / no reward
    [5, 1],   # Action 1: best if chosen
    [0, 6],   # Action 2: best in bad state
    [2, 4],   # Action 3: moderate
])

# Exhaustively evaluate ALL 81 strategies
results = exhaustive(env, top_k=5)

for r in results:
    print(f"#{r.rank} {r.strategy} → fitness {r.fitness:.3f}")
```

Output:
```
#1 Strategy(w=[1, 1, -1, 0]) → fitness 3.040
#2 Strategy(w=[1, 1, -1, 1]) → fitness 2.980
#3 Strategy(w=[1, 1, 0, 0]) → fitness 2.540
...
```

## API

### Core

| Function | What it does |
|---|---|
| `exhaustive(env, n_weights=4, top_k=None)` | Enumerate ALL 3^N strategies, rank by fitness |
| `evolve(population, env, generations=10)` | Run natural selection on a population |
| `pareto(strategies, envs)` | Find Pareto-optimal strategies across environments |
| `species(strategies, threshold=1)` | Cluster strategies by Hamming distance |
| `correlation_matrix(strategies, envs)` | Pearson correlation between environments |
| `all_strategies(n=4)` | Generate all 3^N strategies |

### Strategy

```python
s = Strategy([1, -1, 0, 1])
s.best_action(4)     # → 0 (action with highest weight sum)
s.choose([10, 5, 3]) # → 13.0 (weighted dot product)
s.mutate(p=0.3)      # → new Strategy with random mutations
s.hamming(other)     # → Hamming distance
Strategy.random(4)   # → random strategy
```

### Built-in Environments

```python
from superinstance import PrisonersDilemma, StagHunt, MatchingPennies, RandomEnvironment

env = PrisonersDilemma(rounds=10)
env = StagHunt(coordination_bonus=2.0)
env = MatchingPennies()
env = RandomEnvironment(n=4, seed=42)

# Or define your own:
env = Environment.payoff_matrix([[3, 0], [5, 1], [0, 6], [2, 4]])
```

### Custom Environments

```python
from superinstance import Environment, Strategy

class MyEnv(Environment):
    def score(self, strategy: Strategy) -> float:
        # Your scoring logic here
        return sum(w * 0.5 for w in strategy.w if w > 0)

results = exhaustive(MyEnv(name="custom"), n_weights=4)
```

## Design Decisions

**Why ternary, not binary?** Binary {-1, +1} forces every dimension to take a side. Ternary {-1, 0, +1} allows "I don't know" — which is how real decision-makers think. The zero state is the negative space: it's not abstention, it's information.

**Why exhaustive, not evolutionary?** For N ≤ 8 (6,561 strategies), exhaustive search is faster and more honest than any evolutionary algorithm. You get the global optimum, not a local one. You get the full ranking, not just the top. Evolution is for N > 8 where enumeration becomes expensive.

**Why stochastic scoring?** Real environments are noisy. Averaging over 50 rounds smooths out randomness while keeping the API simple. Set `rounds=1` for deterministic environments.

## From the Browser Spreadsheet

This is the Python API for [SuperInstance Spreadsheet](https://github.com/SuperInstance/superinstance-spreadsheet). The spreadsheet's `=EXHAUSTIVE()` function became this library's `exhaustive()` function. The `=EVOLVE()` became `evolve()`. The `=PARETO()` became `pareto()`.

Same math. Better packaging.

## License

MIT
