# Order Finding
**English** · 简体中文
> Category C1 · Module [`oracq.algorithms.basics.number_theory`](../../api/algorithms/basics/number_theory.rst) · Stage —
## Overview
For a multiplier $a$ coprime with the modulus $m$, find the smallest positive integer $r$ (the order) satisfying $a^r \equiv 1 \pmod m$. The implementation follows Shor's construction ([arXiv:quant-ph/9508027](https://arxiv.org/abs/quant-ph/9508027)): apply the [modular multiplication permutation](modular-multiplication.md) $U_{a,m}$ to the superposed components of the eigenstate $|1\rangle$, run quantum phase estimation on the phase register, read out an approximation of $s/r$, and let classical continued fractions recover candidate orders and attempt to factor $m$. When the order is even and $a^{r/2} \not\equiv -1 \pmod m$, $\gcd(a^{r/2} \pm 1, m)$ yields a non-trivial factor.
## Interface and input model
```python
order_finding(multiplier, modulus, *, precision=3, max_width=8)
factors_from_phase(value, precision, multiplier, modulus)
```
API entry points: {obj}`order_finding `, {obj}`factors_from_phase `
- `multiplier` / `modulus`: the same CP parameters as modular multiplication (classical integers parameterized directly, no oracle input); the underlying modular-multiplication bit-width budget is controlled by `max_width`.
- `precision`: the bit width of the QPE phase register.
- {obj}`factors_from_phase ` is a purely classical function: `value` is the integer readout of the phase register ($0 \le \text{value} < 2^{\text{precision}}$); it returns a verified factor pair (ascending tuple), or `None` when the sample fails to produce factors.
{obj}`order_finding ` returns an {obj}`Operation ` with registers `target: Bits(n)` ($n$ is the modular-multiplication bit width) and `phase: Bits(precision)`. Module attributes:
| Attribute | Meaning |
|---|---|
| `algorithm` | `"order_finding"` |
| `modulus` / `multiplier` | echo of the call parameters |
| `readout_register` | `"phase"` (classical post-processing required after readout) |
## Implementation notes
The generation chain is {obj}`modular_multiply ` → {obj}`phase_estimation `: first prepare $|1\rangle$ by applying X on the least significant bit of `target`, then call QPE. $|1\rangle$ decomposes uniformly over the cyclic eigenstates of the order, so the phase readout approximates $s/r$ ($s$ uniform), and a single sample is not guaranteed to yield the order — `factors_from_phase` uses `Fraction(value, 2**precision).limit_denominator(modulus)` to obtain candidate orders, checks evenness and $a^r \equiv 1$ for each, then verifies $\gcd(a^{r/2}\pm1, m)$, returning `None` when everything fails. When the multiplier and modulus are not coprime and the common factor is non-trivial ($1 < \gcd(a,m) < m$), the quantum path is skipped and the ascending factor pair split off from that common factor is returned directly.
Applicability boundary: the underlying modular multiplication is bounded permutation synthesis capped at 8 bits by default (see [modular multiplication permutation](modular-multiplication.md)), so order finding likewise only targets interface and circuit checks on small instances and **does not represent scalable Shor modular arithmetic**. With insufficient `precision`, continued fractions may fail to recover the correct order; callers must choose the phase bit width based on $r < m$ and accept multiple samples.
## Validation approach
Category C1 (exact discrete semantics; acceptance criteria in `../../development/validation-plan.md` §2): the output distribution and the classical post-processing results must equal the exact construction pointwise. Evidence:
- Structure: construction and property assertions of `tests/core/test_algorithm_expansion.py:AlgorithmExpansionTests` (register layout `target/phase`, attribute echo).
- Numerical: `AlgorithmExpansionTests.test_modular_multiplication_and_order` and the same-name witness `test_modular_multiplication_total_permutation_and_order` — the phase distribution of `order_finding(2, 3, precision=2)` is cross-checked pointwise: $p(0) = p(2) = 0.5$ (order $r=2$, $s \in \{0,1\}$ split evenly); the post-processing path is covered by `factors_from_phase(1, 2, 2, 15) == (3, 5)` and `factors_from_phase(0, 2, 2, 15) is None`.
- Binding: this algorithm has no separate binding witness (no open declaration entry point).
## Known gaps and planned stages
Gap per the validation-matrix wording: the small-scale witnesses **are explicitly noted as not extrapolable to full Shor** (preserving the original wording); quantitative sweeps of the multi-sample success rate and of phase bit width versus recovery success rate have not been done. The stage is listed as — (not in any of the V1–V4 tiers).
## Related links
- Same module: [modular multiplication permutation](modular-multiplication.md)
- Source: `src/oracq/algorithms/basics/number_theory.py`
- API reference: [Modular multiplication and order finding](../../api/algorithms/basics/number_theory.rst)
- Validation matrix: [Validation coverage matrix](../../development/validation-coverage.md)
## Numerical validation
Paper-grade numerical experiments are in `tests/verification/verify_nt_qlss_sde.py` (nt_qlss_sde group), all executed on real backends.
**Experimental design**: (a) For 7 $(a, m, p)$ instances ($m \in \{3,5,7,15\}$, order $r \in \{2,3,4\}$, precision 3–5), run the full order-finding routine on reference and rir-pysparq; the phase marginal distribution is compared against independent theory: $|1\rangle$ is uniform over the $r$ cyclic eigenstates, each eigenphase $s/r$ produces a Dirichlet-kernel peak through QPE, and the total distribution is $\frac{1}{r}\sum_{s=0}^{r-1} D^2(y - 2^p s/r)$ (computed independently with numpy); the $(2,3)$ instance additionally runs the adapter-pysparq and full-amplitude OriginIR-ext paths. The probability of continued fractions recovering the full order is reported as well. (b) `factors_from_phase` exhaustive sweep: $m \in \{15,21,33,35\}$ × all $a \in [2, m-2]$ × all $2^8$ phase readouts (precision=8, 23552 evaluations in total); any returned factor pair must multiply to $m$ with both factors non-trivial; the success rate is weighted by the theoretical QPE distribution and compared per modulus against an independent textbook prediction ($s$ uniform on $[1,r)$, candidate order $d = r/\gcd(s,r)$, requiring $d$ even and $a^d \equiv 1$ and $\gcd(a^{d/2}\pm1, m)$ non-trivial) — the measured shortfall below the prediction is the resolution loss of continued-fraction recovery at precision=8 for larger orders (real physics, not an implementation defect).
**Key metrics**:
| Case | Scale | Path | Metric | Value |
|---|---|---|---|---|
| order-finding-2-3-p3 | $r=2$ | four paths | TVD vs Dirichlet theory / order-recovery probability | 4.4e-16 / 0.500 |
| order-finding-2-5-p4, 3-5-p4 | $r=4$ | two paths | TVD / order-recovery probability | 6.7e-16 / 0.500 |
| order-finding-2-7-p4, 4-7-p4 | $r=3$ | two paths | TVD / order-recovery probability | 8.6e-16 / 0.459 |
| order-finding-2-15-p5, 7-15-p5 | $r=4$ | two paths | TVD / order-recovery probability | 7.8e-16 / 0.500 |
| factors-from-phase-exhaustive | 4 moduli × 56 units | classical oracle | invalid factor pairs / weighted mean success rate / minimum ratio vs textbook prediction | 0 / 0.2925 / 0.791 |
Per-modulus success rates (measured vs textbook prediction): $m=15$: 0.500 vs 0.500; $m=21$: 0.214 vs 0.233; $m=33$: 0.185 vs 0.233; $m=35$: 0.271 vs 0.318. Units that inherently fail due to odd order or $a^{r/2}\equiv-1$ account for 16/56, consistent with the theoretical expectation of Shor's construction.
**Reproduce**:
```bash
PYTHONPATH=src /home/agony/projects/qcfd-dev/quantum-cfd-software/.venv/bin/python tests/verification/verify_nt_qlss_sde.py
```
Output: `out/verification/nt_qlss_sde.json` (`order-finding-*`, `factors-from-phase-exhaustive`, 8 cases in total).