quprep 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quprep-0.3.0/.github/workflows/release.yml +41 -0
- {quprep-0.2.0 → quprep-0.3.0}/CHANGELOG.md +54 -1
- {quprep-0.2.0 → quprep-0.3.0}/PKG-INFO +31 -1
- {quprep-0.2.0 → quprep-0.3.0}/README.md +30 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/api/index.md +9 -1
- quprep-0.3.0/docs/guides/qubo.md +257 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/index.md +5 -1
- {quprep-0.2.0 → quprep-0.3.0}/examples/05_recommend.py +1 -1
- {quprep-0.2.0 → quprep-0.3.0}/examples/06_visualization.py +1 -1
- quprep-0.3.0/examples/07_qubo.py +94 -0
- {quprep-0.2.0 → quprep-0.3.0}/examples/README.md +1 -0
- {quprep-0.2.0 → quprep-0.3.0}/pyproject.toml +1 -1
- {quprep-0.2.0 → quprep-0.3.0}/quprep/__init__.py +1 -1
- quprep-0.3.0/quprep/cli.py +427 -0
- quprep-0.3.0/quprep/qubo/__init__.py +42 -0
- quprep-0.3.0/quprep/qubo/constraints.py +157 -0
- quprep-0.3.0/quprep/qubo/converter.py +237 -0
- quprep-0.3.0/quprep/qubo/ising.py +143 -0
- quprep-0.3.0/quprep/qubo/problems/__init__.py +23 -0
- quprep-0.3.0/quprep/qubo/problems/graph_color.py +101 -0
- quprep-0.3.0/quprep/qubo/problems/knapsack.py +82 -0
- quprep-0.3.0/quprep/qubo/problems/maxcut.py +59 -0
- quprep-0.3.0/quprep/qubo/problems/number_partition.py +101 -0
- quprep-0.3.0/quprep/qubo/problems/portfolio.py +87 -0
- quprep-0.3.0/quprep/qubo/problems/scheduling.py +107 -0
- quprep-0.3.0/quprep/qubo/problems/tsp.py +109 -0
- quprep-0.3.0/quprep/qubo/qaoa.py +130 -0
- quprep-0.3.0/quprep/qubo/solver.py +179 -0
- quprep-0.3.0/quprep/qubo/utils.py +59 -0
- quprep-0.3.0/quprep/qubo/visualize.py +178 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_pipeline.py +1 -1
- quprep-0.3.0/tests/test_qubo.py +833 -0
- {quprep-0.2.0 → quprep-0.3.0}/uv.lock +1 -1
- quprep-0.2.0/docs/guides/qubo.md +0 -47
- quprep-0.2.0/quprep/cli.py +0 -169
- quprep-0.2.0/quprep/qubo/__init__.py +0 -1
- quprep-0.2.0/quprep/qubo/constraints.py +0 -30
- quprep-0.2.0/quprep/qubo/converter.py +0 -64
- quprep-0.2.0/quprep/qubo/ising.py +0 -41
- quprep-0.2.0/quprep/qubo/problems/__init__.py +0 -12
- {quprep-0.2.0 → quprep-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/.github/workflows/ci.yml +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/.gitignore +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/.readthedocs.yaml +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/CODE_OF_CONDUCT.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/CONTRIBUTING.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/LICENSE +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/api/encoders.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/api/exporters.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/api/pipeline.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/contributing.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/getting-started/installation.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/getting-started/quickstart.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/guides/encodings.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/guides/export.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/docs/guides/reduction.md +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/examples/01_quickstart.ipynb +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/examples/01_quickstart.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/examples/02_pipeline.ipynb +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/examples/02_pipeline.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/examples/03_encoders.ipynb +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/examples/03_encoders.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/examples/04_export.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/mkdocs.yml +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/clean/__init__.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/clean/categorical.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/clean/imputer.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/clean/outlier.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/clean/selector.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/core/__init__.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/core/dataset.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/core/pipeline.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/core/recommender.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/encode/__init__.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/encode/amplitude.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/encode/angle.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/encode/base.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/encode/basis.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/encode/entangled_angle.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/encode/hamiltonian.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/encode/iqp.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/encode/reupload.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/export/__init__.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/export/cirq_export.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/export/pennylane_export.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/export/qasm_export.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/export/qiskit_export.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/export/tket_export.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/export/visualize.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/ingest/__init__.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/ingest/csv_ingester.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/ingest/numpy_ingester.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/ingest/profiler.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/normalize/__init__.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/normalize/scalers.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/reduce/__init__.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/reduce/hardware_aware.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/reduce/lda.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/reduce/pca.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/quprep/reduce/spectral.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/__init__.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_clean.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_cli.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_encode.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_export.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_ingest.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_normalize.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_recommender.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_reduce.py +0 -0
- {quprep-0.2.0 → quprep-0.3.0}/tests/test_visualize.py +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release:
|
|
10
|
+
name: Create GitHub Release
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Extract changelog for this version
|
|
19
|
+
id: changelog
|
|
20
|
+
run: |
|
|
21
|
+
VERSION="${GITHUB_REF_NAME#v}"
|
|
22
|
+
BODY=$(python3 - <<EOF
|
|
23
|
+
import re, sys
|
|
24
|
+
content = open("CHANGELOG.md").read()
|
|
25
|
+
version = "$VERSION"
|
|
26
|
+
pattern = rf"## \[{re.escape(version)}\][^\n]*\n(.*?)(?=\n## \[|\Z)"
|
|
27
|
+
m = re.search(pattern, content, re.DOTALL)
|
|
28
|
+
print(m.group(1).strip() if m else "")
|
|
29
|
+
EOF
|
|
30
|
+
)
|
|
31
|
+
echo "body<<ENDOFBODY" >> $GITHUB_OUTPUT
|
|
32
|
+
echo "$BODY" >> $GITHUB_OUTPUT
|
|
33
|
+
echo "ENDOFBODY" >> $GITHUB_OUTPUT
|
|
34
|
+
|
|
35
|
+
- name: Create GitHub Release
|
|
36
|
+
uses: softprops/action-gh-release@v2
|
|
37
|
+
with:
|
|
38
|
+
name: ${{ github.ref_name }}
|
|
39
|
+
body: ${{ steps.changelog.outputs.body }}
|
|
40
|
+
draft: false
|
|
41
|
+
prerelease: false
|
|
@@ -5,12 +5,61 @@ All notable changes to QuPrep will be documented in this file.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
QuPrep uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
---
|
|
9
10
|
|
|
10
11
|
## [Unreleased]
|
|
11
12
|
|
|
12
13
|
---
|
|
13
14
|
|
|
15
|
+
## [0.3.0] — 2026-03-21
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
**QUBO / Ising conversion** (`quprep.qubo`)
|
|
20
|
+
- `to_qubo(cost_matrix, constraints, penalty)` — converts any square cost matrix to upper-triangular QUBO form; supports equality and inequality constraints via Lagrangian penalty
|
|
21
|
+
- `QUBOResult` — holds Q matrix, offset, variable map, n_original; `.to_ising()`, `.evaluate(x)`, `.to_dwave()`, `.to_dict()` / `.from_dict()` methods
|
|
22
|
+
- `IsingResult` — holds h, J, offset; `.to_qubo()` round-trip conversion
|
|
23
|
+
- `qubo_to_ising(qubo)` — QUBO → Ising transformation (s = 2x − 1); energy-consistent for all binary inputs
|
|
24
|
+
- `ising_to_qubo(ising)` — Ising → QUBO inverse transformation; completes the bidirectional round-trip
|
|
25
|
+
- `equality_penalty(A, b, penalty)` — encodes Ax = b as a QUBO penalty matrix
|
|
26
|
+
- `inequality_penalty(A, b, penalty)` — encodes Ax ≤ b via binary slack variables; augments Q from (n,n) to (n+K,n+K)
|
|
27
|
+
- `add_qubo(q1, q2, weight)` — combines two same-size QUBOs; useful for multi-objective problems
|
|
28
|
+
|
|
29
|
+
**Problem library** (`quprep.qubo.problems`) — 7 NP-hard combinatorial problems
|
|
30
|
+
- `max_cut(adjacency)` — Max-Cut graph partitioning
|
|
31
|
+
- `knapsack(weights, values, capacity, penalty)` — 0/1 Knapsack
|
|
32
|
+
- `tsp(distance_matrix, penalty)` — Travelling Salesman Problem (n² binary variables)
|
|
33
|
+
- `portfolio(returns, covariance, budget, risk_penalty, budget_penalty)` — Markowitz portfolio optimization
|
|
34
|
+
- `graph_color(adjacency, n_colors, penalty)` — Graph Colouring (n×K binary variables)
|
|
35
|
+
- `scheduling(processing_times, n_machines, penalty)` — Job scheduling / load balancing
|
|
36
|
+
- `number_partition(values, penalty)` — Number Partitioning
|
|
37
|
+
|
|
38
|
+
**Solvers** (`quprep.qubo.solver`)
|
|
39
|
+
- `solve_brute(qubo, max_n=20)` — exact exhaustive solver; evaluates all 2^n states; practical up to n=20
|
|
40
|
+
- `solve_sa(qubo, n_steps, T_start, T_end, seed, restarts)` — simulated annealing heuristic; O(n) incremental energy update with geometric cooling; scales to n ~ 500+
|
|
41
|
+
|
|
42
|
+
**QAOA circuit generator** (`quprep.qubo.qaoa`)
|
|
43
|
+
- `qaoa_circuit(qubo, p, gamma, beta)` — generates a p-layer QAOA ansatz as OpenQASM 3.0; converts QUBO → Ising internally; compatible with Qiskit, Cirq, and any QASM backend
|
|
44
|
+
|
|
45
|
+
**Visualization** (`quprep.qubo.visualize`) — requires `pip install quprep[viz]`
|
|
46
|
+
- `draw_qubo(qubo, title, cmap, ax)` — heatmap of Q matrix with symmetric colour scale; annotates cells for n ≤ 10
|
|
47
|
+
- `draw_ising(ising, title, ax)` — circular graph layout; node colour = h_i bias; edge colour/width = J_ij coupling strength
|
|
48
|
+
|
|
49
|
+
**CLI** (`quprep qubo`)
|
|
50
|
+
- `quprep qubo maxcut --adjacency ... [--solve]`
|
|
51
|
+
- `quprep qubo knapsack --weights ... --values ... --capacity ... [--solve]`
|
|
52
|
+
- `quprep qubo tsp --distances ... [--solve]`
|
|
53
|
+
- `quprep qubo schedule --times ... --machines ... [--solve]`
|
|
54
|
+
- `quprep qubo partition --values ... [--solve]`
|
|
55
|
+
- `quprep qubo portfolio --returns ... --covariance ... --budget ... [--solve]`
|
|
56
|
+
- `quprep qubo graphcolor --adjacency ... --colors ... [--solve]`
|
|
57
|
+
- `quprep qubo qaoa <problem> ... [--p N] [--gamma ...] [--beta ...] [--output file]`
|
|
58
|
+
- `quprep qubo export <problem> ... [--format json|npy] [--output file]`
|
|
59
|
+
- `--solve` auto-switches from exact to simulated annealing for n > 20
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
14
63
|
## [0.2.0] — 2026-03-21
|
|
15
64
|
|
|
16
65
|
### Added
|
|
@@ -49,6 +98,9 @@ QuPrep uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
49
98
|
- `Pipeline` auto-normalizes IQP/re-upload → `minmax_pm_pi`, Hamiltonian → `zscore`
|
|
50
99
|
- `prepare()` accepts `encoding='iqp'`, `'reupload'`, `'hamiltonian'` with matching kwargs
|
|
51
100
|
|
|
101
|
+
### Fixed
|
|
102
|
+
- `HamiltonianEncoder` via `prepare()` and `Pipeline` was broken — `_encoding_key()` returned `"zscore"` (a strategy name) instead of `"hamiltonian"`, causing `auto_normalizer()` to raise `ValueError`
|
|
103
|
+
|
|
52
104
|
---
|
|
53
105
|
|
|
54
106
|
## [0.1.0] — 2026-03-19
|
|
@@ -100,6 +152,7 @@ First public release. Covers the full ingest → clean → normalize → encode
|
|
|
100
152
|
|
|
101
153
|
---
|
|
102
154
|
|
|
103
|
-
[Unreleased]: https://github.com/quprep/quprep/compare/v0.
|
|
155
|
+
[Unreleased]: https://github.com/quprep/quprep/compare/v0.3.0...HEAD
|
|
156
|
+
[0.3.0]: https://github.com/quprep/quprep/compare/v0.2.0...v0.3.0
|
|
104
157
|
[0.2.0]: https://github.com/quprep/quprep/compare/v0.1.0...v0.2.0
|
|
105
158
|
[0.1.0]: https://github.com/quprep/quprep/releases/tag/v0.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quprep
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Quantum data preparation — the missing preprocessing layer between classical datasets and quantum computing frameworks
|
|
5
5
|
Project-URL: Homepage, https://quprep.org
|
|
6
6
|
Project-URL: Documentation, https://quprep.readthedocs.io
|
|
@@ -282,6 +282,9 @@ CSV / DataFrame / NumPy → QuPrep → circuit-ready output for your framewo
|
|
|
282
282
|
- Recommend the best encoding for your dataset and task
|
|
283
283
|
- Export circuits to OpenQASM 3.0, Qiskit, PennyLane, Cirq, and TKET
|
|
284
284
|
- Visualize circuits as ASCII diagrams or matplotlib figures
|
|
285
|
+
- Formulate combinatorial optimization problems as QUBO / Ising models (Max-Cut, TSP, Knapsack, Portfolio, Graph Colouring, Scheduling, Number Partitioning)
|
|
286
|
+
- Solve with exact brute-force (n ≤ 20) or simulated annealing (any n)
|
|
287
|
+
- Generate QAOA circuits and export to D-Wave Ocean SDK format
|
|
285
288
|
|
|
286
289
|
## What QuPrep does NOT do
|
|
287
290
|
|
|
@@ -356,12 +359,38 @@ print(quprep.draw_ascii(result.encoded[0]))
|
|
|
356
359
|
quprep.draw_matplotlib(result.encoded[0], filename="circuit.png")
|
|
357
360
|
```
|
|
358
361
|
|
|
362
|
+
### QUBO / combinatorial optimization
|
|
363
|
+
|
|
364
|
+
```python
|
|
365
|
+
from quprep.qubo import max_cut, knapsack, solve_brute, solve_sa, qaoa_circuit
|
|
366
|
+
import numpy as np
|
|
367
|
+
|
|
368
|
+
# Max-Cut on a weighted graph
|
|
369
|
+
adj = np.array([[0,1,1],[1,0,1],[1,1,0]], dtype=float)
|
|
370
|
+
q = max_cut(adj)
|
|
371
|
+
print(q.evaluate(np.array([0., 1., 1.]))) # -2.0
|
|
372
|
+
|
|
373
|
+
# Brute-force (n ≤ 20) or simulated annealing (any n)
|
|
374
|
+
sol = solve_brute(q) # exact
|
|
375
|
+
sol = solve_sa(q, seed=42) # heuristic, scales to n ~ 500+
|
|
376
|
+
|
|
377
|
+
# Generate a QAOA circuit
|
|
378
|
+
qasm = qaoa_circuit(q, p=2)
|
|
379
|
+
|
|
380
|
+
# D-Wave Ocean SDK export
|
|
381
|
+
bqm_dict = q.to_dwave() # {(i, j): coeff}
|
|
382
|
+
```
|
|
383
|
+
|
|
359
384
|
### CLI
|
|
360
385
|
|
|
361
386
|
```bash
|
|
362
387
|
quprep convert data.csv --encoding angle --framework qasm
|
|
363
388
|
quprep convert data.csv --encoding iqp --framework pennylane
|
|
364
389
|
quprep recommend data.csv --task classification --qubits 8
|
|
390
|
+
|
|
391
|
+
quprep qubo maxcut --adjacency "0,1,1;1,0,1;1,1,0" --solve
|
|
392
|
+
quprep qubo knapsack --weights "2,3,4" --values "3,4,5" --capacity 5
|
|
393
|
+
quprep qubo qaoa maxcut --adjacency "0,1,1;1,0,1;1,1,0" --p 2 --output circuit.qasm
|
|
365
394
|
```
|
|
366
395
|
|
|
367
396
|
---
|
|
@@ -413,6 +442,7 @@ See the [`examples/`](examples/) directory:
|
|
|
413
442
|
| 04 | Framework export — QASM, Qiskit, PennyLane, Cirq, TKET |
|
|
414
443
|
| 05 | Encoding recommendation |
|
|
415
444
|
| 06 | Circuit visualization |
|
|
445
|
+
| 07 | QUBO / Ising — Max-Cut, Knapsack, solvers, D-Wave export, QAOA |
|
|
416
446
|
|
|
417
447
|
---
|
|
418
448
|
|
|
@@ -28,6 +28,9 @@ CSV / DataFrame / NumPy → QuPrep → circuit-ready output for your framewo
|
|
|
28
28
|
- Recommend the best encoding for your dataset and task
|
|
29
29
|
- Export circuits to OpenQASM 3.0, Qiskit, PennyLane, Cirq, and TKET
|
|
30
30
|
- Visualize circuits as ASCII diagrams or matplotlib figures
|
|
31
|
+
- Formulate combinatorial optimization problems as QUBO / Ising models (Max-Cut, TSP, Knapsack, Portfolio, Graph Colouring, Scheduling, Number Partitioning)
|
|
32
|
+
- Solve with exact brute-force (n ≤ 20) or simulated annealing (any n)
|
|
33
|
+
- Generate QAOA circuits and export to D-Wave Ocean SDK format
|
|
31
34
|
|
|
32
35
|
## What QuPrep does NOT do
|
|
33
36
|
|
|
@@ -102,12 +105,38 @@ print(quprep.draw_ascii(result.encoded[0]))
|
|
|
102
105
|
quprep.draw_matplotlib(result.encoded[0], filename="circuit.png")
|
|
103
106
|
```
|
|
104
107
|
|
|
108
|
+
### QUBO / combinatorial optimization
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from quprep.qubo import max_cut, knapsack, solve_brute, solve_sa, qaoa_circuit
|
|
112
|
+
import numpy as np
|
|
113
|
+
|
|
114
|
+
# Max-Cut on a weighted graph
|
|
115
|
+
adj = np.array([[0,1,1],[1,0,1],[1,1,0]], dtype=float)
|
|
116
|
+
q = max_cut(adj)
|
|
117
|
+
print(q.evaluate(np.array([0., 1., 1.]))) # -2.0
|
|
118
|
+
|
|
119
|
+
# Brute-force (n ≤ 20) or simulated annealing (any n)
|
|
120
|
+
sol = solve_brute(q) # exact
|
|
121
|
+
sol = solve_sa(q, seed=42) # heuristic, scales to n ~ 500+
|
|
122
|
+
|
|
123
|
+
# Generate a QAOA circuit
|
|
124
|
+
qasm = qaoa_circuit(q, p=2)
|
|
125
|
+
|
|
126
|
+
# D-Wave Ocean SDK export
|
|
127
|
+
bqm_dict = q.to_dwave() # {(i, j): coeff}
|
|
128
|
+
```
|
|
129
|
+
|
|
105
130
|
### CLI
|
|
106
131
|
|
|
107
132
|
```bash
|
|
108
133
|
quprep convert data.csv --encoding angle --framework qasm
|
|
109
134
|
quprep convert data.csv --encoding iqp --framework pennylane
|
|
110
135
|
quprep recommend data.csv --task classification --qubits 8
|
|
136
|
+
|
|
137
|
+
quprep qubo maxcut --adjacency "0,1,1;1,0,1;1,1,0" --solve
|
|
138
|
+
quprep qubo knapsack --weights "2,3,4" --values "3,4,5" --capacity 5
|
|
139
|
+
quprep qubo qaoa maxcut --adjacency "0,1,1;1,0,1;1,1,0" --p 2 --output circuit.qasm
|
|
111
140
|
```
|
|
112
141
|
|
|
113
142
|
---
|
|
@@ -159,6 +188,7 @@ See the [`examples/`](examples/) directory:
|
|
|
159
188
|
| 04 | Framework export — QASM, Qiskit, PennyLane, Cirq, TKET |
|
|
160
189
|
| 05 | Encoding recommendation |
|
|
161
190
|
| 06 | Circuit visualization |
|
|
191
|
+
| 07 | QUBO / Ising — Max-Cut, Knapsack, solvers, D-Wave export, QAOA |
|
|
162
192
|
|
|
163
193
|
---
|
|
164
194
|
|
|
@@ -17,7 +17,7 @@ Everything else is accessed via submodules.
|
|
|
17
17
|
```python
|
|
18
18
|
import quprep
|
|
19
19
|
|
|
20
|
-
quprep.__version__ # "0.
|
|
20
|
+
quprep.__version__ # "0.3.0"
|
|
21
21
|
quprep.prepare(...)
|
|
22
22
|
quprep.Pipeline(...)
|
|
23
23
|
quprep.recommend(...)
|
|
@@ -54,6 +54,14 @@ quprep.draw_matplotlib(...)
|
|
|
54
54
|
| `quprep.ingest.numpy_ingester` | `NumpyIngester` |
|
|
55
55
|
| `quprep.ingest.profiler` | `profile`, `DatasetProfile` |
|
|
56
56
|
| `quprep.core.dataset` | `Dataset` |
|
|
57
|
+
| `quprep.qubo` | `to_qubo`, `QUBOResult`, `qubo_to_ising`, `ising_to_qubo`, `IsingResult` |
|
|
58
|
+
| `quprep.qubo.problems` | `max_cut`, `knapsack`, `tsp`, `portfolio`, `graph_color`, `scheduling`, `number_partition` |
|
|
59
|
+
| `quprep.qubo.solver` | `solve_brute`, `solve_sa`, `SolveResult` |
|
|
60
|
+
| `quprep.qubo.qaoa` | `qaoa_circuit` |
|
|
61
|
+
| `quprep.qubo.constraints` | `equality_penalty`, `inequality_penalty` |
|
|
62
|
+
| `quprep.qubo.ising` | `qubo_to_ising`, `ising_to_qubo` |
|
|
63
|
+
| `quprep.qubo.utils` | `add_qubo` |
|
|
64
|
+
| `quprep.qubo.visualize` | `draw_qubo`, `draw_ising` |
|
|
57
65
|
|
|
58
66
|
---
|
|
59
67
|
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# QUBO / Ising
|
|
2
|
+
|
|
3
|
+
QUBO (Quadratic Unconstrained Binary Optimization) is the standard input format for quantum annealers (D-Wave) and QAOA circuits. QuPrep handles the full pipeline: problem formulation → QUBO matrix → Ising model → QAOA circuit or annealer export.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick example
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import numpy as np
|
|
11
|
+
from quprep.qubo import max_cut, solve_brute, qaoa_circuit
|
|
12
|
+
|
|
13
|
+
# Max-Cut on a triangle graph
|
|
14
|
+
adj = np.array([[0,1,1],[1,0,1],[1,1,0]], dtype=float)
|
|
15
|
+
q = max_cut(adj)
|
|
16
|
+
|
|
17
|
+
print(q) # QUBOResult(n_variables=3, offset=0.0)
|
|
18
|
+
print(q.Q) # 3×3 upper-triangular Q matrix
|
|
19
|
+
|
|
20
|
+
# Brute-force solve (exact, n ≤ 20)
|
|
21
|
+
sol = solve_brute(q)
|
|
22
|
+
print(sol.energy) # -2.0
|
|
23
|
+
|
|
24
|
+
# Generate a QAOA circuit
|
|
25
|
+
qasm = qaoa_circuit(q, p=2)
|
|
26
|
+
print(qasm[:60]) # OPENQASM 3.0; ...
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## QUBOResult
|
|
32
|
+
|
|
33
|
+
All problem functions return a `QUBOResult`:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from quprep.qubo import max_cut
|
|
37
|
+
import numpy as np
|
|
38
|
+
|
|
39
|
+
q = max_cut(np.array([[0,1],[1,0]], dtype=float))
|
|
40
|
+
|
|
41
|
+
q.Q # np.ndarray (n, n) — upper-triangular Q matrix
|
|
42
|
+
q.offset # float — constant energy offset
|
|
43
|
+
q.variable_map # dict — name → index mapping
|
|
44
|
+
q.n_original # int — original variable count (before slack)
|
|
45
|
+
|
|
46
|
+
# Evaluate a solution
|
|
47
|
+
q.evaluate(np.array([0.0, 1.0])) # x^T Q x + offset
|
|
48
|
+
|
|
49
|
+
# Convert to Ising
|
|
50
|
+
ising = q.to_ising()
|
|
51
|
+
ising.h # bias vector
|
|
52
|
+
ising.J # coupling matrix (upper-triangular)
|
|
53
|
+
|
|
54
|
+
# Serialize
|
|
55
|
+
d = q.to_dict() # JSON-compatible dict
|
|
56
|
+
q2 = QUBOResult.from_dict(d)
|
|
57
|
+
|
|
58
|
+
# D-Wave Ocean SDK export
|
|
59
|
+
bqm_dict = q.to_dwave() # {(i, j): coeff} i <= j
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Problem library
|
|
65
|
+
|
|
66
|
+
Seven NP-hard combinatorial problems, ready to formulate as QUBO:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import numpy as np
|
|
70
|
+
from quprep.qubo import (
|
|
71
|
+
max_cut, knapsack, tsp, portfolio,
|
|
72
|
+
graph_color, scheduling, number_partition,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Max-Cut
|
|
76
|
+
adj = np.array([[0,1,1],[1,0,1],[1,1,0]], dtype=float)
|
|
77
|
+
q = max_cut(adj)
|
|
78
|
+
|
|
79
|
+
# 0/1 Knapsack
|
|
80
|
+
q = knapsack(
|
|
81
|
+
weights=np.array([2.0, 3.0, 4.0]),
|
|
82
|
+
values=np.array([3.0, 4.0, 5.0]),
|
|
83
|
+
capacity=5.0,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Travelling Salesman Problem (n² variables)
|
|
87
|
+
D = np.array([[0,1,2],[1,0,1],[2,1,0]], dtype=float)
|
|
88
|
+
q = tsp(D)
|
|
89
|
+
|
|
90
|
+
# Markowitz Portfolio Optimization
|
|
91
|
+
mu = np.array([0.1, 0.2, 0.15, 0.05])
|
|
92
|
+
Sigma = np.eye(4) * 0.01
|
|
93
|
+
q = portfolio(mu, Sigma, budget=2)
|
|
94
|
+
|
|
95
|
+
# Graph Colouring
|
|
96
|
+
q = graph_color(adj, n_colors=3)
|
|
97
|
+
|
|
98
|
+
# Job Scheduling (load balancing)
|
|
99
|
+
q = scheduling(processing_times=np.array([3.0,1.0,4.0,2.0]), n_machines=2)
|
|
100
|
+
|
|
101
|
+
# Number Partitioning
|
|
102
|
+
q = number_partition(values=np.array([3.0,1.0,1.0,2.0,2.0,1.0]))
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Solvers
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from quprep.qubo import solve_brute, solve_sa, max_cut
|
|
111
|
+
import numpy as np
|
|
112
|
+
|
|
113
|
+
adj = np.array([[0,1,1],[1,0,1],[1,1,0]], dtype=float)
|
|
114
|
+
q = max_cut(adj)
|
|
115
|
+
|
|
116
|
+
# Exact — exhaustive 2^n search (n ≤ 20)
|
|
117
|
+
sol = solve_brute(q)
|
|
118
|
+
print(sol.x) # optimal binary vector
|
|
119
|
+
print(sol.energy) # optimal energy
|
|
120
|
+
|
|
121
|
+
# Simulated annealing — scales to n ~ 500+
|
|
122
|
+
sol = solve_sa(q, n_steps=10_000, restarts=3, seed=42)
|
|
123
|
+
print(sol.energy)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Constraints
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from quprep.qubo import to_qubo
|
|
132
|
+
from quprep.qubo.constraints import equality_penalty, inequality_penalty
|
|
133
|
+
import numpy as np
|
|
134
|
+
|
|
135
|
+
# Equality constraint: x0 + x1 + x2 = 1
|
|
136
|
+
Q_pen, offset = equality_penalty(
|
|
137
|
+
A=np.array([[1.0, 1.0, 1.0]]),
|
|
138
|
+
b=np.array([1.0]),
|
|
139
|
+
penalty=10.0,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Inequality constraint: x0 + x1 ≤ 1 (adds slack variables)
|
|
143
|
+
Q_pen, offset, n_slack = inequality_penalty(
|
|
144
|
+
A=np.array([[1.0, 1.0]]),
|
|
145
|
+
b=np.array([1.0]),
|
|
146
|
+
penalty=10.0,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Or pass constraints directly to to_qubo()
|
|
150
|
+
cost = np.diag([-1.0, -2.0, -3.0])
|
|
151
|
+
q = to_qubo(cost, constraints=[
|
|
152
|
+
{"type": "eq", "A": np.ones((1, 3)), "b": np.array([1.0]), "penalty": 10.0},
|
|
153
|
+
{"type": "ineq", "A": np.array([[1.0, 1.0, 0.0]]), "b": np.array([1.0])},
|
|
154
|
+
])
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Ising conversion
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from quprep.qubo import qubo_to_ising, ising_to_qubo, max_cut
|
|
163
|
+
import numpy as np
|
|
164
|
+
|
|
165
|
+
q = max_cut(np.array([[0,1,1],[1,0,1],[1,1,0]], dtype=float))
|
|
166
|
+
|
|
167
|
+
# QUBO → Ising
|
|
168
|
+
ising = qubo_to_ising(q) # or: q.to_ising()
|
|
169
|
+
print(ising.h) # bias vector h_i
|
|
170
|
+
print(ising.J) # coupling matrix J_ij
|
|
171
|
+
|
|
172
|
+
# Ising → QUBO (round-trip)
|
|
173
|
+
q2 = ising_to_qubo(ising) # or: ising.to_qubo()
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## QAOA circuit generation
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from quprep.qubo import qaoa_circuit, max_cut
|
|
182
|
+
import numpy as np
|
|
183
|
+
|
|
184
|
+
adj = np.array([[0,1,1],[1,0,1],[1,1,0]], dtype=float)
|
|
185
|
+
q = max_cut(adj)
|
|
186
|
+
|
|
187
|
+
# Generate p-layer QAOA circuit (OpenQASM 3.0)
|
|
188
|
+
qasm = qaoa_circuit(q, p=2)
|
|
189
|
+
|
|
190
|
+
# Custom parameters
|
|
191
|
+
qasm = qaoa_circuit(q, p=2, gamma=[0.5, 0.3], beta=[0.2, 0.1])
|
|
192
|
+
|
|
193
|
+
# Write to file
|
|
194
|
+
from pathlib import Path
|
|
195
|
+
Path("qaoa_maxcut.qasm").write_text(qasm)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Combining QUBOs
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from quprep.qubo import add_qubo, max_cut
|
|
204
|
+
from quprep.qubo.constraints import equality_penalty
|
|
205
|
+
from quprep.qubo.converter import QUBOResult
|
|
206
|
+
import numpy as np
|
|
207
|
+
|
|
208
|
+
q_obj = max_cut(np.array([[0,1],[1,0]], dtype=float))
|
|
209
|
+
Q_pen, off = equality_penalty(np.array([[1.0, 1.0]]), np.array([1.0]), 5.0)
|
|
210
|
+
q_pen = QUBOResult(Q=Q_pen, offset=off)
|
|
211
|
+
|
|
212
|
+
q_combined = add_qubo(q_obj, q_pen, weight=2.0)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Visualization
|
|
218
|
+
|
|
219
|
+
Requires `pip install quprep[viz]`.
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from quprep.qubo import draw_qubo, draw_ising, max_cut
|
|
223
|
+
import numpy as np
|
|
224
|
+
|
|
225
|
+
adj = np.array([[0,1,1],[1,0,1],[1,1,0]], dtype=float)
|
|
226
|
+
q = max_cut(adj)
|
|
227
|
+
|
|
228
|
+
# Heatmap of Q matrix
|
|
229
|
+
ax = draw_qubo(q, title="Max-Cut QUBO")
|
|
230
|
+
|
|
231
|
+
# Circular Ising graph
|
|
232
|
+
ax = draw_ising(q.to_ising(), title="Max-Cut Ising")
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## CLI
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Problem formulation
|
|
241
|
+
quprep qubo maxcut --adjacency "0,1,1;1,0,1;1,1,0" --solve
|
|
242
|
+
quprep qubo knapsack --weights "2,3,4" --values "3,4,5" --capacity 5 --solve
|
|
243
|
+
quprep qubo tsp --distances "0,1,2;1,0,1;2,1,0"
|
|
244
|
+
quprep qubo schedule --times "3,1,4,2" --machines 2
|
|
245
|
+
quprep qubo partition --values "3,1,1,2,2,1" --solve
|
|
246
|
+
quprep qubo portfolio --returns "0.5,0.3,0.2" --covariance "0.1,0.02,0.01;0.02,0.05,0.01;0.01,0.01,0.08" --budget 2
|
|
247
|
+
quprep qubo graphcolor --adjacency "0,1,1;1,0,1;1,1,0" --colors 3
|
|
248
|
+
|
|
249
|
+
# QAOA circuit
|
|
250
|
+
quprep qubo qaoa maxcut --adjacency "0,1,1;1,0,1;1,1,0" --p 2 --output circuit.qasm
|
|
251
|
+
|
|
252
|
+
# Export Q matrix
|
|
253
|
+
quprep qubo export maxcut --adjacency "0,1,1;1,0,1;1,1,0" --format json --output q.json
|
|
254
|
+
quprep qubo export knapsack --weights "2,3,4" --values "3,4,5" --capacity 5 --format npy
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
`--solve` automatically uses exact brute-force for n ≤ 20 and simulated annealing for larger problems.
|
|
@@ -75,7 +75,7 @@ qnode = result.circuit # callable qml.QNode
|
|
|
75
75
|
| **Encode+** | ✅ v0.2.0 | IQP, Entangled Angle, Data re-uploading, Hamiltonian |
|
|
76
76
|
| **Export+** | ✅ v0.2.0 | PennyLane, Cirq, TKET, ASCII + matplotlib visualization |
|
|
77
77
|
| **Recommend** | ✅ v0.2.0 | Automatic encoding selection for your dataset and task |
|
|
78
|
-
| **QUBO** |
|
|
78
|
+
| **QUBO** | ✅ v0.3.0 | QUBO/Ising conversion, 7 problem formulations, solvers, QAOA, D-Wave export |
|
|
79
79
|
|
|
80
80
|
---
|
|
81
81
|
|
|
@@ -100,4 +100,8 @@ quprep convert data.csv --encoding angle --framework qasm
|
|
|
100
100
|
quprep convert data.csv --encoding iqp --framework pennylane
|
|
101
101
|
quprep convert data.csv --encoding basis --samples 10 --output circuits.qasm
|
|
102
102
|
quprep recommend data.csv --task classification --qubits 8
|
|
103
|
+
|
|
104
|
+
quprep qubo maxcut --adjacency "0,1,1;1,0,1;1,1,0" --solve
|
|
105
|
+
quprep qubo knapsack --weights "2,3,4" --values "3,4,5" --capacity 5
|
|
106
|
+
quprep qubo qaoa maxcut --adjacency "0,1,1;1,0,1;1,1,0" --p 2 --output circuit.qasm
|
|
103
107
|
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Example 07 — QUBO / Ising
|
|
3
|
+
|
|
4
|
+
Demonstrates:
|
|
5
|
+
- Problem formulation (Max-Cut, Knapsack)
|
|
6
|
+
- Brute-force and simulated-annealing solvers
|
|
7
|
+
- QUBO ↔ Ising round-trip
|
|
8
|
+
- D-Wave export
|
|
9
|
+
- QAOA circuit generation
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from quprep.qubo import (
|
|
15
|
+
ising_to_qubo,
|
|
16
|
+
knapsack,
|
|
17
|
+
max_cut,
|
|
18
|
+
qaoa_circuit,
|
|
19
|
+
qubo_to_ising,
|
|
20
|
+
solve_brute,
|
|
21
|
+
solve_sa,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# ── Max-Cut ───────────────────────────────────────────────────────────────────
|
|
25
|
+
print("── Max-Cut ──────────────────────────────────────────────────────────────")
|
|
26
|
+
|
|
27
|
+
adj = np.array([[0, 1, 1, 0],
|
|
28
|
+
[1, 0, 1, 1],
|
|
29
|
+
[1, 1, 0, 1],
|
|
30
|
+
[0, 1, 1, 0]], dtype=float)
|
|
31
|
+
|
|
32
|
+
q = max_cut(adj)
|
|
33
|
+
print(f"Variables : {q.Q.shape[0]}")
|
|
34
|
+
print(f"Offset : {q.offset}")
|
|
35
|
+
|
|
36
|
+
sol = solve_brute(q)
|
|
37
|
+
bits = "".join(str(int(b)) for b in sol.x)
|
|
38
|
+
print(f"Exact solution : x={bits} energy={sol.energy:.4f}")
|
|
39
|
+
|
|
40
|
+
# Evaluate a specific assignment manually
|
|
41
|
+
x_test = np.array([0.0, 1.0, 0.0, 1.0])
|
|
42
|
+
print(f"evaluate([0,1,0,1]) = {q.evaluate(x_test):.4f}")
|
|
43
|
+
|
|
44
|
+
# ── Ising round-trip ──────────────────────────────────────────────────────────
|
|
45
|
+
print("\n── Ising round-trip ─────────────────────────────────────────────────────")
|
|
46
|
+
|
|
47
|
+
ising = q.to_ising()
|
|
48
|
+
print(f"Ising h : {ising.h}")
|
|
49
|
+
print(f"Ising J matrix:\n{ising.J}")
|
|
50
|
+
|
|
51
|
+
q2 = ising.to_qubo()
|
|
52
|
+
print(f"Round-trip Q matches: {np.allclose(q.Q, q2.Q)}")
|
|
53
|
+
|
|
54
|
+
# ── D-Wave export ─────────────────────────────────────────────────────────────
|
|
55
|
+
print("\n── D-Wave export ────────────────────────────────────────────────────────")
|
|
56
|
+
|
|
57
|
+
dwave = q.to_dwave()
|
|
58
|
+
print(f"D-Wave BQM dict ({len(dwave)} entries):")
|
|
59
|
+
for (i, j), v in list(dwave.items())[:5]:
|
|
60
|
+
print(f" ({i},{j}): {v:.4f}")
|
|
61
|
+
|
|
62
|
+
# Standalone ising_to_qubo
|
|
63
|
+
q3 = ising_to_qubo(qubo_to_ising(q))
|
|
64
|
+
print(f"ising_to_qubo() round-trip matches: {np.allclose(q.Q, q3.Q)}")
|
|
65
|
+
|
|
66
|
+
# ── Knapsack with simulated annealing ─────────────────────────────────────────
|
|
67
|
+
print("\n── Knapsack (SA solver) ─────────────────────────────────────────────────")
|
|
68
|
+
|
|
69
|
+
weights = np.array([2.0, 3.0, 4.0, 5.0, 6.0])
|
|
70
|
+
values = np.array([3.0, 4.0, 5.0, 6.0, 7.0])
|
|
71
|
+
kq = knapsack(weights, values, capacity=10.0)
|
|
72
|
+
print(f"Variables : {kq.Q.shape[0]}")
|
|
73
|
+
|
|
74
|
+
sol_sa = solve_sa(kq, n_steps=20_000, restarts=3, seed=42)
|
|
75
|
+
bits_sa = "".join(str(int(b)) for b in sol_sa.x[:len(weights)])
|
|
76
|
+
print(f"SA solution : x={bits_sa} energy={sol_sa.energy:.4f}")
|
|
77
|
+
|
|
78
|
+
sol_exact = solve_brute(kq)
|
|
79
|
+
bits_exact = "".join(str(int(b)) for b in sol_exact.x[:len(weights)])
|
|
80
|
+
print(f"Exact : x={bits_exact} energy={sol_exact.energy:.4f}")
|
|
81
|
+
|
|
82
|
+
# ── QAOA circuit ─────────────────────────────────────────────────────────────
|
|
83
|
+
print("\n── QAOA circuit ─────────────────────────────────────────────────────────")
|
|
84
|
+
|
|
85
|
+
small_adj = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]], dtype=float)
|
|
86
|
+
qsmall = max_cut(small_adj)
|
|
87
|
+
qasm = qaoa_circuit(qsmall, p=2)
|
|
88
|
+
lines = qasm.strip().splitlines()
|
|
89
|
+
print(f"QAOA circuit ({len(lines)} lines):")
|
|
90
|
+
for line in lines[:6]:
|
|
91
|
+
print(f" {line}")
|
|
92
|
+
print(" ...")
|
|
93
|
+
|
|
94
|
+
print("\nDone.")
|
|
@@ -10,6 +10,7 @@ Each example is a runnable Python script.
|
|
|
10
10
|
| 04 | Framework export — QASM, Qiskit, PennyLane, Cirq, TKET | `04_export.py` |
|
|
11
11
|
| 05 | Encoding recommendation — `recommend()` | `05_recommend.py` |
|
|
12
12
|
| 06 | Circuit visualization — ASCII + matplotlib | `06_visualization.py` |
|
|
13
|
+
| 07 | QUBO / Ising — Max-Cut, Knapsack, solvers, D-Wave export, QAOA | `07_qubo.py` |
|
|
13
14
|
|
|
14
15
|
## Run a script
|
|
15
16
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "quprep"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Quantum data preparation — the missing preprocessing layer between classical datasets and quantum computing frameworks"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -20,7 +20,7 @@ The missing preprocessing layer between classical datasets and quantum computing
|
|
|
20
20
|
rec = quprep.recommend(df, task="classification", qubits=8)
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
__version__ = "0.
|
|
23
|
+
__version__ = "0.3.0"
|
|
24
24
|
__author__ = "Hasarindu Perera"
|
|
25
25
|
__license__ = "Apache-2.0"
|
|
26
26
|
|