Metadata-Version: 2.4
Name: quapp-pennylane
Version: 0.0.5.dev6
Summary: Quapp pennylane library supporting Quapp Platform for Quantum Computing
Author-email: "CITYNOW Co. Ltd. " <corp@citynow.vn>
License: The MIT License (MIT)
        Copyright © CITYNOW Co. Ltd. All rights reserved.
        
        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Project-URL: Homepage, https://citynow.asia/
Keywords: quapp,quapp-pennylane,pennylane,quantum
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: quapp-common>=0.0.14.dev1
Requires-Dist: autoray==0.6.11
Requires-Dist: pennylane==0.37.0
Requires-Dist: matplotlib
Requires-Dist: PennyLane-Rigetti==0.36.0
Requires-Dist: PennyLane_Lightning==0.37.0
Provides-Extra: dev
Requires-Dist: black; extra == "dev"
Requires-Dist: bumpver; extra == "dev"
Requires-Dist: isort; extra == "dev"
Requires-Dist: pip-tools; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# quapp-pennylane

Quapp PennyLane library supporting the Quapp Platform for Quantum Computing with
providers, devices, circuit export, invocation, and job fetching utilities.

## Overview

`quapp-pennylane` is a Python library that integrates the Quapp Platform with
PennyLane-based quantum backends and simulators. It provides common abstractions
for providers and devices, helpers for circuit construction and export, robust job
submission and result fetching flows, and consistent job-scoped logging across
all components.

## Features

- **Provider & device factories** — PennyLane-compatible factories for local
  simulators (e.g., `default.qubit`) and vendor-backed hardware (Rigetti QVM,
  AWS Braket, IBM Quantum).
- **Circuit export** — `PennylaneCircuitExportTask` with a `_PennylaneDrawableCircuit`
  adapter that satisfies the `CircuitExportTask.draw()` contract using `qml.draw_mpl`.
- **Job execution** — `QAppPennylaneDevice` drives the full execution pipeline:
  tape construction, device selection, QNode creation, probability histogram
  generation, and timing metrics.
- **Rigetti QVM support** — dynamic device-name derivation for N-qubit QVM
  topologies (`Nq-qvm`, `Nq-pyqvm`) alongside fixed 9-qubit variants.
- **Structured logging** — job-scoped, instance-bound loggers emit structured
  key=value fields at every major step for traceability and debugging.
