Metadata-Version: 2.4
Name: spectral-narrative-analysis
Version: 0.2.1
Summary: Narrative graph stability analysis using eigenmode decomposition and spectral perturbation theory.
Project-URL: Homepage, https://github.com/CHML-real/spectral-narrative-analysis
Project-URL: Repository, https://github.com/CHML-real/spectral-narrative-analysis
Project-URL: Issues, https://github.com/CHML-real/spectral-narrative-analysis/issues
License: MIT
Keywords: bayesian,eigenmode,graph,narrative,perturbation,quantum,spectral,stability,timeline,worldbuilding
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: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: numpy>=1.24
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: tox>=4.0; extra == 'dev'
Description-Content-Type: text/markdown

# spectral-narrative-analysis

> A Python package for analyzing **narrative graph stability** using eigenmode decomposition and spectral perturbation theory.

Narrative graphs are converted into operator matrices whose eigenmodes represent dominant narrative patterns. Evidence shocks are modeled as perturbations, and eigenmode shifts measure how structurally stable — or fragile — a narrative is.

---

## Why this exists

Existing tools can tell you *what* events happened or *how confident* you are in them. This package asks a different question:

> **If new evidence appears, does the entire narrative structure change — or just one edge?**

`spectral-narrative-analysis` answers this by treating the narrative as an operator system:

- Dominant eigenmodes = stable narrative patterns
- Eigenvalue magnitude = how strongly that pattern dominates
- Spectral perturbation = what happens when evidence shocks the system
- Eigenvector shift = whether the core narrative axis changed

This is inspired by the **Seoul Interpretation of Quantum Mechanics (SIQM)**, which treats state description (상태서술) not as a fixed entity but as a structured organization of events and evidence.

---

## Installation

```bash
pip install spectral-narrative-analysis
```

With optional scipy for optimal mode matching:

```bash
pip install spectral-narrative-analysis "scipy"
```

Requires Python 3.10 or later. Core dependency: `numpy`.

---

## Quick start

```python
from sna import (
    NarrativeNode,
    NarrativeEdge,
    PerturbationEntry,
    SpectralConfig,
    NarrativeStabilityAnalyzer,
)

# 1. Define nodes (confidence can come from evidence-confidence-propagation)
nodes = [
    NarrativeNode(id="kain",    label="Kain Incident",  confidence=0.9),
    NarrativeNode(id="rift",    label="Rift Opening",   confidence=0.8),
    NarrativeNode(id="archive", label="Archive Fall",   confidence=0.7),
]

# 2. Define edges (p_forward can come from temporal-belief-graph)
edges = [
    NarrativeEdge(source_id="kain",  target_id="rift",    p_forward=0.9, confidence=0.8),
    NarrativeEdge(source_id="rift",  target_id="archive", p_forward=0.8, confidence=0.7),
]

# 3. Define a perturbation (new evidence shock)
perturbations = [
    PerturbationEntry(
        source_id="kain", target_id="rift",
        delta=0.5,
        note="New official source confirms Kain caused the Rift.",
    )
]

# 4. Analyze
analyzer = NarrativeStabilityAnalyzer()
result = analyzer.analyze(nodes, edges, perturbations)

print(result.stability_score)       # float in [0, 1]
print(result.stability_label)       # stable / moderate / fragile / unstable
print(result.regime_changed)        # True if dominant narrative node shifted
print(result.report())              # full Markdown report
print(result.summary())             # compact dict
```

A full working example is in [`examples/basic_usage.py`](examples/basic_usage.py).

---

## Core concepts

### Narrative Operator

The narrative graph is converted into a matrix `A` where:

```
A[i, j] = node_factor(i, j) × p_forward × confidence × causal_strength
```

Default node factor: `sqrt(source.confidence × target.confidence)`

Three symmetry modes:

| Mode | Construction | Use case |
|------|-------------|----------|
| `symmetric` | `(A + A.T) / 2` | Real eigenvalues, clean analysis |
| `directed` | raw `A` | Preserves causal direction |
| `undirected_laplacian` | `D - (A + A.T)/2` | Structural clustering |
| `directed_laplacian` | `D - A` | Direction-sensitive stability |

### Eigenmodes

Eigenmodes of `A` represent dominant narrative patterns. The most dominant eigenmode (largest eigenvalue magnitude) tells you which nodes are central to the current narrative structure.

### Spectral Perturbation

When new evidence appears, a perturbation matrix `V` is constructed:

```
A' = A + epsilon × V
```

Three perturbation modes:

| Mode | Formula | Use case |
|------|---------|----------|
| `raw` | `A + εV` | Default; unconstrained experiments |
| `bounded` | `clip(A + εV, min, max)` | Confidence-bounded systems |
| `relative` | `A × (1 + εV)` | Proportional strengthening/weakening |

### Mode Matching

After perturbation, eigenmodes may reorder. SNA matches original and perturbed modes using:

```
cost = (1 - eigenvector_overlap) + 0.05 × relative_eigenvalue_gap
```

| Method | Complexity | When used |
|--------|-----------|-----------|
| `hungarian` | polynomial | scipy available (best) |
| `permutation` | O(k!) | small k, no scipy |
| `greedy` | O(k² log k) | fallback |
| `auto` | adaptive | default |

### Stability Score

```
stability = exp(-alpha × instability)
```

| Score | Label |
|-------|-------|
| ≥ 0.85 | stable |
| ≥ 0.60 | moderate |
| ≥ 0.35 | fragile |
| < 0.35 | unstable |

---

## Package structure

```
sna/
├── schema.py       NarrativeNode, NarrativeEdge, PerturbationEntry, SpectralConfig
├── operator.py     NarrativeOperator, OperatorResult
├── spectral.py     EigenmodeAnalyzer, SpectralResult, EigenMode
├── perturbation.py SpectralPerturbationAnalyzer, PerturbationResult, ModeShift
└── stability.py    NarrativeStabilityAnalyzer, NarrativeStabilityResult

docs/
└── model.md        Full mathematical model documentation

examples/
└── basic_usage.py  End-to-end example
```

---

## Relationship to other packages

This package is the third layer in a narrative intelligence stack:

| Layer | Package | Question |
|-------|---------|----------|
| Ordering | [`temporal-belief-graph`](https://github.com/CHML-real/temporal-belief-graph) | Does A happen before B? |
| Trustworthiness | [`evidence-confidence-propagation`](https://github.com/CHML-real/evidence-confidence-propagation) | How much should I trust this item? |
| Structure | `spectral-narrative-analysis` | Is the narrative structurally stable? |

---

## Development

```bash
pip install -e ".[dev]"
pytest
tox
python -m build
```

> This package is currently in alpha. APIs may change before version 1.0.0.

---

## Contributing

Contributions, issues, and feature requests are welcome.
Please open an issue before submitting a pull request.

---

## Contributors

| Handle | GitHub | Role |
|--------|--------|------|
| lajjadred | [@lajjadred](https://github.com/lajjadred) | Project lead |
| 이채문 | [@CHML-real](https://github.com/CHML-real) | Mathematical algorithm development |
| CUBE | [@90cube](https://github.com/90cube) | Idea proposal and data collection |

---

## License

MIT License. See [LICENSE](LICENSE) for details.
