marqov 0.2.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.
- marqov-0.2.0/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
- marqov-0.2.0/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- marqov-0.2.0/.github/PULL_REQUEST_TEMPLATE.md +28 -0
- marqov-0.2.0/.github/workflows/ci.yml +24 -0
- marqov-0.2.0/.github/workflows/release.yml +46 -0
- marqov-0.2.0/.gitignore +19 -0
- marqov-0.2.0/CHANGELOG.md +34 -0
- marqov-0.2.0/CODE_OF_CONDUCT.md +54 -0
- marqov-0.2.0/CONTRIBUTING.md +204 -0
- marqov-0.2.0/LICENSE +184 -0
- marqov-0.2.0/PKG-INFO +240 -0
- marqov-0.2.0/README.md +159 -0
- marqov-0.2.0/SECURITY.md +20 -0
- marqov-0.2.0/benchmarks/__init__.py +1 -0
- marqov-0.2.0/benchmarks/harness.py +124 -0
- marqov-0.2.0/benchmarks/raw_sdk/bell_state_dm1.py +249 -0
- marqov-0.2.0/benchmarks/raw_sdk/bell_state_ionq.py +251 -0
- marqov-0.2.0/benchmarks/raw_sdk/bell_state_ionq_aria.py +238 -0
- marqov-0.2.0/benchmarks/raw_sdk/bell_state_iqm.py +261 -0
- marqov-0.2.0/benchmarks/raw_sdk/bell_state_iqm_emerald.py +261 -0
- marqov-0.2.0/benchmarks/raw_sdk/bell_state_rigetti.py +236 -0
- marqov-0.2.0/benchmarks/raw_sdk/bell_state_sv1.py +128 -0
- marqov-0.2.0/benchmarks/raw_sdk/bell_state_tn1.py +152 -0
- marqov-0.2.0/benchmarks/raw_sdk/harness.py +122 -0
- marqov-0.2.0/benchmarks/raw_sdk/mis_quera_aquila.py +322 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_dm1.py +126 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_ionq.py +126 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_ionq_aria.py +126 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_iqm.py +126 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_iqm_emerald.py +126 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_local.py +264 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_rigetti.py +126 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_sv1.py +126 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_sv1_raw.py +274 -0
- marqov-0.2.0/benchmarks/raw_sdk/vqe_h2_tn1.py +126 -0
- marqov-0.2.0/benchmarks/shared/__init__.py +25 -0
- marqov-0.2.0/benchmarks/shared/vqe_h2.py +311 -0
- marqov-0.2.0/benchmarks/shared/vqe_h2_chemistry.py +369 -0
- marqov-0.2.0/benchmarks/suite.py +294 -0
- marqov-0.2.0/marqov/__init__.py +63 -0
- marqov-0.2.0/marqov/backends.py +23 -0
- marqov-0.2.0/marqov/benchmarking/__init__.py +21 -0
- marqov-0.2.0/marqov/benchmarking/spam.py +240 -0
- marqov-0.2.0/marqov/circuits.py +955 -0
- marqov-0.2.0/marqov/cli/__init__.py +365 -0
- marqov-0.2.0/marqov/device.py +303 -0
- marqov-0.2.0/marqov/executors/__init__.py +53 -0
- marqov-0.2.0/marqov/executors/azure.py +485 -0
- marqov-0.2.0/marqov/executors/base.py +155 -0
- marqov-0.2.0/marqov/executors/braket.py +342 -0
- marqov-0.2.0/marqov/executors/factory.py +427 -0
- marqov-0.2.0/marqov/executors/ibm.py +316 -0
- marqov-0.2.0/marqov/executors/ionq.py +428 -0
- marqov-0.2.0/marqov/executors/local.py +119 -0
- marqov-0.2.0/marqov/executors/quantinuum.py +245 -0
- marqov-0.2.0/marqov/executors/rigetti.py +319 -0
- marqov-0.2.0/marqov/experiments/__init__.py +5 -0
- marqov-0.2.0/marqov/experiments/preflight.py +163 -0
- marqov-0.2.0/marqov/simulation/__init__.py +21 -0
- marqov-0.2.0/marqov/simulation/backends.py +67 -0
- marqov-0.2.0/marqov/simulation/circuit_converter.py +71 -0
- marqov-0.2.0/marqov/simulation/config.py +56 -0
- marqov-0.2.0/marqov/simulation/executor.py +176 -0
- marqov-0.2.0/marqov/simulation/noise.py +162 -0
- marqov-0.2.0/marqov/workflows/__init__.py +75 -0
- marqov-0.2.0/marqov/workflows/activity.py +195 -0
- marqov-0.2.0/marqov/workflows/decorators.py +476 -0
- marqov-0.2.0/marqov/workflows/graph.py +302 -0
- marqov-0.2.0/marqov/workflows/runner.py +73 -0
- marqov-0.2.0/marqov/workflows/temporal_workflow.py +189 -0
- marqov-0.2.0/pyproject.toml +135 -0
- marqov-0.2.0/tests/__init__.py +1 -0
- marqov-0.2.0/tests/conftest.py +1 -0
- marqov-0.2.0/tests/experiments/__init__.py +0 -0
- marqov-0.2.0/tests/experiments/test_preflight.py +146 -0
- marqov-0.2.0/tests/integration/__init__.py +0 -0
- marqov-0.2.0/tests/integration/test_qristal_spike.py +230 -0
- marqov-0.2.0/tests/integration/test_rigetti_qvm.py +71 -0
- marqov-0.2.0/tests/test_activity_heartbeat.py +116 -0
- marqov-0.2.0/tests/test_azure_bitorder.py +80 -0
- marqov-0.2.0/tests/test_benchmark_suite.py +366 -0
- marqov-0.2.0/tests/test_circuits.py +726 -0
- marqov-0.2.0/tests/test_decorators.py +239 -0
- marqov-0.2.0/tests/test_device_integration.py +167 -0
- marqov-0.2.0/tests/test_executors.py +824 -0
- marqov-0.2.0/tests/test_ionq_executor.py +524 -0
- marqov-0.2.0/tests/test_noise.py +455 -0
- marqov-0.2.0/tests/test_rigetti_executor.py +257 -0
- marqov-0.2.0/tests/test_simulation.py +436 -0
- marqov-0.2.0/tests/test_spam.py +189 -0
- marqov-0.2.0/tests/test_spam_correction.py +147 -0
- marqov-0.2.0/tests/test_temporal_activities.py +608 -0
- marqov-0.2.0/tests/test_temporal_runner.py +135 -0
- marqov-0.2.0/tests/test_temporal_workflow.py +504 -0
- marqov-0.2.0/tests/test_version.py +18 -0
- marqov-0.2.0/tests/test_workflow_dispatch_start.py +57 -0
- marqov-0.2.0/tests/test_workflows.py +33 -0
- marqov-0.2.0/tools/check_no_url_deps.py +35 -0
- marqov-0.2.0/tools/verify_marqov_wheel.py +15 -0
- marqov-0.2.0/tools/verify_sdk_against_fork.py +33 -0
- marqov-0.2.0/uv.lock +3367 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report a bug in the Marqov SDK
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**Describe the bug**
|
|
8
|
+
A clear description of what the bug is.
|
|
9
|
+
|
|
10
|
+
**To reproduce**
|
|
11
|
+
Minimal code example that reproduces the issue:
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from marqov.circuits import Circuit
|
|
15
|
+
from marqov.executors.local import LocalExecutor
|
|
16
|
+
# ...
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Expected behavior**
|
|
20
|
+
What you expected to happen.
|
|
21
|
+
|
|
22
|
+
**Actual behavior**
|
|
23
|
+
What actually happened, including any error messages or tracebacks.
|
|
24
|
+
|
|
25
|
+
**Environment**
|
|
26
|
+
- marqov version: (run `pip show marqov`)
|
|
27
|
+
- Python version: (run `python --version`)
|
|
28
|
+
- OS:
|
|
29
|
+
- Provider/executor:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest a new feature or improvement
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**What problem does this solve?**
|
|
8
|
+
Describe the use case or limitation you're running into.
|
|
9
|
+
|
|
10
|
+
**Proposed solution**
|
|
11
|
+
Describe what you'd like to see added or changed.
|
|
12
|
+
|
|
13
|
+
**Alternatives considered**
|
|
14
|
+
Any alternative solutions or workarounds you've considered.
|
|
15
|
+
|
|
16
|
+
**Additional context**
|
|
17
|
+
Links to provider documentation, related issues, or examples.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
Brief description of what this PR does.
|
|
4
|
+
|
|
5
|
+
## Type of change
|
|
6
|
+
|
|
7
|
+
- [ ] Bug fix
|
|
8
|
+
- [ ] New executor
|
|
9
|
+
- [ ] Circuit format converter
|
|
10
|
+
- [ ] Documentation
|
|
11
|
+
- [ ] Other (describe):
|
|
12
|
+
|
|
13
|
+
## Testing
|
|
14
|
+
|
|
15
|
+
- [ ] I ran `pytest tests/ -v` and tests pass
|
|
16
|
+
- [ ] For new executors: tested against local simulator or QVM (describe below)
|
|
17
|
+
- [ ] For circuit converters: roundtrip test passes with known-correct reference circuit
|
|
18
|
+
|
|
19
|
+
**Test details:**
|
|
20
|
+
|
|
21
|
+
## Checklist
|
|
22
|
+
|
|
23
|
+
- [ ] No hardcoded credentials or API keys
|
|
24
|
+
- [ ] Handles the canonical gate set from `CONTRIBUTING.md §1` (if adding a circuit converter)
|
|
25
|
+
|
|
26
|
+
**For new executors only:**
|
|
27
|
+
- [ ] Registered in `ExecutorFactory` per `CONTRIBUTING.md §3`
|
|
28
|
+
- [ ] `get_status()` returns device-level availability (`"online"/"offline"/"maintenance"`), not job-level status
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: ["**"]
|
|
5
|
+
pull_request:
|
|
6
|
+
jobs:
|
|
7
|
+
test:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v4
|
|
11
|
+
- uses: actions/setup-python@v5
|
|
12
|
+
with: { python-version: "3.12" }
|
|
13
|
+
- name: Install uv
|
|
14
|
+
run: pip install uv
|
|
15
|
+
# Install the [all] backend extras (qiskit/cirq/pennylane/pytket/quantinuum/
|
|
16
|
+
# pyquil): the circuit-interop / device / executor tests import these at
|
|
17
|
+
# module load and HARD-FAIL (ModuleNotFoundError) rather than skip when
|
|
18
|
+
# absent. Installing them is what makes the full suite green.
|
|
19
|
+
- name: Install (with all backend extras + dev)
|
|
20
|
+
run: uv pip install --system -e ".[all,dev]"
|
|
21
|
+
- name: No-URL-deps guard
|
|
22
|
+
run: python tools/check_no_url_deps.py
|
|
23
|
+
- name: Test suite
|
|
24
|
+
run: pytest tests/ -q
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags: ["v*"]
|
|
5
|
+
workflow_dispatch: # manual TestPyPI dry-run
|
|
6
|
+
jobs:
|
|
7
|
+
build:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v4
|
|
11
|
+
- uses: actions/setup-python@v5
|
|
12
|
+
with: { python-version: "3.12" }
|
|
13
|
+
- run: pip install uv && uv build
|
|
14
|
+
- name: Assert built version matches the tag (tag pushes only)
|
|
15
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
16
|
+
run: |
|
|
17
|
+
TAG="${GITHUB_REF_NAME#v}"
|
|
18
|
+
test -f "dist/marqov-${TAG}-py3-none-any.whl" \
|
|
19
|
+
|| { echo "FAIL: built wheel is not version ${TAG} (check pyproject version)"; ls dist/; exit 1; }
|
|
20
|
+
echo "version OK: ${TAG}"
|
|
21
|
+
- uses: actions/upload-artifact@v4
|
|
22
|
+
with: { name: dist, path: dist/ }
|
|
23
|
+
|
|
24
|
+
publish-testpypi:
|
|
25
|
+
needs: build
|
|
26
|
+
if: github.event_name == 'workflow_dispatch'
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
environment: testpypi
|
|
29
|
+
permissions: { id-token: write }
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/download-artifact@v4
|
|
32
|
+
with: { name: dist, path: dist/ }
|
|
33
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
34
|
+
with:
|
|
35
|
+
repository-url: https://test.pypi.org/legacy/
|
|
36
|
+
|
|
37
|
+
publish-pypi:
|
|
38
|
+
needs: build
|
|
39
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
environment: pypi
|
|
42
|
+
permissions: { id-token: write }
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/download-artifact@v4
|
|
45
|
+
with: { name: dist, path: dist/ }
|
|
46
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
marqov-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
.venv-gate/
|
|
3
|
+
# Any virtualenv (e.g. .verify-venv) — excluded so the hatchling sdist build does
|
|
4
|
+
# not try to bundle venv symlinks.
|
|
5
|
+
*-venv/
|
|
6
|
+
.*-venv/
|
|
7
|
+
# Claude Code local tooling / worktrees — never ship in the sdist.
|
|
8
|
+
.claude/
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.pyc
|
|
11
|
+
*.pyo
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.mypy_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
dist/
|
|
16
|
+
build/
|
|
17
|
+
*.egg-info/
|
|
18
|
+
.env
|
|
19
|
+
.env.local
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the `marqov` SDK are documented here. This project follows
|
|
4
|
+
[Semantic Versioning](https://semver.org/). While on `0.x`, the public API may
|
|
5
|
+
still change between minor versions; `1.0.0` is reserved for the first API-stable
|
|
6
|
+
release.
|
|
7
|
+
|
|
8
|
+
## [0.2.0] — 2026-06-29
|
|
9
|
+
|
|
10
|
+
First public release on PyPI.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Public release of the `marqov` SDK: build quantum circuits and run them across
|
|
14
|
+
multiple hardware backends (AWS Braket, IBM Quantum, Azure Quantum, IonQ,
|
|
15
|
+
Rigetti, Quantinuum, and local simulation) behind one API.
|
|
16
|
+
- Circuit interop helpers (import/export with Qiskit, Cirq, PennyLane, pytket,
|
|
17
|
+
and pyQuil) and workflow/task decorators for composing multi-step programs.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- The circuit IR / transpilation dependency is now the published
|
|
21
|
+
[`marqov-quantumflow`](https://pypi.org/project/marqov-quantumflow/) package
|
|
22
|
+
instead of a git URL, which is what makes `pip install marqov` possible.
|
|
23
|
+
- The package version is single-sourced from `marqov/__init__.py` (`__version__`)
|
|
24
|
+
via hatchling, so the distribution metadata, `marqov.__version__`, and
|
|
25
|
+
`marqov --version` always agree.
|
|
26
|
+
|
|
27
|
+
### Known limitations
|
|
28
|
+
- `@task`/`@workflow` serialize the decorated function with `cloudpickle` at
|
|
29
|
+
decoration time. When the function is a local/closure (not module-level) and a
|
|
30
|
+
large set of heavy backends is imported in the same process, this can overflow
|
|
31
|
+
into a `RecursionError`. Module-level task functions are unaffected. A fix that
|
|
32
|
+
defers/removes the function serialization is planned.
|
|
33
|
+
|
|
34
|
+
[0.2.0]: https://pypi.org/project/marqov/0.2.0/
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment:
|
|
18
|
+
|
|
19
|
+
- Demonstrating empathy and kindness toward other people
|
|
20
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
21
|
+
- Giving and gracefully accepting constructive feedback
|
|
22
|
+
- Accepting responsibility and apologizing to those affected by our mistakes
|
|
23
|
+
- Focusing on what is best not just for us as individuals, but for the overall community
|
|
24
|
+
|
|
25
|
+
Examples of unacceptable behavior:
|
|
26
|
+
|
|
27
|
+
- The use of sexualized language or imagery, and sexual attention or advances of any kind
|
|
28
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
29
|
+
- Public or private harassment
|
|
30
|
+
- Publishing others' private information without their explicit permission
|
|
31
|
+
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
32
|
+
|
|
33
|
+
## Enforcement Responsibilities
|
|
34
|
+
|
|
35
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
36
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
37
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
38
|
+
or harmful.
|
|
39
|
+
|
|
40
|
+
## Scope
|
|
41
|
+
|
|
42
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
43
|
+
an individual is officially representing the community in public spaces.
|
|
44
|
+
|
|
45
|
+
## Enforcement
|
|
46
|
+
|
|
47
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
48
|
+
reported to the community leaders at ops@marqov.ai. All complaints will be
|
|
49
|
+
reviewed and investigated promptly and fairly.
|
|
50
|
+
|
|
51
|
+
## Attribution
|
|
52
|
+
|
|
53
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
|
54
|
+
version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Contributing to Marqov SDK
|
|
2
|
+
|
|
3
|
+
Thank you for contributing. This guide covers everything you need to add a new
|
|
4
|
+
executor, circuit converter, or other contribution to the Marqov SDK.
|
|
5
|
+
|
|
6
|
+
## Development Setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/marqov-dev/marqov-sdk
|
|
10
|
+
cd marqov-sdk
|
|
11
|
+
python3.12 -m venv .venv
|
|
12
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
13
|
+
pip install -e ".[all,dev]"
|
|
14
|
+
pytest tests/ -v
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## §1 — Canonical Gate Set
|
|
18
|
+
|
|
19
|
+
All executor and circuit converter contributions must support the following
|
|
20
|
+
gates and raise `NotImplementedError` for anything outside this set. This list
|
|
21
|
+
is derived from `marqov/circuits.py` (`_QISKIT_GATE_MAP`) and represents what
|
|
22
|
+
the SDK can round-trip today.
|
|
23
|
+
|
|
24
|
+
| Category | Gates |
|
|
25
|
+
|---------------|------------------------------|
|
|
26
|
+
| Single-qubit | H, X, Y, Z, S, T |
|
|
27
|
+
| Rotation | Rx(θ), Ry(θ), Rz(θ) |
|
|
28
|
+
| Two-qubit | CNOT/CX, CZ, SWAP |
|
|
29
|
+
|
|
30
|
+
## §2 — Executor Interface
|
|
31
|
+
|
|
32
|
+
All executors inherit from `BaseExecutor` in `marqov/executors/base.py`.
|
|
33
|
+
|
|
34
|
+
### Required methods
|
|
35
|
+
|
|
36
|
+
**`async execute(circuit: Circuit, shots: int = 1000, **kwargs) -> ExecutionResult`**
|
|
37
|
+
|
|
38
|
+
Submit the circuit to the backend and return results. `ExecutionResult` fields
|
|
39
|
+
you must populate:
|
|
40
|
+
|
|
41
|
+
| Field | Type | Required | Description |
|
|
42
|
+
|-------|------|----------|-------------|
|
|
43
|
+
| `counts` | `dict[str, int]` | Yes | Measurement outcomes e.g. `{"00": 512, "11": 488}` |
|
|
44
|
+
| `backend` | `str` | Yes | Name or identifier of the backend |
|
|
45
|
+
| `execution_time_ms` | `float` | Yes | Wall time in milliseconds |
|
|
46
|
+
| `shots` | `int` | Yes | Number of shots executed |
|
|
47
|
+
| `raw_result` | `Any` | No | Provider-specific result object, for debugging |
|
|
48
|
+
| `metadata` | `dict` | No | Additional provider metadata |
|
|
49
|
+
|
|
50
|
+
**`async cancel(job_id: str) -> bool`**
|
|
51
|
+
|
|
52
|
+
Cancel a running job. Return `True` if successful, `False` otherwise. If the
|
|
53
|
+
provider does not support cancellation, the default `BaseExecutor` implementation
|
|
54
|
+
returns `False` — do not override it unless the provider supports cancellation.
|
|
55
|
+
|
|
56
|
+
`job_id` is the provider's job or task identifier. Callers obtain it from
|
|
57
|
+
`ExecutionResult.metadata` (e.g. `result.metadata["task_arn"]` for Braket).
|
|
58
|
+
Executors that support cancellation should store the active job ID as instance
|
|
59
|
+
state (e.g. `self._current_job_id`) and include it in `ExecutionResult.metadata`
|
|
60
|
+
under a documented key. Job polling (queued → running → completed) happens
|
|
61
|
+
internally inside `execute()` and is not related to this method.
|
|
62
|
+
|
|
63
|
+
**`async get_status() -> DeviceStatus`**
|
|
64
|
+
|
|
65
|
+
Return the QPU's **operational availability** — whether the device is currently
|
|
66
|
+
accepting new job submissions. This is **device-level status**, not job-level
|
|
67
|
+
status. Job polling (queued → running → completed) is handled internally inside
|
|
68
|
+
`execute()` and is not exposed via `get_status()`.
|
|
69
|
+
|
|
70
|
+
`DeviceStatus` fields:
|
|
71
|
+
|
|
72
|
+
| Field | Type | Values |
|
|
73
|
+
|-------|------|--------|
|
|
74
|
+
| `status` | `str` | `"online"`, `"offline"`, `"maintenance"` |
|
|
75
|
+
| `queue_depth` | `int \| None` | Number of queued tasks, or `None` if unknown |
|
|
76
|
+
| `queue_time_seconds` | `int \| None` | Estimated queue wait, or `None` if unknown |
|
|
77
|
+
|
|
78
|
+
The default `BaseExecutor.get_status()` returns `DeviceStatus.always_online()`.
|
|
79
|
+
Cloud backends should override this to query the provider's device status endpoint.
|
|
80
|
+
|
|
81
|
+
## §3 — Adding a New Executor
|
|
82
|
+
|
|
83
|
+
1. Create `marqov/executors/<name>.py` with a config dataclass and executor class:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from dataclasses import dataclass
|
|
87
|
+
from typing import Any
|
|
88
|
+
from marqov.executors.base import BaseExecutor, DeviceStatus, ExecutionResult
|
|
89
|
+
from marqov.circuits import Circuit
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class MyProviderExecutorConfig:
|
|
93
|
+
api_key: str
|
|
94
|
+
device_name: str
|
|
95
|
+
shots: int = 1000
|
|
96
|
+
|
|
97
|
+
class MyProviderExecutor(BaseExecutor):
|
|
98
|
+
def __init__(self, config: MyProviderExecutorConfig) -> None:
|
|
99
|
+
self.config = config
|
|
100
|
+
|
|
101
|
+
async def execute(self, circuit: Circuit, shots: int = 1000, **kwargs: Any) -> ExecutionResult:
|
|
102
|
+
# convert circuit, submit, poll, return ExecutionResult
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
async def get_status(self) -> DeviceStatus:
|
|
106
|
+
# query provider device status endpoint
|
|
107
|
+
...
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
2. Register in `marqov/executors/factory.py`:
|
|
111
|
+
- Add import at top: `from marqov.executors.<name> import MyProviderExecutor, MyProviderExecutorConfig`
|
|
112
|
+
- Add branch in `create_executor()`:
|
|
113
|
+
```python
|
|
114
|
+
if provider == "My Provider":
|
|
115
|
+
return cls._create_myprovider_executor(backend_slug, backend_config)
|
|
116
|
+
```
|
|
117
|
+
- Add `_create_myprovider_executor()` classmethod following the pattern of `_create_ibm_executor()`
|
|
118
|
+
- Add `"My Provider"` to the list in `get_supported_providers()`
|
|
119
|
+
|
|
120
|
+
3. Add the provider package to `pyproject.toml` as an optional dependency:
|
|
121
|
+
```toml
|
|
122
|
+
[project.optional-dependencies]
|
|
123
|
+
myprovider = ["my-provider-sdk>=1.0.0"]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
4. Export from `marqov/executors/__init__.py`.
|
|
127
|
+
|
|
128
|
+
## §4 — Local QVM Setup (Rigetti executor development)
|
|
129
|
+
|
|
130
|
+
The Rigetti QCS executor tests run against a local QVM instance. QVM requires
|
|
131
|
+
`quilc` running alongside it.
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
docker pull rigetti/quilc
|
|
135
|
+
docker pull rigetti/qvm
|
|
136
|
+
docker run -d -p 5555:5555 rigetti/quilc -server
|
|
137
|
+
docker run -d -p 5000:5000 rigetti/qvm -server
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Verify:
|
|
141
|
+
```bash
|
|
142
|
+
python -c "from pyquil import get_qc; qc = get_qc('2q-qvm'); print(qc)"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Expected output: `<QVM 2q-qvm>` or similar. If you see a connection error,
|
|
146
|
+
check both containers are running with `docker ps`.
|
|
147
|
+
|
|
148
|
+
## §5 — Running Benchmarks
|
|
149
|
+
|
|
150
|
+
`benchmarks/suite.py` runs a fixed set of reference circuits — Bell, 3-qubit
|
|
151
|
+
GHZ, and a deterministic depth-5 random circuit — against any configured
|
|
152
|
+
executor and prints a comparison table. It works out of the box with
|
|
153
|
+
`LocalExecutor`, so no credentials are required:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
python benchmarks/suite.py --executor local --shots 1000 --seed 1234
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Output format — one row per (backend × circuit) combination:
|
|
160
|
+
|
|
161
|
+
| backend | circuit | shots | exec_time_ms | top_3_outcomes |
|
|
162
|
+
|---------|-----------|-------|--------------|--------------------------------------|
|
|
163
|
+
| local | bell | 1000 | 0.4 | {"11": 502, "00": 498} |
|
|
164
|
+
| local | ghz | 1000 | 0.4 | {"111": 524, "000": 476} |
|
|
165
|
+
| local | random_d5 | 1000 | 0.4 | {"010": 262, "100": 254, "110": 243} |
|
|
166
|
+
|
|
167
|
+
Columns:
|
|
168
|
+
- `backend`: executor name
|
|
169
|
+
- `circuit`: circuit name (`bell`, `ghz`, `random_d5`)
|
|
170
|
+
- `shots`: number of shots
|
|
171
|
+
- `exec_time_ms`: wall time in milliseconds (varies per run and machine)
|
|
172
|
+
- `top_3_outcomes`: counts of the 3 most frequent measurement outcomes, ordered
|
|
173
|
+
by count descending
|
|
174
|
+
|
|
175
|
+
The measurement outcomes above are reproducible for a fixed `--seed` (it seeds
|
|
176
|
+
both the random circuit and the local sampler); `exec_time_ms` is wall time and
|
|
177
|
+
will differ on your machine.
|
|
178
|
+
|
|
179
|
+
**Scope.** The suite compares execution time and outcome distribution only.
|
|
180
|
+
Shot-fidelity and queue-overhead metrics are out of scope for this harness;
|
|
181
|
+
device-level queue status is available separately via `BaseExecutor.get_status()`.
|
|
182
|
+
|
|
183
|
+
**Error handling.** If a backend errors on any circuit, the suite skips that
|
|
184
|
+
*entire* backend (it emits no partial rows for it), logs the backend and the
|
|
185
|
+
failing circuit to stderr, and continues with the next backend — it never
|
|
186
|
+
aborts. If every backend fails the command exits non-zero, so CI can flag a
|
|
187
|
+
fully broken run.
|
|
188
|
+
|
|
189
|
+
**Benchmarking other backends.** The CLI only constructs the zero-credential
|
|
190
|
+
`local` executor, but `run_suite()` is executor-agnostic — pass a mapping of
|
|
191
|
+
name → `BaseExecutor` to benchmark cloud backends programmatically:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
import asyncio
|
|
195
|
+
from benchmarks.suite import run_suite, format_table
|
|
196
|
+
from marqov.executors import ExecutorFactory, LocalExecutor
|
|
197
|
+
|
|
198
|
+
executors = {
|
|
199
|
+
"local": LocalExecutor(),
|
|
200
|
+
"sv1": ExecutorFactory.create_executor("sv1", braket_config),
|
|
201
|
+
}
|
|
202
|
+
rows = asyncio.run(run_suite(executors, shots=1000))
|
|
203
|
+
print(format_table(rows))
|
|
204
|
+
```
|
marqov-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship made available under
|
|
36
|
+
the License, as indicated by a copyright notice that is included in
|
|
37
|
+
or attached to the work (an example is provided in the Appendix below).
|
|
38
|
+
|
|
39
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
40
|
+
form, that is based on (or derived from) the Work and for which the
|
|
41
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
42
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
43
|
+
of this License, Derivative Works shall not include works that remain
|
|
44
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
45
|
+
the Work and Derivative Works thereof.
|
|
46
|
+
|
|
47
|
+
"Contribution" shall mean, as submitted to the Licensor for inclusion
|
|
48
|
+
in the Work by the copyright owner or by an individual or Legal Entity
|
|
49
|
+
authorized to submit on behalf of the copyright owner. For the purposes
|
|
50
|
+
of this definition, "submitted" means any form of electronic, verbal,
|
|
51
|
+
or written communication sent to the Licensor or its representatives,
|
|
52
|
+
including but not limited to communication on electronic mailing lists,
|
|
53
|
+
source code control systems, and issue tracking systems that are managed
|
|
54
|
+
by, or on behalf of, the Licensor for the purpose of discussing and
|
|
55
|
+
improving the Work, but excluding communication that is conspicuously
|
|
56
|
+
marked or designated in writing by the copyright owner as "Not a
|
|
57
|
+
Contribution."
|
|
58
|
+
|
|
59
|
+
"Contributor" shall mean Licensor and any Legal Entity on behalf of
|
|
60
|
+
whom a Contribution has been received by the Licensor and included
|
|
61
|
+
within the Work.
|
|
62
|
+
|
|
63
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
64
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
65
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
66
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
67
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
68
|
+
Work and such Derivative Works in Source or Object form.
|
|
69
|
+
|
|
70
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
71
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
72
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
73
|
+
(except as stated in this section) patent license to make, have made,
|
|
74
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
75
|
+
where such license applies only to those patent claims licensable
|
|
76
|
+
by such Contributor that are necessarily infringed by their
|
|
77
|
+
Contribution(s) alone or by the combination of their Contribution(s)
|
|
78
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
79
|
+
institute patent litigation against any entity (including a cross-claim
|
|
80
|
+
or counterclaim in a lawsuit) alleging that the Work or any
|
|
81
|
+
Contributor's Contribution(s) constitutes direct or contributory
|
|
82
|
+
patent infringement, then any patent rights granted to You under
|
|
83
|
+
this License for that Work shall terminate as of the date such
|
|
84
|
+
litigation is filed.
|
|
85
|
+
|
|
86
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
87
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
88
|
+
modifications, and in Source or Object form, provided that You
|
|
89
|
+
meet the following conditions:
|
|
90
|
+
|
|
91
|
+
(a) You must give any other recipients of the Work or Derivative
|
|
92
|
+
Works a copy of this License; and
|
|
93
|
+
|
|
94
|
+
(b) You must cause any modified files to carry prominent notices
|
|
95
|
+
stating that You changed the files; and
|
|
96
|
+
|
|
97
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
98
|
+
that You distribute, all copyright, patent, trademark, and
|
|
99
|
+
attribution notices from the Source form of the Work,
|
|
100
|
+
excluding those notices that do not pertain to any part of
|
|
101
|
+
the Derivative Works; and
|
|
102
|
+
|
|
103
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
104
|
+
distribution, You must include a readable copy of the
|
|
105
|
+
attribution notices contained within such NOTICE file, in
|
|
106
|
+
at least one of the following places: within a NOTICE text
|
|
107
|
+
file distributed as part of the Derivative Works; within
|
|
108
|
+
the Source form or documentation, if provided along with the
|
|
109
|
+
Derivative Works; or, within a display generated by the
|
|
110
|
+
Derivative Works, if and wherever such third-party notices
|
|
111
|
+
normally appear. The contents of the NOTICE file are for
|
|
112
|
+
informational purposes only and do not modify the License.
|
|
113
|
+
You may add Your own attribution notices within Derivative
|
|
114
|
+
Works that You distribute, alongside or in addition to the
|
|
115
|
+
NOTICE text from the Work, provided that such additional
|
|
116
|
+
attribution notices cannot be construed as modifying the License.
|
|
117
|
+
|
|
118
|
+
You may add Your own license statement for Your modifications and
|
|
119
|
+
may provide additional grant of rights to use, copy, modify, merge,
|
|
120
|
+
publish, distribute, sublicense, and/or sell copies of the
|
|
121
|
+
Contribution, either on an unrestrictive basis or under the terms of
|
|
122
|
+
this License.
|
|
123
|
+
|
|
124
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
125
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
126
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
127
|
+
this License, without any additional terms or conditions.
|
|
128
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
129
|
+
the terms of any separate license agreement you may have executed
|
|
130
|
+
with Licensor regarding such Contributions.
|
|
131
|
+
|
|
132
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
133
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
134
|
+
except as required for reasonable and customary use in describing the
|
|
135
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
136
|
+
|
|
137
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
138
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
139
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
140
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
141
|
+
implied, including, without limitation, any warranties or conditions
|
|
142
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
143
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
144
|
+
appropriateness of using or reproducing the Work and assume any
|
|
145
|
+
risks associated with Your exercise of permissions under this License.
|
|
146
|
+
|
|
147
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
148
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
149
|
+
unless required by applicable law (such as deliberate and grossly
|
|
150
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
151
|
+
liable to You for damages, including any direct, indirect, special,
|
|
152
|
+
incidental, or exemplary damages of any character arising as a
|
|
153
|
+
result of this License or out of the use or inability to use the
|
|
154
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
155
|
+
work stoppage, computer failure or malfunction, or all other
|
|
156
|
+
commercial damages or losses), even if such Contributor has been
|
|
157
|
+
advised of the possibility of such damages.
|
|
158
|
+
|
|
159
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
160
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
161
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
162
|
+
or other liability obligations and/or rights consistent with this
|
|
163
|
+
License. However, in accepting such obligations, You may offer such
|
|
164
|
+
obligations only on Your own behalf and on Your sole responsibility,
|
|
165
|
+
not on behalf of any other Contributor, and only if You agree to
|
|
166
|
+
indemnify, defend, and hold each Contributor harmless for any
|
|
167
|
+
liability incurred by, or claims asserted against, such Contributor
|
|
168
|
+
by reason of your accepting any such warranty or additional liability.
|
|
169
|
+
|
|
170
|
+
END OF TERMS AND CONDITIONS
|
|
171
|
+
|
|
172
|
+
Copyright 2026 Marqov
|
|
173
|
+
|
|
174
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
175
|
+
you may not use this file except in compliance with the License.
|
|
176
|
+
You may obtain a copy of the License at
|
|
177
|
+
|
|
178
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
179
|
+
|
|
180
|
+
Unless required by applicable law or agreed to in writing, software
|
|
181
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
182
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
183
|
+
See the License for the specific language governing permissions and
|
|
184
|
+
limitations under the License.
|