Metadata-Version: 2.4
Name: atto-qde
Version: 0.3.0
Summary: Quantum Decision Engine (QDE) — models how beliefs evolve into decisions under uncertainty
Author: Nick Buttar
License-Expression: LicenseRef-Proprietary
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
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 :: Cython
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Requires-Dist: pydantic>=2.0
Requires-Dist: PyNaCl>=1.5.0
Provides-Extra: console
Requires-Dist: httpx>=0.27; extra == "console"
Provides-Extra: viz
Requires-Dist: matplotlib>=3.5; extra == "viz"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Dynamic: license-file

<p align="center">
  <img src="assets/docs-logo.png" alt="Atto — Quantum Decision Engine" width="600">
</p>

# Atto — Quantum Decision Engine

Atto is a Python SDK that implements a **Quantum Decision Engine (QDE)** — a system that models how beliefs evolve into decisions under uncertainty.

## Where Atto Fits

Think of a modern decision stack in three layers:

| Layer          | Role               | Question it answers                     |
| -------------- | ------------------ | --------------------------------------- |
| **RAG**        | Retrieval          | _What is true / relevant right now?_    |
| **Mapper**     | Belief formation   | _What do I currently believe?_          |
| **Atto (QDE)** | Decision evolution | _How do beliefs evolve into decisions?_ |

RAG surfaces the right context. The mapper turns that context into a belief state. Atto takes that belief state and evolves it — through competing strategies, interfering signals, and collapsing uncertainty — into a decision.

## Core Mental Model

```
context → belief state → evolving reasoning → decision
```

A belief state is not a static snapshot. It's a superposition of possible strategies, shaped by incoming signals, where the final decision emerges through a process analogous to quantum measurement.

## How Atto Differs

**Traditional systems:**

```
features → probability → decision
```

Features are treated as independent inputs. A model produces a score. You threshold it.

**Atto:**

```
signals → evolving state → decision
```

Signals are not independent — they interfere with each other. The state evolves over time. The decision is not a score; it's the collapse of a rich, structured uncertainty.

## Intuition

- **Decisions emerge from competing latent strategies.** The system holds multiple possible actions in superposition until evidence forces a commitment.
- **Signals interact, not independently.** A price signal and a forecast signal don't just add up — they interfere, amplifying or cancelling each other depending on context.
- **Order of information matters.** Receiving a forecast before a price update produces a different evolved state than the reverse. This is non-commutativity — and it reflects how real decisions work.
- **Final decisions are a collapse of uncertainty.** Measurement extracts a concrete action from a continuously evolving belief state, much like observation in quantum mechanics.

## Example: Energy Dispatch

> Given battery state, node forecast, congestion, and confidence — should we charge, hold, or discharge?

In Atto, this looks like:

1. **Initialise a belief state** from the current battery and market context.
2. **Apply operators** for each incoming signal — forecast, congestion, confidence — each one evolving the state.
3. **Interference** between signals shapes the evolved state (e.g. high confidence in a low-price forecast amplifies the "charge" strategy).
4. **Measure** the final state to collapse it into a decision: charge, hold, or discharge.

The decision isn't a lookup table or a weighted sum. It emerges from the dynamics of how the signals shaped the belief state.

## Architecture

```
atto/
├── core/          # Domain-agnostic math engine
│   ├── state      # Belief state representation and manipulation
│   ├── operators  # Signal operators that evolve states
│   ├── dynamics   # State evolution logic
│   └── measurement# Collapse / decision extraction
├── learning/      # Mapping layer
│   └── ...        # Parameter learning, calibration
├── viz/           # 3D visualization of the decision process
│   ├── wave       # Interference pattern computation and plotting
│   └── pipeline   # Animated pipeline visualization
└── scenarios/     # Domain-specific logic
    └── energy/    # Energy dispatch mappings
```

- **Core engine** — Pure mathematical logic: state spaces, operators, evolution, measurement. Reusable across any domain. Built on numpy.
- **Learning layer** — Maps real-world signals to operators and calibrates the engine from data.
- **Scenarios** — Domain-specific translations. Each scenario defines how raw inputs become signals, which operators to apply, and how to interpret the collapsed decision. Scenarios never modify core math.

## Getting Started

```bash
pip install -e .
```

For built-in visualization support:

```bash
pip install -e ".[viz]"
```

For the hosted licence + usage emission (see "Hosted licence" below):

```bash
pip install -e ".[console]"
```

## Hosted licence

By default, `AttoEngine` looks at the environment to decide whether to
talk to the Atto Console:

