Skip to content

Update API dev docs #3710

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/api/qiskit-c/dev/_toc.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
"title": "QkComplex64",
"url": "/docs/api/qiskit-c/dev/qk-complex-64"
},
{
"title": "QkElidePermutationsResult",
"url": "/docs/api/qiskit-c/dev/qk-elide-permutations-result"
},
{
"title": "QkExitCode",
"url": "/docs/api/qiskit-c/dev/qk-exit-code"
Expand Down
5 changes: 3 additions & 2 deletions docs/api/qiskit-c/dev/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ As this interface is still new in Qiskit it should be considered experimental an

Using the transpiler from the C API is intended to only cover circuits created solely via the C API. If you are in a hybrid mode where you’re using the C API with Python you should invoke the transpiler via the Python [`qiskit.transpiler`](/docs/api/qiskit/dev/transpiler#module-qiskit.transpiler "qiskit.transpiler") module instead; the functionality is the same Rust internals they just offer different entrypoints. The C API for transpilation makes assumptions about the input only using constructs exposed to the C Quantum Circuit API and you will potentially get incomplete results transpiling circuits from Python via the C API.

* [Transpiler Passes](qk-transpiler-passes)
* [QkVF2LayoutResult](qk-vf-2-layout-result)
* [QkTarget](qk-target)
* [QkTargetEntry](qk-target-entry)
* [Transpiler Passes](qk-transpiler-passes)
* [QkVF2LayoutResult](qk-vf-2-layout-result)
* [QkElidePermutationsResult](qk-elide-permutations-result)

31 changes: 15 additions & 16 deletions docs/api/qiskit-c/dev/qk-circuit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ $$
// Create a circuit with three qubits and 3 classical bits
QkCircuit *qc = qk_circuit_new(3, 0);
// H gate on qubit 0, putting this qubit in a superposition of |0> + |1>.
qk_circuit_gate(qc, QkGate_H, {0}, NULL);
qk_circuit_gate(qc, QkGate_H, (uint32_t[]){0}, NULL);
// A CX (CNOT) gate on control qubit 0 and target qubit 1 generating a Bell state.
qk_circuit_gate(qc, QkGate_CX, {0, 1}, NULL);
qk_circuit_gate(qc, QkGate_CX, (uint32_t[]){0, 1}, NULL);
// A CX (CNOT) gate on control qubit 0 and target qubit 2 generating a GHZ state.
qk_circuit_gate(qc, QkGate_CX, {0, 2}, NULL);
qk_circuit_gate(qc, QkGate_CX, (uint32_t[]){0, 2}, NULL);
// Free the created circuit.
qk_circuit_free(qc);
```
Expand Down Expand Up @@ -202,7 +202,7 @@ The circuit C API currently only supports creating circuits that contain operati
QkQuantumRegister *qr = qk_quantum_register_new(1024, "my_little_register");
qk_circuit_add_quantum_register(qc, qr);
qk_quantum_register_free(qr);
qk_circuit_free(qc)
qk_circuit_free(qc);
```

<span id="group__QkCircuit_1autotoc_md13" />
Expand Down Expand Up @@ -233,7 +233,7 @@ The circuit C API currently only supports creating circuits that contain operati
QkClassicalRegister *cr = qk_classical_register_new(24, "my_big_register");
qk_circuit_add_classical_register(qc, cr);
qk_classical_register_free(cr);
qk_circuit_free(qc)
qk_circuit_free(qc);
```

<span id="group__QkCircuit_1autotoc_md15" />
Expand Down Expand Up @@ -391,7 +391,7 @@ The circuit C API currently only supports creating circuits that contain operati

<span id="group__QkCircuit_1autotoc_md25" />

The `qubits` and `params` types are expected to be a pointer to an array of `uint32_t` and `double` respectively where the length is matching the expectations for the standard gate. If the array is insufficently long the behavior of this function is undefined as this will read outside the bounds of the array. It can be a null pointer if there are no qubits or params for a given gate. You can check `qk_gate_num_qubits` and `qk_gate_num_params` to determine how many qubits and params are required for a given gate.
The `qubits` and `params` types are expected to be a pointer to an array of `uint32_t` and `double` respectively where the length is matching the expectations for the standard gate. If the array is insufficiently long the behavior of this function is undefined as this will read outside the bounds of the array. It can be a null pointer if there are no qubits or params for a given gate. You can check `qk_gate_num_qubits` and `qk_gate_num_params` to determine how many qubits and params are required for a given gate.

Behavior is undefined if `circuit` is not a valid, non-null pointer to a `QkCircuit`.

Expand Down Expand Up @@ -562,17 +562,16 @@ The circuit C API currently only supports creating circuits that contain operati
#### Example

```c
QkComplex64 c0 = qk_complex64_from_native(0); // 0+0i
QkComplex64 c1 = qk_complex64_from_native(1); // 1+0i
QkComplex64 c0 = {0, 0}; // 0+0i
QkComplex64 c1 = {1, 0}; // 1+0i

const uint32_t num_qubits = 1;
const uint32_t dim = 2;
QkComplex64[dim * dim] unitary = {c0, c1, // row 0
QkComplex64 unitary[2*2] = {c0, c1, // row 0
c1, c0}; // row 1

QkCircuit *circuit = qk_circuit_new(1, 0); // 1 qubit circuit
uint32_t qubit = {0}; // qubit to apply the unitary on
qk_circuit_unitary(circuit, unitary, qubit, num_qubits);
uint32_t qubit[1] = {0}; // qubit to apply the unitary on
qk_circuit_unitary(circuit, unitary, qubit, num_qubits, true);
```

<span id="group__QkCircuit_1autotoc_md35" />
Expand Down Expand Up @@ -607,7 +606,7 @@ The circuit C API currently only supports creating circuits that contain operati

```c
QkCircuit *qc = qk_circuit_new(100, 0);
uint32_t qubit[1] = {0};
uint32_t qubits[1] = {0};
qk_circuit_gate(qc, QkGate_H, qubits, NULL);
QkOpCounts counts = qk_circuit_count_ops(qc);
```
Expand Down Expand Up @@ -675,7 +674,7 @@ The circuit C API currently only supports creating circuits that contain operati

```c
QkCircuitInstruction inst;
QkCircuit *qc = qk_circuit_new(100);
QkCircuit *qc = qk_circuit_new(100, 0);
uint32_t qubit[1] = {0};
qk_circuit_gate(qc, QkGate_H, qubit, NULL);
qk_circuit_get_instruction(qc, 0, &inst);
Expand Down Expand Up @@ -709,8 +708,8 @@ The circuit C API currently only supports creating circuits that contain operati

```c
QkCircuitInstruction *inst = malloc(sizeof(QkCircuitInstruction));
QkCircuit *qc = qk_circuit_new(100);
uint32_t q0 = {0};
QkCircuit *qc = qk_circuit_new(100, 0);
uint32_t q0[1] = {0};
qk_circuit_gate(qc, QkGate_H, q0, NULL);
qk_circuit_get_instruction(qc, 0, inst);
qk_circuit_instruction_clear(inst); // free the data
Expand Down
14 changes: 13 additions & 1 deletion docs/api/qiskit-c/dev/qk-classical-register.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,26 @@ python_api_name: QkClassicalRegister
typedef struct QkClassicalRegister QkClassicalRegister
```

A common way to instantiate several bits at once is to create a register. A register is a named collection of bits. Creating a register enables giving a collection of bits a name which can be use as metadata around specific bits in a circuit. This name will also typically be preseserved when exporting the circuit to interchange languages.
A common way to instantiate several bits at once is to create a register. A register is a named collection of bits. Creating a register enables giving a collection of bits a name which can be use as metadata around specific bits in a circuit. This name will also typically be preserved when exporting the circuit to interchange languages.

You can create a register by calling `qk_classical_register_new()`, for example:

```c
#include <qiskit.h>

QkClassicalRegister *creg = qk_classical_register_new(5, "my_creg");
```

Which creates a new 5 classical bit register named `"my_creg"`.

Then to add the register to a circuit you use the `qk_circuit_add_classical_register()` function:

```c
QkCircuit *qc = qk_circuit_new(0, 0);
qk_circuit_add_classical_register(qc, creg);
uint32_t num_qubits = qk_circuit_num_qubits(qc); // 5
```

While circuits track registers, the registers themselves impart almost no behavioral differences on circuits.

## Functions
Expand Down
10 changes: 5 additions & 5 deletions docs/api/qiskit-c/dev/qk-complex-64.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ python_api_name: QkComplex64

# QkComplex64

A complex, double-precision number representation. This data type is used to safely use complex numbers within Qiskit, but is not necessarily designed for easy manipulation on user-side. Instead, we provide functions to convert from compiler-native representation (e.g. `double complex` for GNU or Clang compilers), which allow for ergonomic handling, to Qiskit’s `QkComplex64` representation, which is meant for passing into Qiskit functions and structs.
A complex, double-precision number representation. This data type is used to safely use complex numbers within Qiskit, but is not necessarily designed for easy manipulation on user-side. Instead, we provide functions to convert from compiler-native representation (e.g. `complex double` for GNU or Clang compilers), which allow for ergonomic handling, to Qiskit’s `QkComplex64` representation, which is meant for passing into Qiskit functions and structs.

Explicitly, Qiskit assumes the compiler-native complex number type in C to be `_Dcomplex` for Windows MSVC (if `_MSC_VER` is defined) and `double _Complex` otherwise. In C++ (if `__cplusplus` is defined), the complex number type is always `std::complex<double>`.

Expand Down Expand Up @@ -38,11 +38,11 @@ Convert a `QkComplex64` to a compiler-native complex number representation. Note

### Example

Assuming a GNU/clang compiler with `double complex` as native complex number, we have
Assuming a GNU/clang compiler with `complex double` as native complex number, we have

```c
QkComplex64 qk_value = {1, 1}; // represents 1 + i
double complex value = qk_complex64_to_native(&qk_value);
complex double value = qk_complex64_to_native(&qk_value);
```
### Safety
Expand All @@ -65,10 +65,10 @@ Convert a compiler-native complex number to a `QkComplex64`. Note that `CMPLX_DO
### Example
Assuming a GNU/clang compiler with `double complex` as native complex number, we have
Assuming a GNU/clang compiler with `complex double` as native complex number, we have
```c
double complex value = 1 + I;
complex double value = 1 + I;
QkComplex64 qk_value = qk_complex64_from_native(&value);
```

Expand Down
102 changes: 102 additions & 0 deletions docs/api/qiskit-c/dev/qk-elide-permutations-result.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
title: QkElidePermutationsResult (dev version)
description: API reference for QkElidePermutationsResult in the dev version of qiskit-c
in_page_toc_min_heading_level: 2
python_api_type: module
python_api_name: QkElidePermutationsResult
---

# QkElidePermutationsResult

```c
typedef struct QkElidePermutationsResult QkElidePermutationsResult
```

When running the `qk_transpiler_pass_standalone_elide_permutations` function it returns a modified circuit and a permutation array as a QkElidePermutationsResult object. This object contains the outcome of the transpiler pass, whether the pass was able to elide any gates or not, and what the results of that elision were.

## Functions

### qk\_elide\_permutations\_result\_elided\_gates

<Function id="qk_elide_permutations_result_elided_gates" signature="bool qk_elide_permutations_result_elided_gates(const QkElidePermutationsResult *result)">
Check whether the elide permutations was able to elide anything

<span id="group__QkElidePermutationsResult_1autotoc_md94" />

#### Safety

<span id="group__QkElidePermutationsResult_1autotoc_md94" />

Behavior is undefined if `result` is not a valid, non-null pointer to a `QkElidePermutationsResult`.

**Parameters**

**result** – a pointer to the result

**Returns**

`true` if the `qk_transpiler_pass_standalone_elide_permutations()` run elided any gates
</Function>

### qk\_elide\_permutations\_result\_circuit

<Function id="qk_elide_permutations_result_circuit" signature="const QkCircuit *qk_elide_permutations_result_circuit(const QkElidePermutationsResult *result)">
Get the circuit from the elide permutations result

<span id="group__QkElidePermutationsResult_1autotoc_md95" />

#### Safety

<span id="group__QkElidePermutationsResult_1autotoc_md95" />

Behavior is undefined if `result` is not a valid, non-null pointer to a `QkElidePermutationsResult`. The pointer to the returned circuit is owned by the result object, it should not be passed to `qk_circuit_free()` as it will be freed by `qk_elide_permutations_result_free()`.

**Parameters**

**result** – a pointer to the result of the pass. It must have elided gates as checked by `qk_elide_permutations_result_elided_gates()`

**Returns**

A pointer to the circuit with the permutation gates elided
</Function>

### qk\_elide\_permutations\_result\_permutation

<Function id="qk_elide_permutations_result_permutation" signature="const uintptr_t *qk_elide_permutations_result_permutation(const QkElidePermutationsResult *result)">
Get the permutation array for the elided gates

<span id="group__QkElidePermutationsResult_1autotoc_md96" />

#### Safety

<span id="group__QkElidePermutationsResult_1autotoc_md96" />

Behavior is undefined if `layout` is not a valid, non-null pointer to a `QkElidePermutationsResult`. Also qubit must be a valid qubit for the circuit and there must be a result found. The pointer to the permutation array is owned by the result object, it should not be passed to `free()` as it will be freed by `qk_elide_permutations_result_free()` when that is called.

**Parameters**

**result** – a pointer to the result of the pass. It must have elided gates as checked by `qk_elide_permutations_result_elided_gates()`

**Returns**

A pointer to the permutation array caused by the swap elision performed by the pass. This array has a length equal to the number of qubits of the circuit returned by `qk_elide_permutations_result_elided_gates()` (or the circuit passed into `qk_transpiler_pass_standalone_elide_permutations()`). The permutation array maps the virtual qubit in the original circuit at each index to its new output position after all the elision performed by the pass. For example, and array of `[2, 1, 0]` means that qubit 0 is now in qubit 2 on the output of the circuit and qubit 2’s is now at 0 (qubit 1 remains unchanged)
</Function>

### qk\_elide\_permutations\_result\_free

<Function id="qk_elide_permutations_result_free" signature="void qk_elide_permutations_result_free(QkElidePermutationsResult *result)">
Free a `QkElidePermutationsResult` object

<span id="group__QkElidePermutationsResult_1autotoc_md97" />

#### Safety

<span id="group__QkElidePermutationsResult_1autotoc_md97" />

Behavior is undefined if `layout` is not a valid, non-null pointer to a `QkElidePermutationsResult`.

**Parameters**

**result** – a pointer to the result object to free
</Function>

Loading