Metadata-Version: 2.4
Name: rqm-qiskit
Version: 0.1.2
Summary: Thin Qiskit bridge layer for the RQM quantum ecosystem
License: MIT License
        
        Copyright (c) 2026 RQM Technologies
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/RQM-Technologies-dev/rqm-qiskit
Project-URL: Repository, https://github.com/RQM-Technologies-dev/rqm-qiskit
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: qiskit>=1.0
Provides-Extra: simulator
Requires-Dist: qiskit-aer>=0.13; extra == "simulator"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: qiskit-aer>=0.13; extra == "dev"
Dynamic: license-file

# rqm-qiskit

**Thin Qiskit bridge layer for the RQM quantum ecosystem** — translates
canonical RQM circuits and gates (owned by rqm-compiler) into Qiskit
primitives and runs them on Aer simulators or IBM Quantum hardware.

---

## Architecture

`rqm-qiskit` occupies a single, well-defined layer in the RQM dependency
spine:

```
rqm-core        (canonical math: Quaternion, SU(2), Bloch, spinor)
       ↓
rqm-compiler    (canonical gate/circuit IR: Circuit, Operation, compilation)
       ↓
rqm-qiskit      (Qiskit bridge: circuit lowering, IBM execution helpers)
       ↓
[rqm-optimize]  (optional: circuit optimization — see Optimization section)
       ↓
rqm-notebooks   (interactive notebooks and tutorials)
```

The full pipeline with optional optimization:

```
compile → lower → optimize → run
```

### Layer responsibilities

| Package | Responsibility |
|---------|----------------|
| `rqm-core` | Quaternion algebra, SU(2) matrices, Bloch conversions, spinor helpers |
| `rqm-compiler` | Canonical gate/circuit IR (`Circuit`, `Operation`), normalization, compilation pipeline |
| `rqm-qiskit` | Lower rqm-compiler IR to Qiskit `QuantumCircuit`; Aer/IBM execution helpers; thin user-facing wrappers |
| `rqm-notebooks` | Jupyter notebooks, tutorials, interactive demonstrations |

### What rqm-qiskit owns

- `compiled_circuit_to_qiskit()` — the primary bridge: translates an
  `rqm_compiler.Circuit` or `rqm_compiler.CompiledCircuit` into a Qiskit
  `QuantumCircuit`.
- `RQMCircuit` — a thin façade over `rqm_compiler.Circuit` that adds
  Qiskit-specific state preparation (`initialize`) and exposes
  `.to_qiskit()`.
- `RQMGate` — adds `.to_operation()` (→ `rqm_compiler.Operation`) and
  `.to_qiskit_gate()` (→ Qiskit gate object) on top of the rqm-core SU(2)
  matrix.
- `RQMState` — adds Qiskit-facing helpers (`.vector()`, `.as_statevector()`)
  on top of rqm-core spinor/Bloch math.
- `run_on_aer_sampler()` / IBM Runtime helpers in `ibm.py`.
- Result formatting in `results.py`.

### What rqm-qiskit does NOT own

`rqm-qiskit` does not implement canonical math.  It delegates all math
operations to rqm-core.

Specifically, `rqm-qiskit` contains **no** quaternion math, **no** spinor
normalization, **no** Bloch conversions, and **no** SU(2) decomposition of its
own.  All canonical logic is delegated to rqm-core and rqm-compiler.

### Architecture Guarantees

These invariants are stable and hold across all public helpers in this package:

| Guarantee | Detail |
|-----------|--------|
| **Canonical math lives in rqm-core** | Quaternion algebra, SU(2) matrices, Bloch-vector conversions, and spinor normalization are owned exclusively by `rqm-core`.  `rqm-qiskit` never reimplements them. |
| **Canonical circuit IR lives in rqm-compiler** | `rqm_compiler.Circuit`, `rqm_compiler.Operation`, and the compilation pipeline are the single source of truth for gate and circuit semantics. |
| **`compiled_circuit_to_qiskit()` is the primary lowering path** | Every helper that converts a gate or circuit to a Qiskit `QuantumCircuit` routes through `compiled_circuit_to_qiskit()`.  There is no second, parallel lowering path. |
| **`state_to_quantum_circuit()` is the only documented exception** | State preparation uses Qiskit's `initialize` instruction, which has no equivalent in the rqm-compiler IR.  It therefore cannot route through the main lowering path and is explicitly documented as the sole exception. |

In practice this means:
- `RQMCircuit.to_qiskit()` calls `compiled_circuit_to_qiskit()` internally.
- `gate_to_quantum_circuit()` builds a 1-op `rqm_compiler.Circuit` and calls `compiled_circuit_to_qiskit()`.
- New helpers added in future versions **must** route through `compiled_circuit_to_qiskit()` unless there is an explicit, documented reason not to.

---

## What Is This?

`rqm-qiskit` is a clean, beginner-friendly Python package that bridges
**rqm-compiler** (the canonical RQM circuit layer) and **Qiskit** (the
execution engine).

The key insight:

> A single-qubit state lives on the Bloch sphere.  
> Rotations of the Bloch sphere are SU(2) transformations.  
> SU(2) is isomorphic to the group of unit quaternions.

Therefore, **unit quaternions are the natural algebraic object for 1-qubit
quantum states and gates**.  rqm-core owns that algebra; rqm-compiler owns
circuit structure; rqm-qiskit exposes the geometry to Qiskit users and
handles execution.

**This package is not trying to replace Qiskit.**  
It is a thin bridge — Qiskit does all the heavy lifting under the hood.

---

## Quaternion Intuition for Qubits

A unit quaternion `q = w + x·i + y·j + z·k` (with `|q| = 1`) corresponds to an
SU(2) matrix via:

```
U = [[w − i·z,  −(y + i·x)],
     [y − i·x,   w + i·z  ]]
```

This means:

| Operation | Quaternion form |
|-----------|----------------|
| Identity (no rotation) | `q = 1` |
| R_x(θ) | `q = cos(θ/2) + sin(θ/2)·i` |
| R_y(θ) | `q = cos(θ/2) + sin(θ/2)·j` |
| R_z(θ) | `q = cos(θ/2) + sin(θ/2)·k` |
| Compose two gates | `q_total = q2 * q1` (right-to-left) |

Every `RQMGate` exposes its `quaternion` property.  Every `RQMState` exposes
`to_quaternion()` — the rotation that prepares it from `|0>`.

---

## Why Does This Exist?

- **Geometric intuition**: unit quaternions make SU(2) rotations concrete and composable.
- **Quaternionic quantum mechanics**: a foundation for richer RQM educational tooling.
- **Educational clarity**: fewer raw matrix operations, more geometric understanding.
- **IBM Quantum ready**: built on Qiskit so the path to real hardware is direct.

---

## Installation

Install from PyPI:

```bash
pip install rqm-qiskit
```

To also run local simulations (recommended):

```bash
pip install "rqm-qiskit[simulator]"
```

For development:

```bash
git clone https://github.com/RQM-Technologies-dev/rqm-qiskit.git
cd rqm-qiskit
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev,simulator]"
```

---

## Quickstart

```python
from rqm_qiskit import RQMState, RQMGate, RQMCircuit

state = RQMState.plus()
gate = RQMGate.ry(0.6)

circ = RQMCircuit(1)
circ.prepare_state(state)
circ.apply_gate(gate)
circ.measure_all()

print(circ.draw_text())
```

Inspect the quaternion geometry:

```python
# State as a unit quaternion
q_state = state.to_quaternion()
print(q_state.pretty())           # Quaternion(0.7071 +0.0000i +0.7071j +0.0000k)  |q| = 1.000000

# Gate as a unit quaternion
q_gate = gate.quaternion
print(q_gate.pretty())

# Compose two gates as a single quaternion product
gate2 = RQMGate.rz(0.3)
q_composed = gate2.quaternion * gate.quaternion  # apply gate first, then gate2
print(q_composed.to_su2_matrix())  # the combined 2×2 SU(2) matrix
```

