Metadata-Version: 2.4
Name: jiuzhang-sdk
Version: 0.1.4
Summary: Python SDK for JiuZhang cloud GBS tasks and local GBS / handwritten digit workflows
Author: JiuZhang Quantum SDK Team
License: Proprietary
Keywords: gbs,jiuzhang,mnist,photonic,quantum,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.12
Requires-Dist: httpx<0.29,>=0.27
Requires-Dist: matplotlib>=3.8
Requires-Dist: networkx>=3.0
Requires-Dist: numpy<2,>=1.26
Requires-Dist: plotly>=5
Requires-Dist: quantum-blackbird==0.5.0
Requires-Dist: quantum-xir==0.2.2
Requires-Dist: scikit-learn<1.8,>=1.4
Requires-Dist: scipy<1.14,>=1.10
Requires-Dist: setuptools<81,>=70
Requires-Dist: strawberryfields==0.23.0
Requires-Dist: thewalrus==0.21.0
Provides-Extra: dev
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest-mock>=3; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: jupyter
Requires-Dist: ipython>=8; extra == 'jupyter'
Description-Content-Type: text/markdown

# jiuzhang-sdk ✨

Python SDK for the JiuZhang photonic quantum cloud platform, with cloud GBS task submission, result retrieval, local GBS math, sampling, IR serialization, and local application helpers.

The SDK provides three core capability groups:

| Capability | Uses the JiuZhang cloud platform | Result source | Typical use |
| --- | --- | --- | --- |
| Cloud GBS tasks | Yes | Executed by the JiuZhang cloud platform | Submit GBS experiments, poll status, parse returned results |
| Local GBS sampling and math | No | Generated by the SDK local numerical backend | Teaching, prototyping, local validation, notebook demos |
| Local application workflows | No | Generated by SDK local application APIs | Handwritten digit recognition, dense subgraph, graph isomorphism, molecular docking, vibronic spectra |

Cloud GBS tasks are executed by the JiuZhang cloud platform. Python scripts and Jupyter notebooks submit requests, poll task status, and read results.

Local GBS sampling runs entirely on the local machine and does not call the cloud API. Results are generated by the SDK local numerical backend from the provided matrix and sampling parameters.

Local application workflows also run without the cloud API. Results are generated locally from bundled datasets, matrix parameters, and algorithm parameters.

## 📦 Installation

Install the SDK:

```bash
pip install jiuzhang-sdk
```

The default installation includes cloud task submission, local GBS math and sampling, local program serialization, and local application workflow dependencies.

## 🔐 Cloud Credentials

Before submitting a cloud task, prepare these values from the JiuZhang cloud workspace:

| Value | Description |
| --- | --- |
| `api_key` | Authentication credential used in the `X-Jiuzhang-API-Key` request header |
| `project_id` | Cloud project identifier used to associate tasks with a project |
| `quantum_computer_id` | Cloud device code, for example `PH_QC_04` |

Recommended environment variables:

```bash
export JIUZHANG_API_KEY="your-api-key"
export JIUZHANG_PROJECT_ID="your-project-id"
export JIUZHANG_QUANTUM_COMPUTER_ID="PH_QC_04"
export JIUZHANG_BASE_URL="https://cloud.jiuzhangqt.com/api/v1"
```

## ☁️ Cloud GBS Workflow

```python
from jiuzhang import CloudClient, GBSParams, parse_gbs_result

client = CloudClient(
    base_url="https://cloud.jiuzhangqt.com/api/v1",
    api_key="your-api-key",
)

params = GBSParams(
    project_id="EXP-demo-project",
    quantum_computer_id="PH_QC_04",
    mt=500,
    pump_energy_nj=4.6,
    squeezing_param=0.35,
    task_name="GBS experiment",
)

estimate = client.estimate_runtime(
    quantum_computer_id=params.quantum_computer_id,
    mt_value=params.mt,
    pump_energy_nj=params.pump_energy_nj,
)

task = client.submit_task(
    project_id=params.project_id,
    task_name=params.task_name,
    quantum_computer_id=params.quantum_computer_id,
    mt_value=params.mt,
    pump_energy_nj=params.pump_energy_nj,
    squeezing_param=params.squeezing_param,
)

task_id = task["data"]["task_id"]
raw_result = client.get_result(task_id)
result = parse_gbs_result(raw_result)

print(result.status_name)
print(result.sample_count)
print(result.experimental_distribution)

client.close()
```

