Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8772184
Initial: Add Custom Gates/Instructions in Rust
raynelfss Feb 13, 2026
f20f7e3
Fix: Add case for `CustomInstruction` in QPY
raynelfss Feb 14, 2026
badbbdd
Fix: Add missing methods in `PackedInstruction`.
raynelfss Feb 17, 2026
5513f65
Add: `downcast_ref` for `NativeOperation`.
raynelfss Feb 17, 2026
1594c96
Remove: Gate and Instruction views.
raynelfss Feb 18, 2026
32623f7
Add: Method to push custom operation to a Circuit
raynelfss Feb 24, 2026
f2fcb47
Merge remote-tracking branch 'upstream/main' into rust-custom-gate
raynelfss Mar 4, 2026
fa6c006
Merge remote-tracking branch 'upstream/main' into rust-custom-gate
raynelfss Mar 5, 2026
d312bf4
Fix: Implement `Deref` and `DerefMut` for `CustomOp`.
raynelfss Mar 6, 2026
ed3a884
Merge branch 'main' into rust-custom-gate
raynelfss Mar 10, 2026
1f8b9a2
Fix: `Native` -> `Custom`
raynelfss Mar 10, 2026
79f127c
Refactor: Hide `CustomOp` to be internal to the `Circuit` crate
raynelfss Mar 12, 2026
51edfa4
Docs: Fix `CustomOperation`s docstring
raynelfss Mar 12, 2026
bb4074b
Revert: Changes to caused by clippy.
raynelfss Mar 12, 2026
1b9b61d
Fix: Address minor review comments
raynelfss Mar 17, 2026
28c9138
Merge remote-tracking branch 'upstream/main' into rust-custom-gate
raynelfss Apr 6, 2026
89d6c99
Address review comments.
raynelfss Apr 6, 2026
d0fc761
Merge remote-tracking branch 'upstream/main' into rust-custom-gate
raynelfss Apr 16, 2026
cfff8af
Merge remote-tracking branch 'upstream/main' into rust-custom-gate
raynelfss Apr 16, 2026
44f5dbc
FIx: Use trait upcasing to implement `downcast_ref`.
raynelfss Apr 17, 2026
ee48800
Fix: Old review comments
raynelfss Apr 22, 2026
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
7 changes: 4 additions & 3 deletions crates/cext/src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,9 +851,10 @@ pub unsafe extern "C" fn qk_circuit_instruction_kind(
OperationRef::PauliProductMeasurement(_) => COperationKind::PauliProductMeasurement,
OperationRef::PauliProductRotation(_) => COperationKind::PauliProductRotation,
OperationRef::ControlFlow(_) => COperationKind::ControlFlow,
OperationRef::Gate(_) | OperationRef::Instruction(_) | OperationRef::Operation(_) => {
COperationKind::Unknown
}
OperationRef::Gate(_)
| OperationRef::Instruction(_)
| OperationRef::Operation(_)
| OperationRef::CustomOperation(_) => COperationKind::Unknown,
}
}

Expand Down
7 changes: 4 additions & 3 deletions crates/cext/src/dag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,9 +1021,10 @@ pub unsafe extern "C" fn qk_dag_op_node_kind(dag: *const DAGCircuit, node: u32)
OperationRef::PauliProductMeasurement(_) => COperationKind::PauliProductMeasurement,
OperationRef::PauliProductRotation(_) => COperationKind::PauliProductRotation,
OperationRef::ControlFlow(_) => COperationKind::ControlFlow,
OperationRef::Gate(_) | OperationRef::Instruction(_) | OperationRef::Operation(_) => {
COperationKind::Unknown
}
OperationRef::Gate(_)
| OperationRef::Instruction(_)
| OperationRef::Operation(_)
| OperationRef::CustomOperation(_) => COperationKind::Unknown,
}
}

Expand Down
32 changes: 30 additions & 2 deletions crates/circuit/src/circuit_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ use crate::instruction::Parameters;
use crate::interner::{Interned, InternedMap, Interner};
use crate::object_registry::{self, ObjectRegistry};
use crate::operations::{
ControlFlow, ControlFlowView, Operation, OperationRef, Param, PauliBased, PyOperationTypes,
PythonOperation, StandardGate,
ControlFlow, ControlFlowView, CustomOp, CustomOperation, Operation, OperationRef, Param,
PauliBased, PyOperationTypes, PythonOperation, StandardGate,
};
use crate::packed_instruction::{PackedInstruction, PackedOperation};
use crate::parameter::parameter_expression::{ParameterError, ParameterExpression};
Expand Down Expand Up @@ -1053,6 +1053,25 @@ impl CircuitData {
))
}