| Variable                | Purpose                             | Default                        |
| ----------------------- | ----------------------------------- | ------------------------------ |
| `ATTO_API_KEY`          | Org-scoped API key from the console | _required for hosted mode_     |
| `ATTO_ORG_ID`           | Your organisation ID                | _required for hosted mode_     |
| `ATTO_CONSOLE_BASE_URL` | Console origin                      | `https://console.atto-qde.com` |

If both `ATTO_API_KEY` and `ATTO_ORG_ID` are set and the `console` extra
is installed, the SDK transparently:

1. Calls the console licence endpoint before each `decide()` call.
2. Emits a `UsageEvent` to the console after each decision.

Otherwise, the SDK runs in **offline mode** with no-op licence and usage
implementations — no network calls, no environment dependencies.

```python
import os
from atto import AttoEngine, AttoOperator

os.environ["ATTO_API_KEY"] = "atto_live_..."
os.environ["ATTO_ORG_ID"] = "org_..."

engine = AttoEngine(dimension=3, labels=["charge", "hold", "discharge"], org_id=os.environ["ATTO_ORG_ID"])
engine.add_operator(AttoOperator.phase_shift(3, [0.5, 0.0, -0.3]))
decision = engine.decide()  # licence-checked + usage-emitted
```

### Explicit offline opt-out

To force offline mode regardless of environment, inject the no-op pair:

```python
from atto import AttoEngine, NoOpLicenceValidator, NoOpUsageEmitter

engine = AttoEngine(
    dimension=3,
    labels=["charge", "hold", "discharge"],
    validator=NoOpLicenceValidator(),
    emitter=NoOpUsageEmitter(),
)
```

For the full quickstart and signup flow, see the
[atto-qde-docs](../atto-qde-docs/) site.

## Visualization

Atto ships a `viz` module that renders the QDE decision process as 3D wave interference surfaces. Each strategy (charge, hold, discharge) acts as a wave source — their complex amplitudes create an interference pattern that reshapes as signals arrive and the belief state evolves.

### Quick Start

```python
import numpy as np
from atto.scenarios.energy.adapter import EnergyBatteryAdapter
from atto.viz import PipelineVisualizer

adapter = EnergyBatteryAdapter(signal_strength=1.0)
viz = PipelineVisualizer(
    adapter,
    signal_names=["Price signal", "Congestion signal", "Confidence signal"],
)

context = np.array([0.85, 0.15, 0.70, 0.90])
```

### Static Pipeline Trajectory

One panel per stage — initial belief, after each signal operator, after constraints, and collapse:

```python
fig = viz.plot_static(context)
```

### Animated Pipeline

Smooth 3D animation showing the interference surface morphing through each stage, with a probability bar chart tracking strategy distributions. The final collapse uses a smoothstep transition where all amplitude concentrates onto the winning strategy:

```python
# In a script / interactive window
viz.show(context)

# In a Jupyter notebook
from IPython.display import HTML
anim = viz.animate(context)
HTML(anim.to_jshtml())
```

### Single Belief State

Plot the interference pattern of any `AttoState`:

```python
from atto.core.state import AttoState
from atto.viz import plot_interference

state = AttoState.uniform(3, labels=["charge", "hold", "discharge"])
plot_interference(state, title="Uniform superposition")
```

### Pipeline Introspection

Access intermediate states for custom analysis or visualization:

```python
states, stage_names, decision = viz.run_pipeline(context)

for name, state in zip(stage_names, states):
    print(f"{name}: P = {state.probabilities}")
print(f"Decision: {decision.label} (confidence={decision.confidence:.3f})")
```

### API Reference

| Function / Class                   | Purpose                                                 |
| ---------------------------------- | ------------------------------------------------------- |
| `PipelineVisualizer(adapter)`      | One-call wrapper — runs pipeline and visualizes         |
| `.animate(context)`                | Returns `FuncAnimation` (3D surface + probability bars) |
| `.show(context)`                   | Animate + `plt.show()`                                  |
| `.plot_static(context)`            | Multi-panel static figure                               |
| `.run_pipeline(context)`           | Returns `(states, stage_names, decision)`               |
| `plot_interference(state)`         | Single state → 3D surface                               |
| `plot_trajectory(states)`          | Sequence of states → side-by-side panels                |
| `compute_interference(amplitudes)` | Raw numpy computation → `(X, Y, Z)`                     |

## Design Philosophy

- Functions are small and composable.
- Clarity over optimisation.
- The core engine knows nothing about energy, finance, or any specific domain.
- Every decision emerges from state evolution — never from direct prediction.
