def decompose_clifford(clifford): """Decompose a Clifford operator into a QuantumCircuit. Args: clifford (Clifford): a clifford operator. Return: QuantumCircuit: a circuit implementation of the Clifford. """ # Compose a circuit which we will convert to an instruction circuit = QuantumCircuit(clifford.num_qubits, name=str(clifford)) # Make a copy of Clifford as we are going to do row reduction to # reduce it to an identity clifford_cpy = clifford.copy() for i in range(clifford.num_qubits): # put a 1 one into position by permuting and using Hadamards(i,i) _set_qubit_x_true(clifford_cpy, circuit, i) # make all entries in row i except ith equal to 0 # by using phase gate and CNOTS _set_row_x_zero(clifford_cpy, circuit, i) # treat Zs _set_row_z_zero(clifford_cpy, circuit, i) for i in range(clifford.num_qubits): if clifford_cpy.destabilizer.phase[i]: _append_z(clifford_cpy, i) circuit.z(i) if clifford_cpy.stabilizer.phase[i]: _append_x(clifford_cpy, i) circuit.x(i) # Next we invert the circuit to undo the row reduction and return the # result as a gate instruction return circuit.inverse()
def reset(self, qargs=None): """Reset state or subsystems to the 0-state. Args: qargs (list or None): subsystems to reset, if None all subsystems will be reset to their 0-state (Default: None). Returns: StabilizerState: the reset state. Additional Information: If all subsystems are reset this will return the ground state on all subsystems. If only some subsystems are reset this function will perform a measurement on those subsystems and evolve the subsystems so that the collapsed post-measurement states are rotated to the 0-state. The RNG seed for this sampling can be set using the :meth:`seed` method. """ # Resetting all qubits does not require sampling or RNG if qargs is None: return StabilizerState( Clifford(np.eye(2 * self.clifford.num_qubits))) randbits = self._rng.integers(2, size=len(qargs)) ret = self.copy() for bit, qubit in enumerate(qargs): # Apply measurement and get classical outcome outcome = ret._measure_and_update(qubit, randbits[bit]) # Use the outcome to apply X gate to any qubits left in the # |1> state after measure, then discard outcome. if outcome == 1: _append_x(ret.clifford, qubit) return ret
def decompose_clifford_greedy(clifford): """Decompose a Clifford operator into a QuantumCircuit. Args: clifford (Clifford): a clifford operator. Return: QuantumCircuit: a circuit implementation of the Clifford. Raises: QiskitError: if symplectic Gaussian elimination fails. """ num_qubits = clifford.num_qubits circ = QuantumCircuit(num_qubits, name=str(clifford)) qubit_list = list(range(num_qubits)) clifford_cpy = clifford.copy() # Reducing the original Clifford to identity # via symplectic Gaussian elimination while len(qubit_list) > 0: clifford_cpy_inv = clifford_cpy.adjoint() list_greedy_cost = [] for qubit in qubit_list: cliff_ox = clifford_cpy.copy() _append_x(cliff_ox, qubit) cliff_ox = cliff_ox.compose(clifford_cpy_inv) cliff_oz = clifford_cpy.copy() _append_z(cliff_oz, qubit) cliff_oz = cliff_oz.compose(clifford_cpy_inv) list_pairs = [] pauli_count = 0 # Compute the CNOT cost in order to find the qubit with the minimal cost for i in qubit_list: typeq = _from_pair_cliffs_to_type(cliff_ox, cliff_oz, i) list_pairs.append(typeq) pauli_count += 1 cost = _compute_greedy_cost(list_pairs) list_greedy_cost.append([cost, qubit]) _, min_qubit = (sorted(list_greedy_cost))[0] # Gaussian elimination step for the qubit with minimal CNOT cost cliff_ox = clifford_cpy.copy() _append_x(cliff_ox, min_qubit) cliff_ox = cliff_ox.compose(clifford_cpy_inv) cliff_oz = clifford_cpy.copy() _append_z(cliff_oz, min_qubit) cliff_oz = cliff_oz.compose(clifford_cpy_inv) # Compute the decoupling operator of cliff_ox and cliff_oz decouple_circ, decouple_cliff = _calc_decoupling( cliff_ox, cliff_oz, qubit_list, min_qubit, num_qubits) circ = circ.compose(decouple_circ) # Now the clifford acts trivially on min_qubit clifford_cpy = decouple_cliff.adjoint().compose(clifford_cpy) qubit_list.remove(min_qubit) # Add the phases (Pauli gates) to the Clifford circuit for qubit in range(num_qubits): stab = clifford_cpy.stabilizer.phase[qubit] destab = clifford_cpy.destabilizer.phase[qubit] if destab and stab: circ.y(qubit) elif not destab and stab: circ.x(qubit) elif destab and not stab: circ.z(qubit) return circ