Skip to content

Commit

Permalink
Add Rust representation for most controlled gates (Qiskit#12659)
Browse files Browse the repository at this point in the history
* Add C3X (MCX), extend rust tests to multi-controlled gates.

* Add macro to generate multi-controlled gates. Add CU, CU1, CU3, C3SX, C4X, CCZ.

* Kill C4XGate

* Finish adding gates, add circuit construction methods when possible.

* Add import paths, fix drawer test.

* Establish CGates with non-default control states as non-standard in circuit_instruction.rs. Add unit test.

* Fix merge conflicts

* Apply macro on missing gates

* Add RCCX gate and RC3X (RCCCX) gate.

* Make equivalence tests more explicit

* Fix lint

* Modify circuit methods for consistency

* Fix default ctrl state for 3q+ gates, add test for CCZ

* Apply comments from Matt's code review

* Fix ctrl_state logic

* Rename c3x to mcx?

* Brackets didn't match explanation

* Make sure controlled test doesn't use custom ControlledGate instances.

* Rename c4x to mcx in Rust space.

* Return PyResult rather than panic on error

* Add suggestion from Matt's code review

Co-authored-by: Matthew Treinish <[email protected]>

---------

Co-authored-by: John Lapeyre <[email protected]>
Co-authored-by: Matthew Treinish <[email protected]>
  • Loading branch information
3 people authored Jul 8, 2024
1 parent 008dde3 commit 4867e8a
Show file tree
Hide file tree
Showing 12 changed files with 928 additions and 260 deletions.
37 changes: 31 additions & 6 deletions crates/circuit/src/circuit_instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use pyo3::{intern, IntoPy, PyObject, PyResult};
use smallvec::{smallvec, SmallVec};

use crate::imports::{
get_std_gate_class, populate_std_gate_map, GATE, INSTRUCTION, OPERATION,
get_std_gate_class, populate_std_gate_map, CONTROLLED_GATE, GATE, INSTRUCTION, OPERATION,
SINGLETON_CONTROLLED_GATE, SINGLETON_GATE, WARNINGS_WARN,
};
use crate::interner::Index;
Expand Down Expand Up @@ -884,24 +884,49 @@ pub fn convert_py_to_operation_type(
Ok(stdgate) => stdgate.extract().ok().unwrap_or_default(),
Err(_) => None,
};
// If the input instruction is a standard gate and a singleton instance
// If the input instruction is a standard gate and a singleton instance,
// we should check for mutable state. A mutable instance should be treated
// as a custom gate not a standard gate because it has custom properties.
//
// In the futuer we can revisit this when we've dropped `duration`, `unit`,
// Controlled gates with non-default control states are also considered
// custom gates even if a standard representation exists for the default
// control state.

// In the future we can revisit this when we've dropped `duration`, `unit`,
// and `condition` from the api as we should own the label in the
// `CircuitInstruction`. The other piece here is for controlled gates there
// is the control state, so for `SingletonControlledGates` we'll still need
// this check.
if standard.is_some() {
let mutable: bool = py_op.getattr(py, intern!(py, "mutable"))?.extract(py)?;
if mutable
// The default ctrl_states are the all 1 state and None.
// These are the only cases where controlled gates can be standard.
let is_default_ctrl_state = || -> PyResult<bool> {
match py_op.getattr(py, intern!(py, "ctrl_state")) {
Ok(c_state) => match c_state.extract::<Option<i32>>(py) {
Ok(c_state_int) => match c_state_int {
Some(c_int) => {
let qubits: u32 =
py_op.getattr(py, intern!(py, "num_qubits"))?.extract(py)?;
Ok(c_int == (2_i32.pow(qubits - 1) - 1))
}
None => Ok(true),
},
Err(_) => Ok(false),
},
Err(_) => Ok(false),
}
};

if (mutable
&& (py_op_bound.is_instance(SINGLETON_GATE.get_bound(py))?
|| py_op_bound.is_instance(SINGLETON_CONTROLLED_GATE.get_bound(py))?)
|| py_op_bound.is_instance(SINGLETON_CONTROLLED_GATE.get_bound(py))?))
|| (py_op_bound.is_instance(CONTROLLED_GATE.get_bound(py))?
&& !is_default_ctrl_state()?)
{
standard = None;
}
}

if let Some(op) = standard {
let base_class = op_type.to_object(py);
populate_std_gate_map(py, op, base_class);
Expand Down
Loading

0 comments on commit 4867e8a

Please sign in to comment.