Cudaq Importing
NVIDIAOfficialCreated by CUDA-Q TeamDistributed by NVIDIA
- Skill
- Workflow
- Software development
- Apache-2.0
- Medium risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The CUDA-Q Importing skill provides a systematic approach to migrating quantum circuits from external frameworks into the CUDA-Q Python environment. It emphasizes preserving the original quantum algorithm, ensuring validation fidelity, and removing runtime dependencies on source frameworks. The skill includes specific guidance on gate translation, handling floating-point precision differences, and managing bit-ordering conventions to ensure the ported code behaves identically to the source implementation.
What it does
- Maps source framework gates to native CUDA-Q decorator-mode equivalents.
- Provides patterns for decoupling pure-Python helpers from source-framework dependencies.
- Defines execution patterns for sampling and mid-circuit measurement handling.
- Offers troubleshooting steps for common porting issues like bit-order mismatches and precision differences.
- Ensures algorithmic structure is preserved during the migration process.
- Guides the validation of ported kernels against deterministic source inputs.
When to use it
- When you need to migrate an existing quantum algorithm from Qiskit or similar frameworks to CUDA-Q.
- When you need to ensure a port maintains the exact behavior and fidelity of the original implementation.
- When you are refactoring code to remove dependencies on external quantum frameworks.
- When you encounter discrepancies in fidelity or count-key results between frameworks.
Advantages
- Maintains high-level algorithmic integrity throughout the porting process.
- Reduces runtime overhead by eliminating unnecessary source-framework dependencies.
- Provides clear gate-mapping references to simplify translation.
- Addresses common pitfalls like floating-point precision and bit-ordering conventions.
- Supports scalable kernel design using runtime-argument patterns.
Usage examples
- “Port this Qiskit circuit to a CUDA-Q kernel while preserving the oracle definition.”
- The agent will analyze the Qiskit circuit, map the gates to CUDA-Q equivalents, and provide a framework-free Python kernel that maintains the original oracle logic.
- “My ported CUDA-Q circuit shows different measurement results than the original Qiskit version. How do I fix this?”
- The agent will guide you through checking bit-ordering, floating-point precision settings, and measurement return formats to align the CUDA-Q output with the source.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/nvidia/cudaq-importing/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip cudaq-importing.zip -d .agents/skills
Documentation by CUDA-Q Team
CUDA-Q Importing
Purpose
Use this skill to port quantum circuits from another framework into CUDA-Q Python kernels. This includes Qiskit code and Qiskit-style circuit construction, as well as other framework-driven circuit builders. The goal is a framework-free CUDA-Q port that preserves the source quantum algorithm, matches source behavior at small test sizes, and documents any unavoidable CUDA-Q limitations.
For authoring new CUDA-Q kernels from scratch, and for CUDA-Q installation,
simulation targets, QPU access, and parallelization, use the cudaq-guide
skill (/cudaq-guide author for kernel authoring).
Prerequisites
Python 3.10+.
CUDA-Q installed in the target environment. Check the runtime with:
python -c "import cudaq; print(getattr(cudaq, '__version__', 'unknown'))".Access to the source implementation and a way to run or inspect its expected behavior.
To validate against the source framework (e.g. Qiskit/Aer), it must be installed in the validation environment only. The final CUDA-Q port itself must not require the source framework.
When using CUDA-Q documentation or repository MCP connectors, verify the connector is available before relying on it; otherwise use local docs or the source tree.
When debugging and the installed CUDA-Q version differs from the latest documentation, review relevant documentation or source changes before treating a behavior difference as a porting bug.
Workflow
Read the source circuit construction and identify the exact algorithm, qubit/register layout, measurement behavior, and any framework helpers.
Preserve the high-level quantum algorithm. Do not replace mid-circuit measurement, QPE structure, oracle definitions, or decomposition strategy without explicit user permission.
Select the CUDA-Q execution pattern:
Use
cudaq.samplefor final-measurement sampling.Use
cudaq.runwhen mid-circuit measurement values must be returned or used per shot.Use runtime-argument kernels instead of generated per-size kernels unless CUDA-Q requires a fixed-length return shape.
Translate gates and subcircuits. For detailed gate mappings, ordering rules, precision guidance, and helper-extraction patterns, read references/porting-reference.md.
Remove runtime source-framework dependencies from the CUDA-Q port. Extract pure helpers into framework-free modules.
Validate with small deterministic inputs before scaling. Compare raw count keys and distributions, not just aggregate fidelity.
Re-run any previously failing configurations after every fix.
Core Rules
Keep the source algorithm intact unless the user approves a change.
Do not introduce fixed qubit caps, fixed control arities, or source-framework imports unless they are genuinely unavoidable and documented.
Prefer native CUDA-Q gates (
r1.ctrl,x.ctrl,swap.ctrl, etc.) over transpiling through the source framework.Keep bit-order conversion at the port boundary: allocation order, measurement return list, or final count-key formatting.
Match floating-point precision when comparing CUDA-Q and source results if fidelity differences matter (CUDA-Q defaults to fp32, Qiskit to fp64).
Accept source flags that become no-ops in CUDA-Q when doing so preserves source-compatible behavior.
When to Read the Reference
Read references/porting-reference.md when you need any of the following:
Qiskit-to-CUDA-Q gate translation table.
Bit-ordering and count-key conventions.
CUDA-Q fp32 vs Qiskit fp64 precision implications.
Pure-Python helper extraction and import-blocker validation.
Recursive-constructor emitters or gate-recorder patterns.
Detailed port validation checklist and external CUDA-Q references.
Limitations
Guidance targets CUDA-Q 0.14/0.15 decorator-mode Python APIs. Re-check behavior against the installed CUDA-Q version for version-sensitive features.
Some CUDA-Q kernel-language constructs are constrained compared with normal Python; use the companion
cudaq-guideskill (/cudaq-guide author) for core CUDA-Q authoring constraints and shared kernel patterns.CUDA-Q and source frameworks differ in default precision and count-key display order. Apparent fidelity or bitstring mismatches may be convention differences.
Hardware-target behavior, available backends, and target options depend on the local CUDA-Q installation.
This skill does not guarantee equivalent performance; it focuses on correctness-preserving ports.
Troubleshooting
Use this format when diagnosing failures:
Error:
ModuleNotFoundError: qiskit(or another source framework) from a CUDA-Q path. Cause: The port still imports the source framework. Solution: Move pure helpers into a framework-free module and verify with the import-blocker pattern in the reference.Error: Fidelity looks plausible but raw keys are reversed. Cause: The source framework and CUDA-Q count-key ordering differ. Solution: Fix allocation, return-list order, or formatting at the port boundary. Do not alter the algorithm.
Error: Deep-circuit fidelity differs between frameworks. Cause: CUDA-Q and the source framework may be using different floating-point precision. Solution: Match precision before comparing, then rerun the smallest failing deterministic case.
Error: A multi-controlled operation works for small controls but fails or silently changes behavior at higher arity. Cause: The port used a fixed-arity dispatcher. Solution: Use CUDA-Q control-list patterns for arbitrary arity.
Error: MCP documentation or repository lookup fails. Cause: Connector unavailable, stale, or transiently failing. Solution: Verify the connector/resource list, retry transient failures once, then fall back to local docs/source or official CUDA-Q docs. Do not change the port based on unverified MCP results.
Error: CUDA-Q behavior conflicts with documentation while debugging. Cause: The installed CUDA-Q version may differ from the latest documentation. Solution: Check
cudaq.__version__, then review relevant documentation or source changes between the installed version and latest before changing the port.
References
Companion skill:
cudaq-guide(/cudaq-guide author) for CUDA-Q authoring patterns, kernel-language constraints, execution APIs, and debugging workflow.
Files
- ATTRIBUTION.mdAdded by AutoGineer908 B
- BENCHMARK.md7.6 KiB
- LICENSELicence file added by AutoGineer11.2 KiB
- SKILL.md7.3 KiB
- evals/evals.json6.4 KiB
- references/porting-reference.md10.9 KiB
- skill-card.md3.9 KiB
- skill.oms.sig4.7 KiB
references/porting-reference.md
Qiskit to CUDA-Q Porting Reference
Use this reference when the top-level SKILL.md says detailed gate, ordering,
precision, or framework-decoupling guidance is needed.
Porting Disciplines
Preserve the source algorithm when porting.
Do not change the high-level quantum algorithm without explicit permission. Examples: removing mid-circuit measurements, replacing iterative QPE with a coherent unroll, or changing oracle decompositions.
Do not introduce restrictions that the source implementation did not have.
If a CUDA-Q language constraint genuinely requires a cap or unsupported path, raise
NotImplementedErrorwith a clear reason. Never silently drop gates.A CUDA-Q port must not depend on Qiskit, Qiskit Aer, Qiskit IBM Runtime, or another source framework at runtime.
Avoid these failure modes:
Hardcoded register sizes such as
cudaq.qvector(10)whencudaq.qvector(num_qubits)works.Fixed-arity dispatchers that silently ignore controls beyond a hand-coded limit. Use runtime-arity control lists.
Rejecting source flags that are no-ops in CUDA-Q, such as a
parameterized=Trueflag when the CUDA-Q kernel already accepts runtime parameters.Per-shape kernel factories when a runtime integer parameter is enough.
Framework-free ports:
Do not
import qiskitfrom CUDA-Q modules.Do not import a Qiskit module just to reuse pure-Python helpers.
Do not build a
QuantumCircuitand inspectqc.dataat runtime.Move pure-Python analyzers, generators, and post-processing helpers into a sibling module using only stdlib and NumPy.
Gate Translation Table
| Qiskit | CUDA-Q decorator-mode equivalent | Notes |
|---|---|---|
qc.h(q), x, y, z, s, t, sdg, tdg | h(q), x(q), y(q), z(q), s(q), t(q), s.adj(q), t.adj(q) | Direct |
qc.rx/ry/rz(theta, q) | rx(theta, q), ry(theta, q), rz(theta, q) | Direct |
qc.p(theta, q) | r1(theta, q) | Both are diag(1, exp(i theta)) |
qc.cx(c, t) | cx(c, t) or x.ctrl(c, t) | Direct |
qc.cy/cz(c, t) | y.ctrl(c, t), z.ctrl(c, t) | Direct |
qc.ch(c, t) | h.ctrl(c, t) | Direct |
qc.crx/cry/crz(theta, c, t) | rx.ctrl(theta, c, t), ry.ctrl(...), rz.ctrl(...) | Control and target order matters |
qc.cp(theta, c, t) | r1.ctrl(theta, c, t) | Controlled phase; symmetric mathematically |
qc.u/UGate/u3(theta, phi, lam, q) | u3(theta, phi, lam, q) when available; otherwise decompose to rotations | Check the installed CUDA-Q version |
qc.cu/CUGate/cu3(theta, phi, lam, gamma, c, t) | u3.ctrl(theta, phi, lam, c, t) when available, with global-phase handling if needed; otherwise decompose | Do not assume a separate cu3 helper exists |
qc.rzz(theta, i, j) | cx(q[i], q[j]); rz(theta, q[j]); cx(q[i], q[j]) | Decomposition works across 0.14/0.15; prefer native rzz only if available in the installed API |
qc.rxx(theta, i, j) | H on both qubits, RZZ decomposition, H on both qubits | |
qc.ryy(theta, i, j) | Sdg and H basis changes around RZZ decomposition | |
qc.mcx([c...], t) | x.ctrl([c...], t) | Arbitrary arity |
qc.mcry(theta, [c...], t) | ry.ctrl(theta, [c...], t) | Arbitrary arity |
qc.mcp(theta, [c...], t) | r1.ctrl(theta, [c...], t) | Preferred for many-control phase |
MCXGate(..., ctrl_state="010") | X-wrap open controls before and after the controlled operation | No Qiskit-style ctrl_state argument; ~control syntax may be available in the installed CUDA-Q version |
qc.swap(a, b) | swap(a, b) | Direct |
qc.cswap(c, a, b) | swap.ctrl(c, a, b) | Also accepts list/variadic controls |
Final qc.measure(q, c) | mz(qubits) and cudaq.sample | See bit-ordering guidance |
Mid-circuit qc.measure(q, c) | b = mz(q) plus cudaq.run and typed return | Use when the measurement result drives control flow or must be returned; newer CUDA-Q documents mz captures as measurement handles that discriminate in boolean contexts or typed returns |
qc.reset(q) | reset(q) | Unconditional reset |
qc.append(U, qubits) | Implement U as a CUDA-Q kernel/function and call it | |
qc.inverse() | cudaq.adjoint(K, *args) at top level | Hand-roll inverse if K is used inside cudaq.control |
qc.control(n) | cudaq.control(K, controls, *args) | K must not contain cudaq.adjoint |
qc.compose(other, qubits) | Direct function call with qview slices or explicit qubits | |
Qiskit ParameterVector / binds | Pass parameter values as kernel arguments | No symbolic-vs-bound distinction |
For asymmetric controlled rotations, keep Qiskit's control-target orientation exactly. Swapping arguments gives a different unitary.
Bit Ordering and Count Keys
CUDA-Q and Qiskit stringify measurement results differently. Keep ordering changes at the port boundary: allocation convention, measurement return list, or final count-key formatting.
| API | Convention |
|---|---|
cudaq.sample with mz(qview) | Keys follow qview order; qview[0] is leftmost |
Multiple CUDA-Q qvector allocations | Keys follow allocation order, not mz call order |
cudaq.sample(..., explicit_measurements=True) | Keys follow measurement-call order |
cudaq.run returning List[bool] | Join return-list element 0 as leftmost |
cudaq.get_state(K)[i] | format(i, f"0{N}b") matches CUDA-Q sample key order for the same kernel |
Qiskit get_counts | Classical bit c[0] is displayed rightmost |
Mapping rules:
To match Qiskit keys like
{prefix}{c[N-1]}...{c[0]}, build a CUDA-Q return list in that same displayed order.To match a Qiskit register without a prefix, allocate CUDA-Q qubits so
qubits[N - 1 - q]corresponds to Qiskit'sqr[q].If a Qiskit oracle decomposes an integer and reverses its bit list with
[::-1], check whether the CUDA-Q port should remove that reverse because CUDA-Qregister[0]appears leftmost.CUDA-Q does not add spaces between classical registers in count keys.
When keys are wrong but counts are otherwise plausible, fix ordering at the boundary, not by changing the algorithm. Use deterministic 2- or 3-qubit probes and compare exact raw keys before relying on aggregate fidelity.
Floating-Point Precision
CUDA-Q and Qiskit commonly default to different statevector precision:
| Framework | Typical backend | Default amplitude precision | Bytes per complex amplitude |
|---|---|---|---|
| CUDA-Q | nvidia / cuStateVec | fp32 | 8 |
| Qiskit | Aer statevector/GPU | fp64 | 16 |
Implications:
Deep circuits or many small rotations can diverge between fp32 and fp64.
Transpiling through small bases can add rotations and increase rounding drift.
For cross-framework fidelity comparisons, use matching precision unless the task is explicitly default-vs-default comparison.
To match precision, adjust one side or the other (not both):
# Option A: raise CUDA-Q to fp64 to match Aer's default
cudaq.set_target("nvidia", option="fp64")
# Option B: lower Aer to fp32 to match CUDA-Q's default
sim = AerSimulator(device="GPU", precision="single")CUDA-Q fp64 roughly doubles statevector memory, reducing maximum GPU width.
Framework-Decoupling Patterns
Recursive Constructor to Flat Emitter
CUDA-Q kernels cannot recurse. If a Qiskit implementation recursively builds subcircuits, port the recursion to a pure-Python emitter that produces arrays consumed by a non-recursive kernel.
def ucr_sequence_pure(n, theta):
ry_angles, ctrl_indices = [], []
def recurse(qubit_idx_list, theta_slice):
if len(qubit_idx_list) == 1:
ry_angles.append(float(theta_slice[0]))
ctrl_indices.append(qubit_idx_list[0])
ry_angles.append(float(theta_slice[1]))
else:
half = len(theta_slice) // 2
recurse(qubit_idx_list[1:], theta_slice[:half])
ctrl_indices.append(qubit_idx_list[0])
recurse(qubit_idx_list[1:], theta_slice[half:])
recurse(list(range(n)), list(theta))
ctrl_indices.append(0)
return ry_angles, ctrl_indicesIf source code uses sympy.combinatorics.GrayCode, replace it with
gray(i) = i ^ (i >> 1) when possible.
Source-Framework Import Blocker
Use this verification pattern after extracting pure helpers:
import sys, importlib.abc
class _BlockSourceFramework(importlib.abc.MetaPathFinder):
BLOCKED = ("qiskit", "qiskit_aer", "qiskit_ibm_runtime", "sympy")
def find_spec(self, name, path, target=None):
for blocked in self.BLOCKED:
if name == blocked or name.startswith(blocked + "."):
raise ModuleNotFoundError(f"refusing to import {name}")
return None
sys.meta_path.insert(0, _BlockSourceFramework())Then import and run the CUDA-Q port at a small representative configuration.
Gate-Recorder Class
For deeply nested Qiskit constructors with .inverse() and .control(k), use
a Python-side recorder whose methods mirror the source constructors and append
parallel arrays for a CUDA-Q kernel walker.
Default op-kind menu for modular-arithmetic-style circuits:
1 = h
2 = x
3 = cx
4 = swap.ctrl
5 = r1(angle, t)
6 = r1.ctrl(angle, c, t)
7 = r1.ctrl(angle, c1, c2, t)
8 = rz.ctrl(angle, c, t)For inverse calls, build a forward sub-sequence into a temporary recorder, then append records in reverse order while negating rotation angles. Self-inverse gates such as H, X, CX, and CSWAP keep angle 0.
Native-gate dispatch avoids per-circuit transpile cost and precision loss from
unnecessary transpilation. When u3 / controlled u3 exists in the installed
CUDA-Q API, emit it directly; otherwise decompose through supported rotations,
cx, and swap.
Port Validation Gate
For every port:
Run the source implementation for the same deterministic inputs.
Run the CUDA-Q implementation with the same inputs.
Compare raw count keys, not only fidelity.
Test at least one small, nominal, and larger configuration when feasible.
Use stochastic tolerance only when shot noise is expected to dominate.
Re-run every previously failing configuration after changes.
When installed CUDA-Q behavior differs from the latest documentation while debugging, review relevant documentation or source changes between the installed version and latest before changing the port.
When stuck, copy subcircuit conventions from the exact source module being ported. IQFT direction, qubit order, and gate flavor can differ across implementations with similar names.
External References
CUDA-Q latest documentation: https://nvidia.github.io/cuda-quantum/latest/
CUDA-Q examples in the local/source tree:
docs/sphinx/examples/pythonCUDA-Q Academic: https://github.com/NVIDIA/cuda-q-academic
CUDA-Q tests:
python/tests/kernel/test_kernel_features.pyandpython/tests/kernel/test_measure_handle.pywhen presentCompanion skill:
cudaq-guide(/cudaq-guide author) for execution API selection, kernel-language constraints, shared kernel patterns, resource metrics, and debugging workflow.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Python
The author says: Python 3.10+
Security
What our scanner noticed· Medium risk
- Large base64-encoded blobs
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- CUDA-Q Team
- Publisher
- NVIDIA (Official)
- Distributed by
- NVIDIA
- Source
- NVIDIA/skills · skills/cudaq-importing · commit fce3cca
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE-APACHE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by CUDA-Q Team or NVIDIA.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download cudaq-importing.zip