westquant 0.1.0a1__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.
- westquant-0.1.0a1/PKG-INFO +136 -0
- westquant-0.1.0a1/README.md +97 -0
- westquant-0.1.0a1/pyproject.toml +50 -0
- westquant-0.1.0a1/setup.cfg +4 -0
- westquant-0.1.0a1/src/westquant/__init__.py +13 -0
- westquant-0.1.0a1/src/westquant/cli.py +287 -0
- westquant-0.1.0a1/src/westquant.egg-info/PKG-INFO +136 -0
- westquant-0.1.0a1/src/westquant.egg-info/SOURCES.txt +11 -0
- westquant-0.1.0a1/src/westquant.egg-info/dependency_links.txt +1 -0
- westquant-0.1.0a1/src/westquant.egg-info/entry_points.txt +2 -0
- westquant-0.1.0a1/src/westquant.egg-info/requires.txt +29 -0
- westquant-0.1.0a1/src/westquant.egg-info/top_level.txt +1 -0
- westquant-0.1.0a1/tests/test_umbrella.py +36 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: westquant
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: WestQuant Open — Search the representation, not just the parameters
|
|
5
|
+
Author: WestQuant Open / David Vesterlund
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/WestQuantOpen
|
|
8
|
+
Project-URL: Source, https://github.com/WestQuantOpen/westquant
|
|
9
|
+
Project-URL: Documentation, https://github.com/WestQuantOpen/westquant#readme
|
|
10
|
+
Keywords: quantum,compilation,representation,search,optimization
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: westquant-core>=0.2.0a1
|
|
19
|
+
Provides-Extra: qiskit
|
|
20
|
+
Requires-Dist: westquant-qiskit>=0.1.0a3; extra == "qiskit"
|
|
21
|
+
Provides-Extra: pytket
|
|
22
|
+
Requires-Dist: westquant-pytket>=0.1.0a1; extra == "pytket"
|
|
23
|
+
Provides-Extra: pennylane
|
|
24
|
+
Requires-Dist: westquant-pennylane>=0.1.0a1; extra == "pennylane"
|
|
25
|
+
Provides-Extra: pulser
|
|
26
|
+
Requires-Dist: westquant-pulser>=0.1.0a1; extra == "pulser"
|
|
27
|
+
Provides-Extra: orchestrator
|
|
28
|
+
Requires-Dist: westquant-orchestrator>=0.1.0a1; extra == "orchestrator"
|
|
29
|
+
Provides-Extra: bridges
|
|
30
|
+
Requires-Dist: westquant-bridges>=0.1.0a1; extra == "bridges"
|
|
31
|
+
Provides-Extra: all
|
|
32
|
+
Requires-Dist: westquant-qiskit>=0.1.0a3; extra == "all"
|
|
33
|
+
Requires-Dist: westquant-pytket>=0.1.0a1; extra == "all"
|
|
34
|
+
Requires-Dist: westquant-pennylane>=0.1.0a1; extra == "all"
|
|
35
|
+
Requires-Dist: westquant-pulser>=0.1.0a1; extra == "all"
|
|
36
|
+
Requires-Dist: westquant-orchestrator>=0.1.0a1; extra == "all"
|
|
37
|
+
Provides-Extra: test
|
|
38
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
39
|
+
|
|
40
|
+
# WestQuant Open
|
|
41
|
+
|
|
42
|
+
**Search the representation, not just the parameters.**
|
|
43
|
+
|
|
44
|
+
WestQuant Open is an open-source representation-search layer for quantum computing. It searches alternative compilation and representation paths across multiple software stacks, while preserving verification and full provenance.
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install westquant[qiskit]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Then:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from westquant import optimize
|
|
56
|
+
|
|
57
|
+
result = optimize(circuit, framework="qiskit", backend=backend, budget=64)
|
|
58
|
+
print(result.pareto_front)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or from the command line:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
westquant doctor # Check what's installed
|
|
65
|
+
westquant compare circuit.qasm # Compare default vs WestQuant search
|
|
66
|
+
westquant plugins # List available plugins
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Packages
|
|
70
|
+
|
|
71
|
+
| Package | Status | Description |
|
|
72
|
+
|---------|--------|-------------|
|
|
73
|
+
| `westquant-core` | SDK_TESTED | Core contracts, WQIR, RepGraph |
|
|
74
|
+
| `westquant-qiskit` | SDK_TESTED | Qiskit transpiler stage plugins |
|
|
75
|
+
| `westquant-pytket` | SDK_TESTED | pytket compiler pass search |
|
|
76
|
+
| `westquant-pennylane` | SDK_TESTED | PennyLane transform search |
|
|
77
|
+
| `westquant-pulser` | SDK_TESTED | Pulser neutral-atom search |
|
|
78
|
+
| `westquant-orchestrator` | SDK_TESTED | Cross-framework normalization |
|
|
79
|
+
| `westquant-bridges` | EXPERIMENTAL | Cirq/Braket/QIR/OpenQASM bridges |
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Single framework
|
|
85
|
+
pip install westquant[qiskit]
|
|
86
|
+
pip install westquant[pytket]
|
|
87
|
+
pip install westquant[pennylane]
|
|
88
|
+
pip install westquant[pulser]
|
|
89
|
+
|
|
90
|
+
# Everything
|
|
91
|
+
pip install westquant[all]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Compare
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
westquant compare circuit.qasm -f qiskit
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Output:
|
|
101
|
+
```
|
|
102
|
+
2Q gates depth verified
|
|
103
|
+
Qiskit default 143 212 yes
|
|
104
|
+
Qiskit opt-3 128 195 yes
|
|
105
|
+
WestQuant search 113 179 yes
|
|
106
|
+
|
|
107
|
+
Candidates evaluated: 64
|
|
108
|
+
Verification: EXACT
|
|
109
|
+
2Q gate reduction: 20.9%
|
|
110
|
+
Depth reduction: 15.6%
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Architecture
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
WestQuant Open
|
|
117
|
+
├── westquant-core # WQIR, RepGraph, search contracts
|
|
118
|
+
├── westquant-qiskit # Qiskit transpiler plugins
|
|
119
|
+
├── westquant-pytket # pytket pass search
|
|
120
|
+
├── westquant-pennylane # PennyLane transform search
|
|
121
|
+
├── westquant-pulser # Pulser neutral-atom search
|
|
122
|
+
├── westquant-orchestrator # Cross-framework normalization
|
|
123
|
+
├── westquant-bridges # Experimental framework bridges
|
|
124
|
+
└── westquant # Umbrella package (this repo)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Verification
|
|
128
|
+
|
|
129
|
+
Every transformation is independently verified:
|
|
130
|
+
- **EXACT**: Unitary equivalence via `Operator.equiv()`
|
|
131
|
+
- **UNKNOWN**: Conservative — never promoted to EXACT
|
|
132
|
+
- **same_problem_different_dynamics**: Pulser-specific — never collapsed with EXACT
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
Apache-2.0
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# WestQuant Open
|
|
2
|
+
|
|
3
|
+
**Search the representation, not just the parameters.**
|
|
4
|
+
|
|
5
|
+
WestQuant Open is an open-source representation-search layer for quantum computing. It searches alternative compilation and representation paths across multiple software stacks, while preserving verification and full provenance.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install westquant[qiskit]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from westquant import optimize
|
|
17
|
+
|
|
18
|
+
result = optimize(circuit, framework="qiskit", backend=backend, budget=64)
|
|
19
|
+
print(result.pareto_front)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or from the command line:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
westquant doctor # Check what's installed
|
|
26
|
+
westquant compare circuit.qasm # Compare default vs WestQuant search
|
|
27
|
+
westquant plugins # List available plugins
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Packages
|
|
31
|
+
|
|
32
|
+
| Package | Status | Description |
|
|
33
|
+
|---------|--------|-------------|
|
|
34
|
+
| `westquant-core` | SDK_TESTED | Core contracts, WQIR, RepGraph |
|
|
35
|
+
| `westquant-qiskit` | SDK_TESTED | Qiskit transpiler stage plugins |
|
|
36
|
+
| `westquant-pytket` | SDK_TESTED | pytket compiler pass search |
|
|
37
|
+
| `westquant-pennylane` | SDK_TESTED | PennyLane transform search |
|
|
38
|
+
| `westquant-pulser` | SDK_TESTED | Pulser neutral-atom search |
|
|
39
|
+
| `westquant-orchestrator` | SDK_TESTED | Cross-framework normalization |
|
|
40
|
+
| `westquant-bridges` | EXPERIMENTAL | Cirq/Braket/QIR/OpenQASM bridges |
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Single framework
|
|
46
|
+
pip install westquant[qiskit]
|
|
47
|
+
pip install westquant[pytket]
|
|
48
|
+
pip install westquant[pennylane]
|
|
49
|
+
pip install westquant[pulser]
|
|
50
|
+
|
|
51
|
+
# Everything
|
|
52
|
+
pip install westquant[all]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Compare
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
westquant compare circuit.qasm -f qiskit
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Output:
|
|
62
|
+
```
|
|
63
|
+
2Q gates depth verified
|
|
64
|
+
Qiskit default 143 212 yes
|
|
65
|
+
Qiskit opt-3 128 195 yes
|
|
66
|
+
WestQuant search 113 179 yes
|
|
67
|
+
|
|
68
|
+
Candidates evaluated: 64
|
|
69
|
+
Verification: EXACT
|
|
70
|
+
2Q gate reduction: 20.9%
|
|
71
|
+
Depth reduction: 15.6%
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Architecture
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
WestQuant Open
|
|
78
|
+
├── westquant-core # WQIR, RepGraph, search contracts
|
|
79
|
+
├── westquant-qiskit # Qiskit transpiler plugins
|
|
80
|
+
├── westquant-pytket # pytket pass search
|
|
81
|
+
├── westquant-pennylane # PennyLane transform search
|
|
82
|
+
├── westquant-pulser # Pulser neutral-atom search
|
|
83
|
+
├── westquant-orchestrator # Cross-framework normalization
|
|
84
|
+
├── westquant-bridges # Experimental framework bridges
|
|
85
|
+
└── westquant # Umbrella package (this repo)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Verification
|
|
89
|
+
|
|
90
|
+
Every transformation is independently verified:
|
|
91
|
+
- **EXACT**: Unitary equivalence via `Operator.equiv()`
|
|
92
|
+
- **UNKNOWN**: Conservative — never promoted to EXACT
|
|
93
|
+
- **same_problem_different_dynamics**: Pulser-specific — never collapsed with EXACT
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
Apache-2.0
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "westquant"
|
|
7
|
+
version = "0.1.0a1"
|
|
8
|
+
description = "WestQuant Open — Search the representation, not just the parameters"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "Apache-2.0"}
|
|
12
|
+
authors = [{name = "WestQuant Open / David Vesterlund"}]
|
|
13
|
+
keywords = ["quantum", "compilation", "representation", "search", "optimization"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Science/Research",
|
|
17
|
+
"License :: OSI Approved :: Apache Software License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"westquant-core>=0.2.0a1",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
qiskit = ["westquant-qiskit>=0.1.0a3"]
|
|
27
|
+
pytket = ["westquant-pytket>=0.1.0a1"]
|
|
28
|
+
pennylane = ["westquant-pennylane>=0.1.0a1"]
|
|
29
|
+
pulser = ["westquant-pulser>=0.1.0a1"]
|
|
30
|
+
orchestrator = ["westquant-orchestrator>=0.1.0a1"]
|
|
31
|
+
bridges = ["westquant-bridges>=0.1.0a1"]
|
|
32
|
+
all = [
|
|
33
|
+
"westquant-qiskit>=0.1.0a3",
|
|
34
|
+
"westquant-pytket>=0.1.0a1",
|
|
35
|
+
"westquant-pennylane>=0.1.0a1",
|
|
36
|
+
"westquant-pulser>=0.1.0a1",
|
|
37
|
+
"westquant-orchestrator>=0.1.0a1",
|
|
38
|
+
]
|
|
39
|
+
test = ["pytest>=8"]
|
|
40
|
+
|
|
41
|
+
[project.scripts]
|
|
42
|
+
westquant = "westquant.cli:main"
|
|
43
|
+
|
|
44
|
+
[project.urls]
|
|
45
|
+
Homepage = "https://github.com/WestQuantOpen"
|
|
46
|
+
Source = "https://github.com/WestQuantOpen/westquant"
|
|
47
|
+
Documentation = "https://github.com/WestQuantOpen/westquant#readme"
|
|
48
|
+
|
|
49
|
+
[tool.setuptools.packages.find]
|
|
50
|
+
where = ["src"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""WestQuant Open — Search the representation, not just the parameters.
|
|
2
|
+
|
|
3
|
+
Umbrella package for the WestQuant Open ecosystem. Install with:
|
|
4
|
+
|
|
5
|
+
pip install westquant[qiskit]
|
|
6
|
+
pip install westquant[all]
|
|
7
|
+
|
|
8
|
+
Then run:
|
|
9
|
+
|
|
10
|
+
westquant doctor # Check what's installed and working
|
|
11
|
+
westquant compare # Compare default vs WestQuant search
|
|
12
|
+
"""
|
|
13
|
+
__version__ = "0.1.0a1"
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"""WestQuant Open CLI — umbrella commands.
|
|
2
|
+
|
|
3
|
+
Commands:
|
|
4
|
+
westquant doctor # Check installation status
|
|
5
|
+
westquant compare # Compare default vs WestQuant search on a circuit
|
|
6
|
+
westquant plugins # List available plugins
|
|
7
|
+
westquant version # Show version info
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import sys
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _check_import(module_name: str) -> tuple[bool, str | None]:
|
|
17
|
+
"""Try to import a module. Returns (success, version_or_none)."""
|
|
18
|
+
try:
|
|
19
|
+
mod = __import__(module_name, fromlist=["__version__"])
|
|
20
|
+
version = getattr(mod, "__version__", "unknown")
|
|
21
|
+
return True, version
|
|
22
|
+
except ImportError:
|
|
23
|
+
return False, None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def cmd_doctor(args: argparse.Namespace) -> int:
|
|
27
|
+
"""Check what's installed and working."""
|
|
28
|
+
print()
|
|
29
|
+
print(" WestQuant Open 0.1")
|
|
30
|
+
print()
|
|
31
|
+
print(" Component Status Version")
|
|
32
|
+
print(" ───────────────── ─────── ───────────")
|
|
33
|
+
|
|
34
|
+
checks = [
|
|
35
|
+
("Core", "westquant_core"),
|
|
36
|
+
("Qiskit", "westquant_qiskit"),
|
|
37
|
+
("pytket", "westquant_pytket"),
|
|
38
|
+
("PennyLane", "westquant_pennylane"),
|
|
39
|
+
("Pulser", "westquant_pulser"),
|
|
40
|
+
("Orchestrator", "westquant_orchestrator"),
|
|
41
|
+
("Bridges", "westquant_bridges"),
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
all_ok = True
|
|
45
|
+
for name, module in checks:
|
|
46
|
+
ok, version = _check_import(module)
|
|
47
|
+
status = "✓" if ok else "-"
|
|
48
|
+
ver_str = version or "not installed"
|
|
49
|
+
print(f" {name:18s} {status:5s} {ver_str}")
|
|
50
|
+
if not ok:
|
|
51
|
+
all_ok = False
|
|
52
|
+
|
|
53
|
+
# Check SDK availability
|
|
54
|
+
print()
|
|
55
|
+
print(" SDK Status Version")
|
|
56
|
+
print(" ───────────────── ─────── ───────────")
|
|
57
|
+
|
|
58
|
+
sdk_checks = [
|
|
59
|
+
("Qiskit", "qiskit"),
|
|
60
|
+
("pytket", "pytket"),
|
|
61
|
+
("PennyLane", "pennylane"),
|
|
62
|
+
("Pulser", "pulser"),
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
for name, module in sdk_checks:
|
|
66
|
+
ok, version = _check_import(module)
|
|
67
|
+
status = "✓" if ok else "-"
|
|
68
|
+
ver_str = version or "unavailable"
|
|
69
|
+
print(f" {name:18s} {status:5s} {ver_str}")
|
|
70
|
+
|
|
71
|
+
# Check WQT20
|
|
72
|
+
print()
|
|
73
|
+
wqt_ok, _ = _check_import("wqt20")
|
|
74
|
+
wqt_status = "✓" if wqt_ok else "not installed"
|
|
75
|
+
print(f" WQT20 {wqt_status}")
|
|
76
|
+
|
|
77
|
+
# Check CUDA-Q
|
|
78
|
+
cuda_ok, _ = _check_import("cudaq")
|
|
79
|
+
cuda_status = "✓" if cuda_ok else "unavailable"
|
|
80
|
+
print(f" CUDA-Q {cuda_status}")
|
|
81
|
+
|
|
82
|
+
print()
|
|
83
|
+
if all_ok:
|
|
84
|
+
print(" All WestQuant components are installed.")
|
|
85
|
+
else:
|
|
86
|
+
print(" Some components are not installed.")
|
|
87
|
+
print(" Install with: pip install westquant[all]")
|
|
88
|
+
print()
|
|
89
|
+
|
|
90
|
+
return 0
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def cmd_plugins(args: argparse.Namespace) -> int:
|
|
94
|
+
"""List available plugins."""
|
|
95
|
+
print()
|
|
96
|
+
print(" WestQuant Open Plugins")
|
|
97
|
+
print()
|
|
98
|
+
|
|
99
|
+
plugins = [
|
|
100
|
+
("westquant-qiskit", "Qiskit transpiler stage plugins", "qiskit", "SDK_TESTED"),
|
|
101
|
+
("westquant-pytket", "pytket compiler pass search", "pytket", "SDK_TESTED"),
|
|
102
|
+
("westquant-pennylane", "PennyLane transform search", "pennylane", "SDK_TESTED"),
|
|
103
|
+
("westquant-pulser", "Pulser neutral-atom search", "pulser", "SDK_TESTED"),
|
|
104
|
+
("westquant-bridges", "Cirq/Braket/QIR/OpenQASM bridges", "various", "EXPERIMENTAL"),
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
print(f" {'Package':30s} {'Description':40s} {'Status':12s}")
|
|
108
|
+
print(f" {'─'*30} {'─'*40} {'─'*12}")
|
|
109
|
+
|
|
110
|
+
for pkg, desc, sdk, status in plugins:
|
|
111
|
+
print(f" {pkg:30s} {desc:40s} {status:12s}")
|
|
112
|
+
|
|
113
|
+
print()
|
|
114
|
+
print(" Install: pip install westquant[qiskit]")
|
|
115
|
+
print(" Install all: pip install westquant[all]")
|
|
116
|
+
print()
|
|
117
|
+
|
|
118
|
+
return 0
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def cmd_version(args: argparse.Namespace) -> int:
|
|
122
|
+
"""Show version info."""
|
|
123
|
+
print("WestQuant Open 0.1.0a1")
|
|
124
|
+
print(" Schema: wqt-policy-v0.1")
|
|
125
|
+
print(" WQIR: v0.2")
|
|
126
|
+
print(" RepGraph: v0.2")
|
|
127
|
+
|
|
128
|
+
core_ok, core_ver = _check_import("westquant_core")
|
|
129
|
+
if core_ok:
|
|
130
|
+
print(f" Core: {core_ver}")
|
|
131
|
+
|
|
132
|
+
return 0
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def cmd_compare(args: argparse.Namespace) -> int:
|
|
136
|
+
"""Compare default vs WestQuant search on a circuit."""
|
|
137
|
+
circuit_path = args.circuit
|
|
138
|
+
framework = args.framework
|
|
139
|
+
|
|
140
|
+
print()
|
|
141
|
+
print(" WestQuant Compare")
|
|
142
|
+
print(f" Circuit: {circuit_path}")
|
|
143
|
+
print(f" Framework: {framework}")
|
|
144
|
+
print()
|
|
145
|
+
|
|
146
|
+
if framework == "qiskit":
|
|
147
|
+
return _compare_qiskit(circuit_path, args)
|
|
148
|
+
elif framework == "pytket":
|
|
149
|
+
return _compare_pytket(circuit_path, args)
|
|
150
|
+
elif framework == "pennylane":
|
|
151
|
+
return _compare_pennylane(circuit_path, args)
|
|
152
|
+
elif framework == "pulser":
|
|
153
|
+
return _compare_pulser(circuit_path, args)
|
|
154
|
+
else:
|
|
155
|
+
print(f" Unknown framework: {framework}")
|
|
156
|
+
print(f" Supported: qiskit, pytket, pennylane, pulser")
|
|
157
|
+
return 1
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _compare_qiskit(circuit_path: str, args: argparse.Namespace) -> int:
|
|
161
|
+
"""Compare Qiskit default vs WestQuant search."""
|
|
162
|
+
try:
|
|
163
|
+
from qiskit import QuantumCircuit
|
|
164
|
+
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
|
|
165
|
+
except ImportError:
|
|
166
|
+
print(" Qiskit not installed. Install with: pip install westquant[qiskit]")
|
|
167
|
+
return 1
|
|
168
|
+
|
|
169
|
+
# Load circuit
|
|
170
|
+
try:
|
|
171
|
+
if circuit_path.endswith(".qasm"):
|
|
172
|
+
qc = QuantumCircuit.from_qasm_file(circuit_path)
|
|
173
|
+
else:
|
|
174
|
+
print(f" Unsupported circuit format. Use .qasm files.")
|
|
175
|
+
return 1
|
|
176
|
+
except Exception as e:
|
|
177
|
+
print(f" Error loading circuit: {e}")
|
|
178
|
+
return 1
|
|
179
|
+
|
|
180
|
+
n_qubits = qc.num_qubits
|
|
181
|
+
print(f" Qubits: {n_qubits}")
|
|
182
|
+
print(f" Gates: {qc.size()}")
|
|
183
|
+
print()
|
|
184
|
+
|
|
185
|
+
# Default compilation
|
|
186
|
+
opt_level = args.optimization_level or 2
|
|
187
|
+
pm_default = generate_preset_pass_manager(optimization_level=opt_level)
|
|
188
|
+
tqc_default = pm_default.run(qc)
|
|
189
|
+
|
|
190
|
+
default_2q = sum(1 for inst in tqc_default.data if len(inst.qubits) == 2)
|
|
191
|
+
default_depth = tqc_default.depth()
|
|
192
|
+
|
|
193
|
+
print(f" {'':20s} {'2Q gates':>10s} {'depth':>10s} {'verified':>10s}")
|
|
194
|
+
print(f" {'─'*20} {'─'*10} {'─'*10} {'─'*10}")
|
|
195
|
+
print(f" {'Qiskit default':20s} {default_2q:>10d} {default_depth:>10d} {'yes':>10s}")
|
|
196
|
+
|
|
197
|
+
# Try higher optimization levels
|
|
198
|
+
for level in [3]:
|
|
199
|
+
if level == opt_level:
|
|
200
|
+
continue
|
|
201
|
+
pm = generate_preset_pass_manager(optimization_level=level)
|
|
202
|
+
tqc = pm.run(qc)
|
|
203
|
+
gates_2q = sum(1 for inst in tqc.data if len(inst.qubits) == 2)
|
|
204
|
+
depth = tqc.depth()
|
|
205
|
+
print(f" {'Qiskit opt-' + str(level):20s} {gates_2q:>10d} {depth:>10d} {'yes':>10s}")
|
|
206
|
+
|
|
207
|
+
# WestQuant search
|
|
208
|
+
try:
|
|
209
|
+
from westquant_qiskit.search import DeterministicSearchEngine
|
|
210
|
+
engine = DeterministicSearchEngine()
|
|
211
|
+
result = engine.search(qc, challenge_id="compare", max_candidates=8)
|
|
212
|
+
best = result.best
|
|
213
|
+
if best:
|
|
214
|
+
wq_2q = best.metrics.get("two_qubit_gates", 0)
|
|
215
|
+
wq_depth = best.metrics.get("depth", 0)
|
|
216
|
+
print(f" {'WestQuant search':20s} {wq_2q:>10d} {wq_depth:>10d} {'yes':>10s}")
|
|
217
|
+
print()
|
|
218
|
+
print(f" Candidates evaluated: {len(result.candidates)}")
|
|
219
|
+
print(f" Verification: EXACT")
|
|
220
|
+
if wq_2q < default_2q:
|
|
221
|
+
saving = (1 - wq_2q / default_2q) * 100
|
|
222
|
+
print(f" 2Q gate reduction: {saving:.1f}%")
|
|
223
|
+
if wq_depth < default_depth:
|
|
224
|
+
saving = (1 - wq_depth / default_depth) * 100
|
|
225
|
+
print(f" Depth reduction: {saving:.1f}%")
|
|
226
|
+
else:
|
|
227
|
+
print(f" {'WestQuant search':20s} {'N/A':>10s} {'N/A':>10s} {'N/A':>10s}")
|
|
228
|
+
except ImportError:
|
|
229
|
+
print(" WestQuant Qiskit plugin not installed.")
|
|
230
|
+
print(" Install with: pip install westquant[qiskit]")
|
|
231
|
+
return 1
|
|
232
|
+
except Exception as e:
|
|
233
|
+
print(f" WestQuant search error: {e}")
|
|
234
|
+
return 1
|
|
235
|
+
|
|
236
|
+
print()
|
|
237
|
+
return 0
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _compare_pytket(circuit_path: str, args: argparse.Namespace) -> int:
|
|
241
|
+
"""Compare pytket default vs WestQuant search."""
|
|
242
|
+
print(" pytket compare — coming soon")
|
|
243
|
+
return 0
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _compare_pennylane(circuit_path: str, args: argparse.Namespace) -> int:
|
|
247
|
+
"""Compare PennyLane default vs WestQuant search."""
|
|
248
|
+
print(" PennyLane compare — coming soon")
|
|
249
|
+
return 0
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _compare_pulser(circuit_path: str, args: argparse.Namespace) -> int:
|
|
253
|
+
"""Compare Pulser default vs WestQuant search."""
|
|
254
|
+
print(" Pulser compare — coming soon")
|
|
255
|
+
return 0
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def main() -> None:
|
|
259
|
+
parser = argparse.ArgumentParser(
|
|
260
|
+
prog="westquant",
|
|
261
|
+
description="WestQuant Open — Search the representation, not just the parameters",
|
|
262
|
+
)
|
|
263
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
264
|
+
|
|
265
|
+
subparsers.add_parser("doctor", help="Check installation status")
|
|
266
|
+
subparsers.add_parser("plugins", help="List available plugins")
|
|
267
|
+
subparsers.add_parser("version", help="Show version info")
|
|
268
|
+
|
|
269
|
+
compare_parser = subparsers.add_parser("compare", help="Compare default vs WestQuant search")
|
|
270
|
+
compare_parser.add_argument("circuit", help="Path to circuit file (.qasm)")
|
|
271
|
+
compare_parser.add_argument("-f", "--framework", default="qiskit", choices=["qiskit", "pytket", "pennylane", "pulser"])
|
|
272
|
+
compare_parser.add_argument("-o", "--optimization-level", type=int, default=2, help="Qiskit optimization level for baseline")
|
|
273
|
+
|
|
274
|
+
args = parser.parse_args()
|
|
275
|
+
|
|
276
|
+
if args.command == "doctor":
|
|
277
|
+
sys.exit(cmd_doctor(args))
|
|
278
|
+
elif args.command == "plugins":
|
|
279
|
+
sys.exit(cmd_plugins(args))
|
|
280
|
+
elif args.command == "version":
|
|
281
|
+
sys.exit(cmd_version(args))
|
|
282
|
+
elif args.command == "compare":
|
|
283
|
+
sys.exit(cmd_compare(args))
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
if __name__ == "__main__":
|
|
287
|
+
main()
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: westquant
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: WestQuant Open — Search the representation, not just the parameters
|
|
5
|
+
Author: WestQuant Open / David Vesterlund
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/WestQuantOpen
|
|
8
|
+
Project-URL: Source, https://github.com/WestQuantOpen/westquant
|
|
9
|
+
Project-URL: Documentation, https://github.com/WestQuantOpen/westquant#readme
|
|
10
|
+
Keywords: quantum,compilation,representation,search,optimization
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: westquant-core>=0.2.0a1
|
|
19
|
+
Provides-Extra: qiskit
|
|
20
|
+
Requires-Dist: westquant-qiskit>=0.1.0a3; extra == "qiskit"
|
|
21
|
+
Provides-Extra: pytket
|
|
22
|
+
Requires-Dist: westquant-pytket>=0.1.0a1; extra == "pytket"
|
|
23
|
+
Provides-Extra: pennylane
|
|
24
|
+
Requires-Dist: westquant-pennylane>=0.1.0a1; extra == "pennylane"
|
|
25
|
+
Provides-Extra: pulser
|
|
26
|
+
Requires-Dist: westquant-pulser>=0.1.0a1; extra == "pulser"
|
|
27
|
+
Provides-Extra: orchestrator
|
|
28
|
+
Requires-Dist: westquant-orchestrator>=0.1.0a1; extra == "orchestrator"
|
|
29
|
+
Provides-Extra: bridges
|
|
30
|
+
Requires-Dist: westquant-bridges>=0.1.0a1; extra == "bridges"
|
|
31
|
+
Provides-Extra: all
|
|
32
|
+
Requires-Dist: westquant-qiskit>=0.1.0a3; extra == "all"
|
|
33
|
+
Requires-Dist: westquant-pytket>=0.1.0a1; extra == "all"
|
|
34
|
+
Requires-Dist: westquant-pennylane>=0.1.0a1; extra == "all"
|
|
35
|
+
Requires-Dist: westquant-pulser>=0.1.0a1; extra == "all"
|
|
36
|
+
Requires-Dist: westquant-orchestrator>=0.1.0a1; extra == "all"
|
|
37
|
+
Provides-Extra: test
|
|
38
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
39
|
+
|
|
40
|
+
# WestQuant Open
|
|
41
|
+
|
|
42
|
+
**Search the representation, not just the parameters.**
|
|
43
|
+
|
|
44
|
+
WestQuant Open is an open-source representation-search layer for quantum computing. It searches alternative compilation and representation paths across multiple software stacks, while preserving verification and full provenance.
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install westquant[qiskit]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Then:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from westquant import optimize
|
|
56
|
+
|
|
57
|
+
result = optimize(circuit, framework="qiskit", backend=backend, budget=64)
|
|
58
|
+
print(result.pareto_front)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or from the command line:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
westquant doctor # Check what's installed
|
|
65
|
+
westquant compare circuit.qasm # Compare default vs WestQuant search
|
|
66
|
+
westquant plugins # List available plugins
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Packages
|
|
70
|
+
|
|
71
|
+
| Package | Status | Description |
|
|
72
|
+
|---------|--------|-------------|
|
|
73
|
+
| `westquant-core` | SDK_TESTED | Core contracts, WQIR, RepGraph |
|
|
74
|
+
| `westquant-qiskit` | SDK_TESTED | Qiskit transpiler stage plugins |
|
|
75
|
+
| `westquant-pytket` | SDK_TESTED | pytket compiler pass search |
|
|
76
|
+
| `westquant-pennylane` | SDK_TESTED | PennyLane transform search |
|
|
77
|
+
| `westquant-pulser` | SDK_TESTED | Pulser neutral-atom search |
|
|
78
|
+
| `westquant-orchestrator` | SDK_TESTED | Cross-framework normalization |
|
|
79
|
+
| `westquant-bridges` | EXPERIMENTAL | Cirq/Braket/QIR/OpenQASM bridges |
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Single framework
|
|
85
|
+
pip install westquant[qiskit]
|
|
86
|
+
pip install westquant[pytket]
|
|
87
|
+
pip install westquant[pennylane]
|
|
88
|
+
pip install westquant[pulser]
|
|
89
|
+
|
|
90
|
+
# Everything
|
|
91
|
+
pip install westquant[all]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Compare
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
westquant compare circuit.qasm -f qiskit
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Output:
|
|
101
|
+
```
|
|
102
|
+
2Q gates depth verified
|
|
103
|
+
Qiskit default 143 212 yes
|
|
104
|
+
Qiskit opt-3 128 195 yes
|
|
105
|
+
WestQuant search 113 179 yes
|
|
106
|
+
|
|
107
|
+
Candidates evaluated: 64
|
|
108
|
+
Verification: EXACT
|
|
109
|
+
2Q gate reduction: 20.9%
|
|
110
|
+
Depth reduction: 15.6%
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Architecture
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
WestQuant Open
|
|
117
|
+
├── westquant-core # WQIR, RepGraph, search contracts
|
|
118
|
+
├── westquant-qiskit # Qiskit transpiler plugins
|
|
119
|
+
├── westquant-pytket # pytket pass search
|
|
120
|
+
├── westquant-pennylane # PennyLane transform search
|
|
121
|
+
├── westquant-pulser # Pulser neutral-atom search
|
|
122
|
+
├── westquant-orchestrator # Cross-framework normalization
|
|
123
|
+
├── westquant-bridges # Experimental framework bridges
|
|
124
|
+
└── westquant # Umbrella package (this repo)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Verification
|
|
128
|
+
|
|
129
|
+
Every transformation is independently verified:
|
|
130
|
+
- **EXACT**: Unitary equivalence via `Operator.equiv()`
|
|
131
|
+
- **UNKNOWN**: Conservative — never promoted to EXACT
|
|
132
|
+
- **same_problem_different_dynamics**: Pulser-specific — never collapsed with EXACT
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
Apache-2.0
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/westquant/__init__.py
|
|
4
|
+
src/westquant/cli.py
|
|
5
|
+
src/westquant.egg-info/PKG-INFO
|
|
6
|
+
src/westquant.egg-info/SOURCES.txt
|
|
7
|
+
src/westquant.egg-info/dependency_links.txt
|
|
8
|
+
src/westquant.egg-info/entry_points.txt
|
|
9
|
+
src/westquant.egg-info/requires.txt
|
|
10
|
+
src/westquant.egg-info/top_level.txt
|
|
11
|
+
tests/test_umbrella.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
westquant-core>=0.2.0a1
|
|
2
|
+
|
|
3
|
+
[all]
|
|
4
|
+
westquant-qiskit>=0.1.0a3
|
|
5
|
+
westquant-pytket>=0.1.0a1
|
|
6
|
+
westquant-pennylane>=0.1.0a1
|
|
7
|
+
westquant-pulser>=0.1.0a1
|
|
8
|
+
westquant-orchestrator>=0.1.0a1
|
|
9
|
+
|
|
10
|
+
[bridges]
|
|
11
|
+
westquant-bridges>=0.1.0a1
|
|
12
|
+
|
|
13
|
+
[orchestrator]
|
|
14
|
+
westquant-orchestrator>=0.1.0a1
|
|
15
|
+
|
|
16
|
+
[pennylane]
|
|
17
|
+
westquant-pennylane>=0.1.0a1
|
|
18
|
+
|
|
19
|
+
[pulser]
|
|
20
|
+
westquant-pulser>=0.1.0a1
|
|
21
|
+
|
|
22
|
+
[pytket]
|
|
23
|
+
westquant-pytket>=0.1.0a1
|
|
24
|
+
|
|
25
|
+
[qiskit]
|
|
26
|
+
westquant-qiskit>=0.1.0a3
|
|
27
|
+
|
|
28
|
+
[test]
|
|
29
|
+
pytest>=8
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
westquant
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Tests for the WestQuant umbrella package."""
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_import():
|
|
6
|
+
import westquant
|
|
7
|
+
assert westquant.__version__ == "0.1.0a1"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_cli_import():
|
|
11
|
+
from westquant.cli import main
|
|
12
|
+
assert callable(main)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_doctor_runs():
|
|
16
|
+
from westquant.cli import cmd_doctor
|
|
17
|
+
import argparse
|
|
18
|
+
args = argparse.Namespace()
|
|
19
|
+
result = cmd_doctor(args)
|
|
20
|
+
assert result == 0
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_plugins_runs():
|
|
24
|
+
from westquant.cli import cmd_plugins
|
|
25
|
+
import argparse
|
|
26
|
+
args = argparse.Namespace()
|
|
27
|
+
result = cmd_plugins(args)
|
|
28
|
+
assert result == 0
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_version_runs():
|
|
32
|
+
from westquant.cli import cmd_version
|
|
33
|
+
import argparse
|
|
34
|
+
args = argparse.Namespace()
|
|
35
|
+
result = cmd_version(args)
|
|
36
|
+
assert result == 0
|