Skip to content

Commit eb0baba

Browse files
structure cahnge, package rename, CI, docs, examples and tests and sampling, v0.1.0
1 parent 81f7c9b commit eb0baba

49 files changed

Lines changed: 1427 additions & 539 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/tests.yml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
tests:
9+
name: Tests Python ${{ matrix.python-version }}
10+
runs-on: ubuntu-latest
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
python-version: ["3.10", "3.11", "3.12"]
15+
16+
steps:
17+
- name: Check out repository
18+
uses: actions/checkout@v4
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: ${{ matrix.python-version }}
24+
cache: pip
25+
26+
- name: Install package
27+
run: |
28+
python -m pip install --upgrade pip
29+
python -m pip install -e ".[test]"
30+
31+
- name: Run tests
32+
run: python -m pytest -q
33+
34+
circuit-extras:
35+
name: Circuit Extras
36+
runs-on: ubuntu-latest
37+
38+
steps:
39+
- name: Check out repository
40+
uses: actions/checkout@v4
41+
42+
- name: Set up Python
43+
uses: actions/setup-python@v5
44+
with:
45+
python-version: "3.12"
46+
cache: pip
47+
48+
- name: Install package with circuit extras
49+
run: |
50+
python -m pip install --upgrade pip
51+
python -m pip install -e ".[dev]"
52+
53+
- name: Run tests
54+
run: python -m pytest -q
55+
56+
package-smoke:
57+
name: Package Smoke
58+
runs-on: ubuntu-latest
59+
60+
steps:
61+
- name: Check out repository
62+
uses: actions/checkout@v4
63+
64+
- name: Set up Python
65+
uses: actions/setup-python@v5
66+
with:
67+
python-version: "3.12"
68+
cache: pip
69+
70+
- name: Build package
71+
run: |
72+
python -m pip install --upgrade pip
73+
python -m pip install build
74+
python -m build
75+
76+
- name: Install wheel and run console command
77+
run: |
78+
python -m venv /tmp/shors-wheel
79+
/tmp/shors-wheel/bin/python -m pip install --upgrade pip
80+
/tmp/shors-wheel/bin/python -m pip install dist/*.whl
81+
/tmp/shors-wheel/bin/shors-sim --N 15 --a 2 --json

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ __pycache__/
77
.ruff_cache/
88
.coverage
99
htmlcov/
10+
build/
11+
dist/
12+
*.egg-info/
1013

1114
.venv/
1215
venv/

CHANGELOG.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Changelog
2+
3+
All notable changes to this project are documented here.
4+
5+
## v0.1.0, 22/04/2026
6+
7+
### Added
8+
9+
- Added a real installable package, `shors_algorithm_simulation`, with a typed public API.
10+
- Added the `shors-sim` console entry point.
11+
- Added sampled-measurement support with `shots` and deterministic `random_seed`.
12+
- Added retry orchestration with `max_attempts` when no base `a` is provided.
13+
- Added optional circuit dependencies via `.[circuits]` and `requirements-circuits.txt`.
14+
- Added package metadata in `pyproject.toml`.
15+
- Added GitHub Actions CI for Python 3.10, 3.11, 3.12, circuit extras, and package build smoke tests.
16+
- Added package install smoke tests.
17+
- Added `examples/shots_sweep_example.py` for success rate versus sampled measurements.
18+
- Added configurable output directories for generated plots.
19+
20+
### Changed
21+
22+
- Replaced the public `src.*` import namespace with `shors_algorithm_simulation.*`.
23+
- Moved CLI parsing and human-readable output into `shors_algorithm_simulation.cli`.
24+
- Split algorithm, probability, validation, plotting, and quantum helper code into separate modules.
25+
- Moved probability sampling into `shors_algorithm_simulation.probabilities`.
26+
- Moved period finding into `shors_algorithm_simulation.period`.
27+
- Moved classical checks into `shors_algorithm_simulation.validation`.
28+
- Updated examples to run as modules with `python -m examples...`.
29+
- Updated documentation to clarify that distribution mode and shot sampling use ideal simulated probabilities.
30+
31+
### Removed
32+
33+
- Removed the old tracked `src/` Python package modules.
34+
- Removed Qiskit and pylatexenc from the core requirements file.
35+
- Removed `sys.path.append(...)` setup from examples.
36+
37+
## Earlier History
38+
39+
- Added educational circuit diagrams and circuit documentation.
40+
- Added distribution mode for faster ideal first-register probability simulation.
41+
- Added matrix mode comparisons, runtime examples, diagnostic plots, and regression tests.

CIRCUITS.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ The oracle decomposition is intentionally tiny. It shows how an oracle can be bu
1313
Generate the standard circuit diagram set with:
1414

1515
```bash
16-
python examples/circuit_diagrams_example.py --N 15 --a 2
16+
python -m examples.circuit_diagrams_example --N 15 --a 2
1717
```
1818

1919
or call the module directly:
2020

2121
```bash
22-
python -m src.quantum_part.circuit_diagrams --N 15 --a 2 --output-dir images
22+
python -m shors_algorithm_simulation.quantum.circuits --N 15 --a 2 --output-dir images
2323
```
2424

2525
This creates:
@@ -28,10 +28,10 @@ This creates:
2828
- `images/inverse_qft_decomposition_4_qubits.png`
2929
- `images/oracle_decomposition_N=15_a=2_xqubits=2.png`
3030

31-
The older compatibility command still regenerates the compact circuit used in the README:
31+
The compact circuit used in the README can be regenerated with:
3232

3333
```bash
34-
python src/quantum_part/quantum_circuit.py
34+
python -m shors_algorithm_simulation.quantum.quantum_circuit
3535
```
3636

3737
## Register Layout

README.md

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Classical Simulation of Shor's Algorithm
22

3+
[![Tests](https://github.com/SidRichardsQuantum/Shors_Algorithm_Simulation/actions/workflows/tests.yml/badge.svg)](https://github.com/SidRichardsQuantum/Shors_Algorithm_Simulation/actions/workflows/tests.yml)
4+
35
A pure Python implementation of Shor's quantum factorization algorithm using classical simulation of the period-finding step.
46
The project supports both explicit matrix simulation for very small inputs and a faster distribution-based simulation for the ideal first-register measurement probabilities.
57

@@ -48,6 +50,8 @@ A quantum circuit sketch for Shor's Algorithm using 8 qubits:
4850
- **Visualization**: Plots probability distributions to visualize quantum measurements
4951
- **Period-Finding Diagnostics**: Plots oracle periodicity, marked IQFT peaks, continued-fraction candidates, and mode comparisons
5052
- **Runtimes**: Graph of code runtime to show the exponential nature of this classical simulation
53+
- **Sampled Measurements**: Optional `shots` sampling draws stochastic first-register measurements from the ideal distribution
54+
- **Retry Orchestration**: `max_attempts` can try multiple bases when `a` is not provided
5155
- **Two Period-Finding Modes**:
5256
- `mode="distribution"` computes the ideal first-register measurement distribution directly, using the standard `Q ~= N^2` period register size.
5357
- `mode="matrix"` explicitly applies the simulated Hadamard, oracle, and IQFT matrices for very small inputs.
@@ -62,38 +66,39 @@ Shors_Algorithm_Simulation
6266
├── CIRCUITS.md # Circuit diagram walkthrough
6367
├── THEORY.md # Theoretical background
6468
├── RESULTS.md # Results, conclusions and evaluations
65-
├── main.py # Main execution script
69+
├── main.py # Compatibility CLI shim
6670
├── examples/ # Example usage and demonstrations
6771
│ ├── __init__.py
6872
│ ├── benchmark_runtime.py # Save runtime benchmark table
6973
│ ├── circuit_diagrams_example.py # Generate Qiskit circuit diagrams
7074
│ ├── factorisation_example.py # Single deterministic run with saved plot
7175
│ ├── no_plot_example.py # Deterministic run without displaying plots
7276
│ ├── multiple_cases_example.py # Run several (N, a) examples without plots
77+
│ ├── shots_sweep_example.py # Success rate vs sampled measurement shots
7378
│ ├── visualizations_example.py # Generate educational period-finding plots
7479
│ └── runtimes_test.py # Runtime performance testing
7580
├── images/ # Generated visualizations of examples
7681
├── tests/ # Regression tests
77-
└── src/ # Source code
78-
├── __init__.py # Main package initialization
79-
├── classical_parts/ # Classical algorithm components
80-
│ ├── __init__.py
81-
│ ├── pre_checks.py # Pre-quantum validation
82-
│ └── post_checks.py # Post-quantum validation
83-
├── plots_and_period/ # Visualization and period finding
82+
└── shors_algorithm_simulation/ # Source package
83+
├── __init__.py # Public API exports
84+
├── cli.py # argparse and human-readable output
85+
├── core.py # Typed core API without CLI printing
86+
├── probabilities.py # Ideal distributions and sampled measurements
87+
├── period.py # Continued-fraction period recovery
88+
├── validation.py # Classical input and factor checks
89+
├── plotting/ # Visualization helpers
8490
│ ├── __init__.py
85-
│ ├── find_period.py # Period finding function
86-
│ ├── probability_plot.py # Probability visualization
87-
│ ├── visualizations.py # Educational diagnostics and comparison plots
88-
│ └── runtime_plot.py # Runtime analysis plots
89-
└── quantum_part/ # Quantum operators
91+
│ ├── diagnostics.py # Educational diagnostics and comparison plots
92+
│ ├── formatting.py # Plot label formatting
93+
│ ├── probabilities.py # Probability visualization
94+
│ └── runtime.py # Runtime analysis plots
95+
└── quantum/ # Quantum operators and optional diagrams
9096
├── __init__.py
91-
├── circuit_diagrams.py # Reusable Qiskit circuit diagram builders
92-
├── hadamard_matrix.py # Hadamard gate implementation
93-
├── oracle_matrix.py # Modular exponentiation oracle
94-
├── iqft_matrix.py # Inverse QFT implementation
95-
├── quantum_circuit.py # Qiskit circuit diagram generation
96-
└── run_quantum_gates.py # Quantum circuit execution
97+
├── circuits.py # Reusable Qiskit circuit diagram builders
98+
├── gates.py # Quantum circuit execution
99+
├── hadamard.py # Hadamard gate implementation
100+
├── iqft.py # Inverse QFT implementation
101+
└── oracle.py # Modular exponentiation oracle
97102
```
98103

99104
### Installation
@@ -104,64 +109,77 @@ cd Shors_Algorithm_Simulation
104109
pip install -r requirements.txt
105110
```
106111

107-
`qiskit` and `pylatexenc` are included so `src/quantum_part/quantum_circuit.py` can regenerate the illustrative circuit diagram.
112+
`requirements.txt` includes the simulator dependencies plus `pytest` for local test runs. Circuit diagram generation uses optional Qiskit dependencies:
113+
114+
```bash
115+
pip install -r requirements-circuits.txt
116+
# or, for editable/package installs:
117+
pip install ".[circuits]"
118+
```
108119

109120
### Example Usage
110121

111122
**Terminal inputs**:
112123

113124
```python
114-
python examples/factorisation_example.py # single run with plot output
115-
python examples/no_plot_example.py # single run without plotting
116-
python examples/multiple_cases_example.py # batch of small deterministic cases
117-
python examples/visualizations_example.py # generate educational diagnostic plots
118-
python examples/circuit_diagrams_example.py --N 15 --a 2
125+
python -m examples.factorisation_example # single run with plot output
126+
python -m examples.no_plot_example # single run without plotting
127+
python -m examples.multiple_cases_example # batch of small deterministic cases
128+
python -m examples.shots_sweep_example # plot success rate vs sampled shots
129+
python -m examples.visualizations_example # generate educational diagnostic plots
130+
python -m examples.circuit_diagrams_example --N 15 --a 2
119131
```
120132

121133
**Command-line usage**:
122134

123135
```bash
124-
python main.py --N 35 --a 2 --mode distribution --plots
136+
python main.py --N 35 --a 2 --mode distribution --plots --output-dir images
125137
python main.py --N 15 --a 2 --mode matrix --json
138+
python main.py --N 21 --a 2 --shots 1024 --seed 1 --json
139+
python main.py --N 33 --max-attempts 5 --seed 0
126140
```
127141

128142
Visualization plots can also be selected from the command line:
129143

130144
```bash
131-
python examples/visualizations_example.py --N 35 --a 2 --plots oracle marked continued
132-
python examples/visualizations_example.py --plots comparison --comparison-N 15 --comparison-a 2
145+
python -m examples.shots_sweep_example --N 21 --a 2 --shots 16 32 64 128 256 --trials 20
146+
python -m examples.visualizations_example --N 35 --a 2 --plots oracle marked continued
147+
python -m examples.visualizations_example --plots comparison --comparison-N 15 --comparison-a 2
133148
```
134149

135150
Circuit diagrams can be generated from the command line:
136151

137152
```bash
138-
python examples/circuit_diagrams_example.py --N 15 --a 2 --output-dir images
139-
python -m src.quantum_part.circuit_diagrams --N 35 --a 2
153+
python -m examples.circuit_diagrams_example --N 15 --a 2 --output-dir images
154+
python -m shors_algorithm_simulation.quantum.circuits --N 35 --a 2
140155
```
141156

142157
**Programmatic mode selection**:
143158

144159
```python
145-
from main import shors_simulation
160+
from shors_algorithm_simulation import shors_simulation
146161

147-
result = shors_simulation(N=21, a=2, show_plots=False, mode="distribution")
162+
result = shors_simulation(N=21, a=2, mode="distribution")
148163
print(result["success"], result["factors"], result["period"])
149164

150-
matrix_result = shors_simulation(N=15, a=2, show_plots=False, mode="matrix")
165+
matrix_result = shors_simulation(N=15, a=2, mode="matrix")
151166
print(matrix_result["success"], matrix_result["factors"], matrix_result["period"])
167+
168+
sampled_result = shors_simulation(N=21, a=2, shots=1024, random_seed=1)
169+
print(sampled_result["measurement_counts"])
170+
171+
retry_result = shors_simulation(N=33, max_attempts=5, random_seed=0)
172+
print(retry_result["success"], len(retry_result["attempts"]))
152173
```
153174

154175
`distribution` mode is the default and is appropriate for the documented examples. `matrix` mode is intended for the smallest cases because explicit gate matrices grow quickly.
155-
`shors_simulation` returns a dictionary containing `success`, `N`, `a`, `mode`, `period`, `factors`, `message`, and `classical_precheck`.
176+
`shors_simulation` returns a dictionary containing `success`, `N`, `a`, `mode`, `period`, `factors`, `message`, `classical_precheck`, `shots`, `measurement_counts`, and `attempts`.
156177

157178
**Output**:
158179

159180
```
160181
N = 35
161-
Running Classical Checks...
162-
Classical checks passed.
163-
a = 2.
164-
Proceeding to quantum algorithm...
182+
Attempt 1: a = 2
165183
The period r = 12 is even.
166184
a^(r/2) + 1 = 30, and gcd(30, 35) = 5
167185
a^(r/2) - 1 = 28, and gcd(28, 35) = 7
@@ -180,6 +198,14 @@ This also saves the plot to the "images" directory as "first_register_probabilit
180198
- continued-fraction candidate plot and CSV table
181199
- matrix mode vs distribution mode comparison for a small case
182200

201+
`examples/shots_sweep_example.py` repeats sampled period recovery for multiple shot counts and saves a CSV plus a success-rate plot. It is intended to show how empirical measurement histograms converge toward the ideal distribution as shots increase.
202+
203+
### What Is Simulated
204+
205+
`mode="matrix"` constructs the full simulated state evolution for tiny examples, so it is useful for checking the gate-level model but grows quickly.
206+
`mode="distribution"` computes the ideal post-IQFT first-register probability distribution directly from the periodic oracle values. It does not build a scalable quantum computer or simulate hardware noise.
207+
When `shots` is provided, the simulator samples measurement counts from that ideal distribution and then runs the same continued-fraction recovery on the empirical histogram.
208+
183209
### Tests
184210

185211
```bash
@@ -190,6 +216,7 @@ pytest -q
190216

191217
- **Exponential Runtime/Memory**: `mode="matrix"` scales exponentially with the number of simulated qubits and is only practical for tiny cases.
192218
- **Distribution Mode Is Idealized**: `mode="distribution"` avoids full matrices by computing the ideal first-register distribution directly, which is still a classical simulation of the period-finding output.
219+
- **Shot Sampling Is Synthetic**: `shots` samples from the ideal distribution; it does not model device noise, decoherence, or imperfect gates.
193220
- **Small Numbers Only**: Practical for factoring small educational examples, not cryptographic integers.
194221
- **Educational Purpose**: Not suitable for large numbers practically used for low-bit RSA
195222
- **Multiple Runs**: May require multiple runs if classical checks on $N, a$ or $r$ fail

RESULTS.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,24 +67,20 @@ The peaks are not all exactly equally high because $4096$ is not divisible by $1
6767
Running:
6868

6969
```python
70-
shors_simulation(N=35, a=2, show_plots=True, sparse=True, mode="distribution")
70+
from shors_algorithm_simulation import shors_simulation
71+
72+
shors_simulation(N=35, a=2, sparse=True, mode="distribution")
7173
```
7274

7375
prints:
7476

7577
```
7678
N = 35
77-
Running Classical Checks...
78-
Classical checks passed.
79-
a = 2.
80-
Proceeding to quantum algorithm...
79+
Attempt 1: a = 2
8180
The period r = 12 is even.
8281
a^(r/2) + 1 = 30, and gcd(30, 35) = 5
8382
a^(r/2) - 1 = 28, and gcd(28, 35) = 7
8483
The factors of N = 35 are 5 and 7.
85-
----------------------------------------
86-
87-
Plot saved as: images/first_register_probabilities_N=35_a=2.png
8884
```
8985

9086
The function also returns a structured result dictionary containing the recovered period and factors.
@@ -173,7 +169,7 @@ The two distributions match up to floating-point error for $N=15, a=2$.
173169

174170
## Runtimes Vs Required Qubits
175171

176-
Running `examples/runtimes_test.py` calls `run_runtime_analysis()` from `src/plots_and_period/runtime_plot.py`.
172+
Running `python -m examples.runtimes_test` calls `run_runtime_analysis()` from `shors_algorithm_simulation.plotting.runtime`.
177173
It measures repeated runtimes for deterministic pairs `(N, a)` known to yield useful periods.
178174

179175
Example cases include:

0 commit comments

Comments
 (0)