Use the rqm-compiler circuit directly:

```python
from rqm_compiler import Circuit, compile_circuit
from rqm_qiskit.convert import compiled_circuit_to_qiskit

# Build a backend-neutral circuit in rqm-compiler
c = Circuit(2)
c.h(0)
c.cx(0, 1)
c.measure(0)
c.measure(1)

# Lower to Qiskit
qc = compiled_circuit_to_qiskit(c)
print(qc.draw(output="text"))
```

Run on the local Aer simulator:

```python
from rqm_qiskit import format_counts_summary
from rqm_qiskit.ibm import run_on_aer_sampler

counts = run_on_aer_sampler(circ.to_qiskit(), shots=1024)
print(format_counts_summary(counts))
```

---

## Package Structure

```
rqm-qiskit/
  src/
    rqm_qiskit/
      quaternion.py  – Quaternion: thin shim re-exporting from rqm-core
      state.py       – RQMState: Qiskit-bridge wrapper over rqm-core spinor math
      gates.py       – RQMGate: dual-mode gate; re-exports gate factories from rqm-core
      circuit.py     – RQMCircuit: façade over rqm_compiler.Circuit + to_qiskit()
      convert.py     – compiled_circuit_to_qiskit(); state/gate convenience wrappers
      translator.py  – QiskitTranslator, compile_to_qiskit_circuit
      execution.py   – run_local, run_backend
      backend.py     – QiskitBackend: unified entry point
      result.py      – QiskitResult: structured result wrapper
      bridges.py     – spinor_to_circuit, bloch_to_circuit (bridge functions)
      results.py     – summarize_counts, format_counts_summary
      ibm.py         – Aer sampler helper + IBM Runtime stub
      utils.py       – internal utilities
  tests/             – pytest test suite (256 tests)
  examples/          – runnable example scripts
  AGENTS.md          – coding agent rules
```

---

## Convenience Bridges

Two thin bridge functions map physical state representations to Qiskit circuits.
**All physics is delegated to rqm-core; these functions own only the gate mapping.**

### `spinor_to_circuit(alpha, beta, target=0)`

Converts a spinor `(α, β)` to a `QuantumCircuit` that prepares qubit `target`
in the corresponding state.

Steps:
1. Normalize `(α, β)` via `rqm_core.spinor.normalize_spinor`
2. Convert to Bloch vector via `rqm_core.bloch.state_to_bloch`
3. Map `(θ, φ)` → `RY(θ) RZ(φ)` Qiskit gates

```python
from rqm_qiskit import spinor_to_circuit
import math

s = 1 / math.sqrt(2)
qc = spinor_to_circuit(s + 0j, s + 0j)   # |+⟩ state
print(qc.draw())
```

### `bloch_to_circuit(theta, phi, target=0)`

Converts Bloch angles `(θ, φ)` directly to a `QuantumCircuit`:
- `RY(θ)` sets the polar angle
- `RZ(φ)` sets the azimuthal angle

```python
from rqm_qiskit import bloch_to_circuit
import math

qc = bloch_to_circuit(math.pi / 2, 0.0)   # |+⟩ on Bloch equator
print(qc.draw())
```

### `Quaternion` re-export

`Quaternion` is re-exported from rqm-core.  Users can access it via either:

```python
from rqm_qiskit import Quaternion
# or
from rqm_core import Quaternion
```

Both refer to the same canonical implementation.

---

## Usage Modes

### Mode 1 — Compiler-first (primary)

Use `rqm_compiler.Circuit` as the canonical circuit IR, then lower to Qiskit
via `QiskitBackend` or `compile_to_qiskit_circuit`:

```python
from rqm_compiler import Circuit
from rqm_qiskit import QiskitBackend

c = Circuit(2)
c.h(0)
c.cx(0, 1)
c.measure(0)
c.measure(1)

backend = QiskitBackend()
result = backend.run_local(c, shots=1024)
print(result.counts)            # {"00": 512, "11": 512}
print(result.most_likely_bitstring())
```

### Mode 2 — Bridge functions (educational / experimental)

Use `spinor_to_circuit` or `bloch_to_circuit` for state preparation directly
from physical parameters:

```python
from rqm_qiskit import spinor_to_circuit, QiskitBackend
import math

# Prepare |+⟩ state from spinor
s = 1 / math.sqrt(2)
qc = spinor_to_circuit(s + 0j, s + 0j)
qc.measure_all()

backend = QiskitBackend()
counts = backend.run_local(qc, shots=1024).counts
print(counts)    # approximately {"0": 512, "1": 512}
```

---

## Current Scope (v0.1.0)

- ✅ `Quaternion` — thin re-export from rqm-core with `pretty()` convenience
- ✅ `RQMState` — normalized 1-qubit states; delegates math to rqm-core
- ✅ `RQMGate` — dual-mode: rotation (R_x, R_y, R_z) or named gate (H, CNOT, …)
- ✅ `RQMCircuit` — façade over rqm-compiler `Circuit`; `to_qiskit()` lowers to Qiskit
- ✅ `QiskitBackend` — unified entry point: compile + run
- ✅ `QiskitTranslator` — rqm-compiler IR → Qiskit `QuantumCircuit`
- ✅ `compile_to_qiskit_circuit()` — convenience function
- ✅ `run_local()` / `run_backend()` — execution helpers
- ✅ `QiskitResult` — structured result wrapper (counts, probabilities, most-likely)
- ✅ `spinor_to_circuit` / `bloch_to_circuit` — bridge functions (delegate to rqm-core)
- ✅ `compiled_circuit_to_qiskit()` — primary bridge: rqm-compiler IR → `QuantumCircuit`
- ✅ Local Aer simulation via `run_on_aer_sampler()` and `run_local()`
- 🚧 IBM Runtime execution (placeholder, not yet implemented)

---

## Roadmap

| Version | Features |
|---------|----------|
| 0.1.0   | Full architecture; compiler-first design; bridge functions; QiskitBackend/Translator/Result |
| 0.2.0   | IBM Runtime `SamplerV2` integration |
| 0.3.0   | Noise models, density matrices |
| 1.0.0   | Stable public API, full documentation |

---

## Running Tests

```bash
# Install development dependencies
pip install -e ".[dev]"
pytest
```

## Running Examples

```bash
python examples/quaternion_state_demo.py
python examples/bloch_vs_quaternion_demo.py
python examples/simulator_counts_demo.py
```


---

## Optimization (Optional)

For improved circuit performance, use [`rqm-optimize`](https://github.com/RQM-Technologies-dev/rqm-optimize):

```python
from rqm_compiler import Circuit, compile_circuit
from rqm_qiskit.convert import compiled_circuit_to_qiskit
from rqm_optimize import optimize  # installed separately — not a dependency of rqm-qiskit

compiled = compile_circuit(my_circuit)
qc = compiled_circuit_to_qiskit(compiled)
qc = optimize(qc)
```

`rqm-optimize` is a **completely separate, optional package**.  `rqm-qiskit`
does **not** depend on it, import it, or couple to it in any way.  Install it
only when you need it:

```bash
pip install "git+https://github.com/RQM-Technologies-dev/rqm-optimize.git"
```

> **Important boundaries:**
> - ❌ Do **not** add `rqm-optimize` as a dependency of `rqm-qiskit`
> - ❌ Do **not** import `rqm_optimize` inside `rqm-qiskit` source code
> - ❌ Do **not** couple the two repositories
>
> Keep optimization **optional and external**.

---

## License

MIT — see [LICENSE](LICENSE).
