# true-qrandom

[![PyPI version](https://img.shields.io/pypi/v/true-qrandom)](https://pypi.org/project/true-qrandom/)
[![Python](https://img.shields.io/pypi/pyversions/true-qrandom)](https://pypi.org/project/true-qrandom/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**True quantum random number generation using IBM Quantum hardware via Qiskit Runtime.**

Classical computers produce *pseudo*-random numbers — deterministic sequences that only appear random. `true-qrandom` uses real quantum hardware: a qubit placed in superposition is measured, producing a result that is fundamentally unpredictable by the laws of quantum mechanics.

---

## Features

- 🔬 True quantum randomness — powered by IBM Quantum hardware
- 🔌 Familiar `random` module API — same interface, quantum backend
- 🧪 Local simulator mode — develop and test with no credentials
- ⚡ Single multi-qubit circuit per request — efficient and fast
- 🔢 Multiple output types — integers, floats, bytes, and raw bits

> More features planned for v0.2.0.

---

## Installation

```bash
pip install true-qrandom
```

Requires Python >= 3.10.

---

## Setup

You need two things from IBM — both are free:

| What | Where to get it |
|---|---|
| IBM Cloud API key | [cloud.ibm.com/iam/apikeys](https://cloud.ibm.com/iam/apikeys) |
| Instance CRN | [quantum.cloud.ibm.com](https://quantum.cloud.ibm.com) → Create instance → copy the CRN |

Set them as environment variables:

```
IBMQ_API_KEY=your_ibm_cloud_api_key
IBMQ_INSTANCE=your_ibm_instance_crn
```

---

## Usage

```python
from true_qrandom import QuantumRandom

# Reads IBMQ_API_KEY and IBMQ_INSTANCE from environment
qr = QuantumRandom()

qr.randint(1, 100)           # → e.g. 42
qr.random()                  # → e.g. 0.7341...
qr.randbytes(4)              # → e.g. b'\x3f\xa1\x09\xcc'
qr.choice(["a", "b", "c"])  # → e.g. "b"
```

You can also pass credentials explicitly:

```python
qr = QuantumRandom(
    api_key="your_ibm_cloud_api_key",
    instance="your_ibm_instance_crn"
)
```

### Simulator mode (no credentials needed)

```python
qr = QuantumRandom(use_simulator=True)
qr.random()
```

> Simulator mode uses AerSimulator — not true quantum randomness. Use IBM hardware for production.

---

## API Reference

### `QuantumRandom(api_key=None, instance=None, use_simulator=False)`

| Parameter | Type | Description |
|---|---|---|
| `api_key` | `str` | IBM Cloud API key. Falls back to `IBMQ_API_KEY` env var. |
| `instance` | `str` | IBM instance CRN. Falls back to `IBMQ_INSTANCE` env var. |
| `use_simulator` | `bool` | Use local AerSimulator instead of IBM hardware. |

### Methods

| Method | Returns | Description |
|---|---|---|
| `random()` | `float` | Random float in `[0.0, 1.0)` |
| `randint(a, b)` | `int` | Random integer `N` such that `a <= N <= b` |
| `randbytes(n)` | `bytes` | `n` random bytes |
| `choice(seq)` | `any` | Random element from a non-empty sequence |

### Low-level access

```python
from true_qrandom import generate_bits

bits = generate_bits(num_bits=16, use_simulator=True)
print(bits)          # → "1011001001110100"
print(int(bits, 2))  # → 45172
```

---

## How It Works

```
 |0⟩ ──[ H ]───────────────[ M ]──► 0 or 1   (bit 1)
                              
 |0⟩ ──[ H ]───────────────[ M ]──► 0 or 1   (bit 2)
        :                     :
        :                     :
 |0⟩ ──[ H ]───────────────[ M ]──► 0 or 1   (bit N)
                              │
                              ▼      
transpile to native gates    1 0 1 1 0 ...  →  int / float / bytes
```

1. Each qubit starts in ground state `|0⟩`
2. A **Hadamard gate (H)** puts it into 50/50 superposition `(|0⟩ + |1⟩) / √2`
3. The circuit is **transpiled** to the native gate set of the target chip
4. **Measuring** collapses the qubit to `0` or `1` — governed by quantum mechanics, not an algorithm
5. N bits are assembled into the requested output type

---

## Development

```bash
git clone https://github.com/yourname/true-qrandom
cd true-qrandom
python3 -m venv .venv
source .venv/bin/activate
pip install -e .

# Simulator tests — no credentials needed
pytest

# Hardware tests
IBMQ_API_KEY="..." IBMQ_INSTANCE="..." pytest -k real_hardware
```

---

## Requirements

- Python >= 3.10
- `qiskit >= 1.0`
- `qiskit-ibm-runtime >= 0.41`
- `qiskit-aer >= 0.14` (simulator mode)

---

## License

MIT — see [LICENSE](LICENSE)

---

## Contributing

Contributions are welcome! Open an issue or pull request on [GitHub](https://github.com/toukir26251/true-qrandom).