/// Appends a custom operation to this instance of [CircuitData].
pub fn push_custom_operation<O>(
&mut self,
operation: O,
params: &[Param],
qargs: &[Qubit],
cargs: &[Clbit],
) -> Result<(), CircuitDataError>
where
O: CustomOperation,
{
let params = (!params.is_empty()).then(|| Box::new(params.iter().cloned().collect()));
let qubits = self.qargs_interner.insert(qargs);
let clbits = self.cargs_interner.insert(cargs);
self.push(PackedInstruction::from_custom_operation(
operation, qubits, clbits, params,
))
}

/// Append a packed operation to this CircuitData.
///
/// If a [ControlFlow] operation is provided, the blocks given in
Expand Down Expand Up @@ -3078,6 +3097,9 @@ impl PyCircuitData {
OperationRef::PauliProductRotation(ppr) => {
PauliBased::PauliProductRotation(ppr.clone()).into()
}
OperationRef::CustomOperation(custom_operation) => {
CustomOp::from(custom_operation.clone_dyn()).into()
}
};
res.data.push(PackedInstruction {
op: new_op,
Expand Down Expand Up @@ -3109,6 +3131,9 @@ impl PyCircuitData {
OperationRef::PauliProductRotation(ppr) => {
PauliBased::PauliProductRotation(ppr.clone()).into()
}
OperationRef::CustomOperation(custom_operation) => {
CustomOp::from(custom_operation.clone_dyn()).into()
}
};
res.data.push(PackedInstruction {
op: new_op,
Expand Down Expand Up @@ -4000,6 +4025,9 @@ impl PyCircuitData {
OperationRef::Operation(op) => {
PyOperationTypes::Operation(op.py_deepcopy(py, None)?).into()
}
OperationRef::CustomOperation(custom) => {
PackedOperation::from_boxed_custom_operation(custom.clone_dyn())
}
};
out.push(PackedInstruction { op, ..inst.clone() })?;
}
Expand Down
5 changes: 4 additions & 1 deletion crates/circuit/src/circuit_instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,10 @@ pub fn extract_params<T: CircuitBlock>(
}
}
OperationRef::Unitary(_) | OperationRef::PauliProductMeasurement(_) => None,
OperationRef::Gate(_) | OperationRef::Instruction(_) | OperationRef::Operation(_) => {
OperationRef::CustomOperation(_)
| OperationRef::Gate(_)
| OperationRef::Instruction(_)
| OperationRef::Operation(_) => {
let params: SmallVec<[Param; 3]> = params.extract()?;
(!params.is_empty()).then(|| Parameters::Params(params))
}
Expand Down
3 changes: 3 additions & 0 deletions crates/circuit/src/dag_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7891,6 +7891,9 @@ impl DAGCircuit {
OperationRef::StandardGate(gate) => gate.into(),
OperationRef::StandardInstruction(instruction) => instruction.into(),
OperationRef::Unitary(unitary) => unitary.clone().into(),
OperationRef::CustomOperation(custom) => {
PackedOperation::from_boxed_custom_operation(custom.clone_dyn())
}
OperationRef::PauliProductMeasurement(ppm) => {
PauliBased::PauliProductMeasurement(ppm.clone()).into()
}
Expand Down
2 changes: 2 additions & 0 deletions crates/circuit/src/dag_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ impl DAGOpNode {
OperationRef::StandardGate(gate) => gate.into(),
OperationRef::StandardInstruction(instruction) => instruction.into(),
OperationRef::Unitary(unitary) => unitary.clone().into(),
OperationRef::CustomOperation(_) => instruction.operation.clone(),
OperationRef::PauliProductMeasurement(ppm) => {
PauliBased::PauliProductMeasurement(ppm.clone()).into()
}
Expand Down Expand Up @@ -327,6 +328,7 @@ impl DAGOpNode {
OperationRef::StandardGate(gate) => gate.into(),
OperationRef::StandardInstruction(instruction) => instruction.into(),
OperationRef::Unitary(unitary) => unitary.clone().into(),
OperationRef::CustomOperation(_) => self.instruction.operation.clone(),
OperationRef::PauliProductMeasurement(ppm) => {
PauliBased::PauliProductMeasurement(ppm.clone()).into()
}
Expand Down
3 changes: 3 additions & 0 deletions crates/circuit/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,5 +191,8 @@ pub fn create_py_op(
OperationRef::Instruction(instruction) => Ok(instruction.instruction.clone_ref(py)),
OperationRef::Operation(operation) => Ok(operation.instruction.clone_ref(py)),
OperationRef::Unitary(unitary) => unitary.create_py_op(py, label),
OperationRef::CustomOperation(custom_gate) => custom_gate
.create_py_op(py, params.map(|p| p.unwrap_params()))
.map(|op| op.unbind()),
}
}
Loading
Loading