-
Notifications
You must be signed in to change notification settings - Fork 2.9k
C API: Burn Optimize1qGatesDecomposition.
#14710
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
Changes from 7 commits
67a495a
3f053cb
a77ce5e
0fe11b8
84c6bf3
6edc33c
cfc03cb
7ee5c4a
cf16fa9
619ec0d
7e8a147
b4ba388
4ab2e26
19f55a6
25cd6cf
923a8bb
0a75d7c
01d280e
9315826
b4bd4ba
82ce69d
9224253
b40298b
85317c9
1b86842
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,14 @@ | ||
| // This code is part of Qiskit. | ||
| // | ||
| // (C) Copyright IBM 2025 | ||
| // | ||
| // This code is licensed under the Apache License, Version 2.0. You may | ||
| // obtain a copy of this license in the LICENSE.txt file in the root directory | ||
| // of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
| // | ||
| // Any modifications or derivative works of this code must retain this | ||
| // copyright notice, and modified files need to carry a notice indicating | ||
| // that they have been altered from the originals. | ||
|
|
||
| pub mod optimize_1q_decomposition; | ||
| pub mod vf2; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| // This code is part of Qiskit. | ||
| // | ||
| // (C) Copyright IBM 2025 | ||
| // | ||
| // This code is licensed under the Apache License, Version 2.0. You may | ||
| // obtain a copy of this license in the LICENSE.txt file in the root directory | ||
| // of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
| // | ||
| // Any modifications or derivative works of this code must retain this | ||
| // copyright notice, and modified files need to carry a notice indicating | ||
| // that they have been altered from the originals. | ||
|
|
||
| use crate::pointers::const_ptr_as_ref; | ||
| use qiskit_circuit::{ | ||
| circuit_data::CircuitData, converters::dag_to_circuit, dag_circuit::DAGCircuit, | ||
| }; | ||
| use qiskit_transpiler::{passes::run_optimize_1q_gates_decomposition, target::Target}; | ||
|
|
||
| /// @ingroup QkTranspilerPasses | ||
| /// Runs the Optimize1qGatesDecomposition pass in standalone mode on a circuit. | ||
| /// | ||
| /// Optimize1qGatesDecomposition, as its name implies, optimizes chains of single-qubit | ||
| /// gates by combining them into a single gate. | ||
| /// | ||
| /// The decision of whether to replace the original chain depends on: | ||
| /// - If the original chain was out of basis. | ||
| /// - If the original chain was in basis but the replacement has lower error rates. | ||
| /// - If the original chain is an identity (chain gets removed). | ||
| /// | ||
| /// The error is the combined multiplication of the errors of individual gates on the | ||
| /// qubit it operates on. | ||
| /// | ||
| /// @param circuit A pointer to the ``QkCircuit`` object to transform. | ||
| /// @param target A pointer to the ``QkTarget`` object. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the code it looks like this is allowed to be a null pointer. What happens in this case? We should document that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From snippet: /// In the case a null pointer is provided and gate errors are unknown
/// the pass will choose the sequence with the least amount of gates,
/// and will support all basis gates on its Euler basis set.
|
||
| /// | ||
| /// @return The circuit after applying the optimizations. | ||
|
raynelfss marked this conversation as resolved.
Outdated
|
||
| /// | ||
| /// # Example | ||
| /// | ||
| /// QkTarget *target_u1_u2_u3 = qk_target_new(1); | ||
| /// | ||
| /// double u_errors[3] = {0., 1e-4, 1e-4}; | ||
| /// QkGate u_gates[3] = {QkGate_U1, QkGate_U2, QkGate_U3}; | ||
| /// // TODO: Update this part to use parameters once we support them. | ||
| /// double u1_params[1] = {3.14}; | ||
| /// double u2_params[2] = {3.14, 3.14 / 2.}; | ||
| /// double u3_params[3] = {3.14, 3.14 / 2., 3.14 / 4.}; | ||
| /// | ||
| /// double **u_params = {u1_params, u2_params, u3_params}; | ||
| /// for (int idx = 0; idx < 3; idx++) { | ||
| /// QkTargetEntry *u_entry = qk_target_entry_new_fixed(u_gates[idx], u_params[idx]); | ||
| /// uint32_t qargs[1] = { | ||
| /// 0, | ||
| /// }; | ||
| /// qk_target_entry_add_property(u_entry, qargs, 1, NAN, u_errors[idx]); | ||
| /// qk_target_add_instruction(target_u1_u2_u3, u_entry); | ||
| /// } | ||
| /// | ||
| /// // Build circuit | ||
| /// QkCircuit *circuit = qk_circuit_new(1, 0); | ||
| /// uint32_t qubits[1] = {0}; | ||
| /// for (int iter = 0; iter < 3; iter++) { | ||
| /// qk_circuit_gate(circuit, QkGate_H, qubits, NULL); | ||
| /// } | ||
| /// | ||
| /// // Run transpiler pass | ||
| /// QkCircuit *circuit_result = | ||
| /// qk_transpiler_standalone_optimize_1q_gates_decomposition(circuit, target); | ||
| /// | ||
| /// // Clean up | ||
| /// qk_target_free(target_u1_u2_u3); | ||
| /// qk_circuit_free(circuit); | ||
| /// qk_circuit_free(circuit_result); | ||
|
raynelfss marked this conversation as resolved.
Outdated
|
||
| /// | ||
| /// # Safety | ||
| /// | ||
| /// Behavior is undefined if ``circuit`` is not a valid, non-null pointer to a ``QkCircuit`` and | ||
| /// if ``target`` is not a valid pointer to a ``QkTarget``. | ||
| #[no_mangle] | ||
| #[cfg(feature = "cbinding")] | ||
| pub unsafe extern "C" fn qk_transpiler_standalone_optimize_1q_gates_decomposition( | ||
|
raynelfss marked this conversation as resolved.
Outdated
|
||
| circuit: *const CircuitData, | ||
| target: *const Target, | ||
| ) -> *mut CircuitData { | ||
| // SAFETY: Per documentation, the pointer is non-null and aligned. | ||
| let target = unsafe { | ||
| if target.is_null() { | ||
| None | ||
| } else { | ||
| Some(const_ptr_as_ref(target)) | ||
| } | ||
| }; | ||
| // SAFETY: Per documentation, the pointer is non-null and aligned. | ||
| let circuit = unsafe { const_ptr_as_ref(circuit) }; | ||
|
|
||
| // Convert the circuit to a DAG. | ||
| let mut circuit_as_dag = DAGCircuit::from_circuit_data(circuit, false, None, None, None, None) | ||
| .expect("Error while converting the circuit to a dag."); | ||
|
Comment on lines
+90
to
+
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice if we would have a set of |
||
|
|
||
| // Run the pass | ||
| run_optimize_1q_gates_decomposition(&mut circuit_as_dag, target, None, None) | ||
| .expect("Error while running the pass."); | ||
|
|
||
| // Convert the DAGCircuit back to an instance of CircuitData | ||
| let dag_to_circuit = dag_to_circuit(&circuit_as_dag, false) | ||
| .expect("Error while converting the dag to a circuit."); | ||
|
|
||
| // Convert to pointer. | ||
| Box::into_raw(Box::new(dag_to_circuit)) | ||
|
Cryoris marked this conversation as resolved.
Outdated
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| --- | ||
| features_c: | ||
| - | | ||
| Add support for the ``Optimize1qGatesDecomposition`` transpiler pass through | ||
| the C API, via the ``qk_transpiler_standalone_optimize_1q_gates_decomposition`` | ||
| method. | ||
|
|
||
| Here's an example: | ||
|
|
||
| .. code-block:: C | ||
|
|
||
| // Build a circuit | ||
| QkCircuit *circuit = qk_circuit_new(1, 0); | ||
| uint32_t qubits[1] = {0}; | ||
| double params_pos[1] = {3.14 / 7.}; | ||
| double params_neg[1] = {-3.14 / 7.}; | ||
| qk_circuit_gate(circuit, QkGate_RY, qubits, params_pos); | ||
| qk_circuit_gate(circuit, QkGate_RY, qubits, params_neg); | ||
|
|
||
| // Run the transpiler pass | ||
| QkCircuit *circuit_result = | ||
| qk_transpiler_standalone_optimize_1q_gates_decomposition(circuit, NULL); | ||
|
|
||
| // Free both circuits | ||
| qk_circuit_free(circuit); | ||
| qk_circuit_free(circuit_result); |
Uh oh!
There was an error while loading. Please reload this page.