- **Compatibility shims** — `quapp_pennylane/__init__.py` patches API breaks
  between `pennylane-rigetti==0.36.0` and PennyLane 0.37–0.42+ at import time
  (see [Compatibility](#compatibility) below).

## Installation

```bash
pip install quapp-pennylane
```

## Requirements

| Dependency | Version |
|---|---|
| Python | ≥ 3.10 |
| quapp-common | 0.0.11.dev7 |
| pennylane | 0.37.0 |
| PennyLane-Rigetti | 0.36.0 |
| PennyLane-Lightning | 0.37.0 |
| pydantic | ≥ 1.7.2, < 2.0.0 |
| autoray | 0.6.11 |

## Project Structure

```
quapp_pennylane/
├── __init__.py                          # Compatibility shims (loaded at import)
├── async_tasks/
│   └── pennylane_circuit_export_task.py # PennylaneCircuitExportTask + adapter
├── component/
│   └── backend/
│       └── pennylane_invocation.py
├── factory/
│   ├── pennylane_device_factory.py
│   ├── pennylane_handler_factory.py
│   └── pennylane_provider_factory.py
├── handler/
│   └── invocation_handler.py
└── model/
    ├── device/
    │   ├── qapp_pennylane_device.py     # Core execution device
    │   ├── aws_braket_device.py
    │   └── ibm_quantum_device.py
    └── provider/
        ├── qapp_pennylane_provider.py
        ├── aws_braket_provider.py
        ├── ibm_cloud_provider.py
        └── ibm_quantum_provider.py
```

## Compatibility

`quapp_pennylane/__init__.py` applies the following shims at import time so that
`pennylane-rigetti==0.36.0` works against PennyLane 0.37–0.42+:

| Symbol | Change | Shim |
|---|---|---|
| `measurements.Expectation` | Renamed to `ExpectationMP` in PennyLane 0.37+ | Alias `Expectation → ExpectationMP` |
| `operation.Tensor` | Removed in PennyLane 0.40+; replaced by `ops.Prod` | Alias `Tensor → Prod` for isinstance checks |
| `pennylane.QubitDevice` | Moved to `pennylane.devices` in PennyLane ~0.40+ | Re-export at top-level namespace |
| `pydantic.BaseModel.__config__` | Removed in Pydantic v2; `qcs-api-client<0.22.0` reads `self.__config__.env_prefix` | Inject a stub `__config__` with `env_prefix=''` onto `BaseModel` |

`pydantic` is pinned to `>=1.7.2,<2.0.0` in `pyproject.toml` to make the v1
requirement of `qcs-api-client<0.22.0` explicit and prevent pip from resolving v2.

## Recent Changes

### 0.0.5.dev6

- **feat(error)**: Thêm `quapp_pennylane/error_rules.py` — 9 rule phân loại lỗi
  đặc thù PennyLane, đăng ký vào classifier của `quapp-common` khi package được
  import. Nhờ đó lỗi PennyLane có `category` / `code` / hướng xử lý cụ thể trong
  Job Log thay vì rơi về fallback chung `COMPILATION_FAILED`:
  - `PENNYLANE_DEVICE_NOT_AVAILABLE` — device không có trong `qml.plugin_devices`
    (thường do thiếu plugin hoặc viết sai tên device);
  - `PENNYLANE_INVALID_QUANTUM_FUNCTION`, `PENNYLANE_WIRE_ERROR`,
    `PENNYLANE_QUEUING_ERROR`, `PENNYLANE_MEASUREMENT_SHAPE_ERROR` — lỗi trong
    circuit do user viết (`USER_CODE`);
  - `PENNYLANE_OPERATION_UNSUPPORTED`, `PENNYLANE_TAPE_ERROR`,
    `PENNYLANE_DEVICE_ERROR` — giới hạn của SDK/device (`SDK_RUNTIME`);
  - `PENNYLANE_DEVICE_CONFIG_INVALID` — `DeviceError` về shots/wire, phân loại
    là `INVALID_INPUT` vì user sửa được.

  Rule match theo **tên class dạng string**, nên `quapp-common` không phải import
  PennyLane — bắt buộc, vì lib này kéo theo `pennylane-rigetti` và `pyquil` với
  ràng buộc version rất chặt.

- **fix(device)**: `QAppPennylaneDevice._get_shots()` dùng
  `getattr(job_result, 'shots')` trên một **dict** nên luôn trả `None` — shots
  không bao giờ tới được Job Log dù `_create_job()` đã tính đúng. Nay đọc bằng
  `.get()` cho dict.

- **fix(device)**: `_create_job()` đọc `parts[1]` cho device Rigetti QVM mà không
  kiểm tra độ dài, nên spec thiếu phần sau `/` gây `IndexError: list index out of
  range`. Nay raise `ValueError` nói rõ spec phải có dạng
  `rigetti.qvm/<device_type>`.

- **build**: `quapp-common` từ `==0.0.11.dev7` (exact pin, không có
  `register_rules`) thành `>=0.0.14.dev1`.

- **test**: Thêm `tests/test_error_rules.py` — 14 case, dựng exception thật từ
  PennyLane 0.37 để test vỡ khi PennyLane đổi tên exception.

> Ghi chú version: nhảy từ `0.0.4.dev6` (bản develop đang giữ sau
> `revert/pennylane-to-0.0.4.dev6`) lên `0.0.5.dev6` vì `0.0.5.dev1`–`dev5` đã
> publish, và template `js-pennylane` / `qs-pennylane` pin
> `quapp-pennylane>=0.0.5.dev2` nên không thể lùi về dòng `0.0.4`.

### 0.0.5.dev2

- **fix(export)**: Fix `_PennylaneDrawableCircuit.draw()` — `qml.draw_mpl` requires
  a `QNode`, not a bare callable; now captures the circuit into a `QuantumTape`,
  derives wires, creates a `default.qubit` device, and wraps in a `QNode` before
  rendering with `qml.draw_mpl`.
- **build**: Bump version to `0.0.5.dev2`.

### 0.0.5.dev1

- **feat(device)**: Add structured key=value log fields to `QAppPennylaneDevice`
  at every execution stage — initialization, tape diagnostics, device resolution,
  QNode setup, execution timing, histogram generation, and finalization.
- **feat(device)**: Default shots fallback — `shots=None` or `shots=0` in
  `CircuitRunningOption` falls back to 1024 with a warning instead of raising.
- **feat(export)**: Introduce `_PennylaneDrawableCircuit` adapter in
  `PennylaneCircuitExportTask` to wrap PennyLane circuits for the
  `CircuitExportTask.draw()` contract using `qml.draw_mpl`.
- **feat(export)**: Emit Python runtime information and duration timing in
  `_transpile_circuit`.
- **fix(compat)**: Patch `pydantic.BaseModel.__config__` at import time for
  Pydantic v2 environments — `qcs-api-client<0.22.0` accesses
  `self.__config__.env_prefix` (a Pydantic v1 inner Config class removed in v2).
- **fix(deps)**: Pin `pydantic>=1.7.2,<2.0.0` in `pyproject.toml` to prevent
  pip from resolving Pydantic v2.
- **fix(compat)**: Extend compatibility shims for `pennylane-rigetti==0.36.0`
  against PennyLane 0.37–0.42+: `measurements.Expectation`, `operation.Tensor`,
  and `pennylane.QubitDevice`.
- **build**: Bump version to `0.0.5.dev1`.

For detailed API references, refer to the in-code documentation or contact the
maintainers at [corp@citynow.vn](mailto:corp@citynow.vn).