One-call helper:

```python
result = client.run_gbs(params, poll_interval=2.0, timeout=300.0)
print(result.status_name)
```

## 🌐 Cloud API Methods

| Method | Purpose |
| --- | --- |
| `CloudClient(base_url, api_key, timeout=30.0)` | Create an authenticated cloud API client |
| `CloudClient.from_env()` | Create a client from `JIUZHANG_*` environment variables |
| `estimate_runtime(quantum_computer_id, mt_value, pump_energy_nj)` | Estimate runtime before submitting a task |
| `submit_task(project_id, task_name, quantum_computer_id, mt_value, pump_energy_nj, squeezing_param=None)` | Submit a cloud GBS task |
| `get_result(task_id)` | Query a task result |
| `run_experiment(...)` | Estimate, submit, poll, and return raw responses |
| `estimate_gbs(params)` | Estimate using `GBSParams` |
| `submit_gbs(params)` | Submit using `GBSParams` |
| `run_gbs(params)` | Run the full workflow and return `GBSResult` |
| `close()` | Close the underlying HTTP client |

## 🧾 Cloud Parameter Object

```python
from jiuzhang import GBSParams

params = GBSParams(
    project_id="EXP-demo-project",
    quantum_computer_id="PH_QC_04",
    mt=500,
    pump_energy_nj=4.6,
    squeezing_param=0.35,
    task_name="GBS experiment",
)
```

| Field | Description |
| --- | --- |
| `project_id` | Cloud project ID |
| `quantum_computer_id` | Cloud device code |
| `mt` | Pump pulse time-bin count, validated as `1..500` |
| `pump_energy_nj` | Pump energy in nJ |
| `squeezing_param` | Optional squeezing parameter |
| `shots` | Optional shot count field |
| `task_name` | Display name for the task |

Helper methods:

| Method | Purpose |
| --- | --- |
| `validate()` | Validate fields locally |
| `input_mode_count()` | Return `3 * mt` |
| `output_mode_count()` | Return `9 * (mt + 80)` |
| `to_cloud_payload()` | Build a cloud payload dictionary |
| `summary()` | Build a compact parameter summary |

## 📊 Parsed Result Object

`GBSResult` is returned by `run_gbs()` or by `parse_gbs_result(raw_result)`.

| Field or property | Description |
| --- | --- |
| `task_id` | Cloud task ID |
| `status_name` | Normalized task status |
| `sample_count` | Returned sample count |
| `result_map_points` | Probability distribution curves |
| `experimental_distribution` | Experimental distribution points |
| `ground_truth_distribution` | Reference distribution points |
| `download_url` | Raw result download URL |
| `raw` | Original response dictionary |

## 🧮 Local GBS Sampling

Local GBS sampling does not call the cloud API. Results are generated on the local machine by the SDK from the adjacency matrix and sampling parameters.

```python
from jiuzhang.local.gbs import (
    random_adjacency_matrix,
    sample_gbs,
    samples_to_distribution,
)

graph = random_adjacency_matrix(8, scale=0.16, seed=7)
samples = sample_gbs(
    graph,
    shots=24,
    mean_photon_count=1.0,
    detector="pnr",
    cutoff=4,
    max_photons=12,
    seed=123,
)
distribution = samples_to_distribution(samples)
print(distribution)
```

| Function | Purpose |
| --- | --- |
| `random_adjacency_matrix(modes, scale=0.2, seed=None)` | Generate a symmetric adjacency matrix |
| `sample_gbs(adjacency, shots=10, mean_photon_count=1.0, detector="pnr", cutoff=5, max_photons=30, seed=None, parallel=False)` | Generate local GBS samples |
| `samples_to_distribution(samples)` | Convert samples into a normalized pattern distribution |

## 🧩 Local Math and IR Helpers

```python
from jiuzhang.local.gbs import (
    GBSProgram,
    dumps_ir,
    hafnian,
    loop_hafnian,
    threshold_probability,
    to_blackbird,
    to_xir,
    torontonian,
)
```

| Function | Purpose |
| --- | --- |
| `hafnian(matrix, loop=False, approx=False, num_samples=1000, method="glynn")` | Compute the Hafnian of a square matrix |
| `loop_hafnian(matrix, diagonal=None, reps=None, glynn=True)` | Compute the loop Hafnian |
| `torontonian(matrix, recursive=True)` | Compute the Torontonian |
| `threshold_probability(mean, covariance, pattern, hbar=2.0, atol=1e-10, rtol=1e-10)` | Compute a threshold detection probability |
| `GBSProgram(modes, operations=(), name="gbs_program")` | Build a local GBS program |
| `dumps_ir(program, format="json")` | Serialize a program to JSON or text IR |
| `loads_ir(payload)` | Parse JSON local IR |
| `to_blackbird(program)` | Serialize to local program text |
| `to_xir(program)` | Serialize to XIR text |

## 🧠 Local Handwritten Digit Recognition

```python
from jiuzhang.local.mnist import run_mnist_recognition

result = run_mnist_recognition(
    train_size=1200,
    test_size=300,
    source="digits",
    n_components=32,
    feature_count=256,
    combine=True,
    random_state=7,
)

print(result.train)
print(result.accuracy)
print(result.confusion_matrix)
```

Manual training:

```python
from jiuzhang.local.mnist import GBSMNISTClassifier, load_mnist_data

dataset = load_mnist_data(train_size=1200, test_size=300, source="digits")
classifier = GBSMNISTClassifier(n_components=32, feature_count=256)

classifier.fit(dataset.train_data, dataset.train_labels, combine=True)
predictions = classifier.predict(dataset.test_data)
evaluation = classifier.evaluate(dataset.test_data, dataset.test_labels, reuse=True)
```

| Parameter | Description |
| --- | --- |
| `source` | Dataset source. `digits` is the bundled offline dataset, and `openml` downloads MNIST 784 |
| `train_size` | Number of training samples |
| `test_size` | Number of test samples |
| `n_components` | PCA components retained before feature extraction |
| `feature_count` | Number of local GBS-style features |
| `combine` | `True` for GBS-RVFL, `False` for GBS-ELM |
| `regularization` | Ridge regularization strength for the output layer |
| `random_state` | Seed for reproducible experiments |

## 🧪 Local Application Workflows

The graph and molecular demos are available through `jiuzhang.local.applications`, so notebooks can call SDK-level methods only.

```python
from jiuzhang.local.applications import (
    greedy_dense_subgraph,
    load_formic_acid,
    load_mutag_graphs,
    load_planted_dense_graph,
    load_tace_as_graph,
)

adjacency = load_planted_dense_graph()
dense_result = greedy_dense_subgraph(adjacency, size=8)

mutag_graphs = load_mutag_graphs()
docking_graph = load_tace_as_graph()
molecule = load_formic_acid()
```

| Function | Purpose |
| --- | --- |
| `load_planted_dense_graph()` | Load the dense-subgraph demo graph |
| `greedy_dense_subgraph(...)`, `random_dense_search(...)`, `simulated_annealing_dense_search(...)` | Search fixed-size dense subgraphs |
| `sample_database_search(...)` | Search dense subgraphs from a local sample database |
| `load_mutag_graphs()`, `load_graph_samples(...)` | Load graph-isomorphism demo graphs and sample data |
| `event_feature_vector_from_samples(...)`, `train_linear_graph_classifier(...)` | Build event features and train a linear graph classifier |
| `load_tace_as_graph()`, `load_phat_graph()` | Load molecular-docking graph datasets |
| `postselect_subgraphs(...)`, `clique_shrink(...)`, `clique_search(...)` | Extract clique candidates from sampled subgraphs |
| `load_formic_acid()`, `vibronic_parameters(...)`, `sample_vibronic_spectrum(...)` | Load molecular data, build vibronic parameters, and generate spectrum samples |

## 📄 License

Proprietary. Copyright 2026 JiuZhang Quantum. All rights reserved.
