def test_operations_as_set(): q = QubitPlaceholder.register(6) term_1 = PauliTerm("Z", q[0], 1.0) * PauliTerm("Z", q[1], 1.0) * PauliTerm( "X", q[5], 5) term_2 = PauliTerm("X", q[5], 5) * PauliTerm("Z", q[0], 1.0) * PauliTerm( "Z", q[1], 1.0) assert term_1.operations_as_set() == term_2.operations_as_set()
def get_calibration_program(observable: PauliTerm, noisy_program: Program = None, active_reset: bool = False) -> Program: """ Program required for calibrating the given observable. :param observable: observable to calibrate :param noisy_program: a program with readout and gate noise defined; only useful for QVM :param active_reset: whether or not to begin the program by actively resetting. If true, execution of each of the returned programs in a loop on the QPU will generally be faster. :return: Program performing the calibration """ calibr_prog = Program() if active_reset: calibr_prog += RESET() # Inherit any noisy attributes from noisy_program, including gate definitions # and applications which can be handy in simulating noisy channels if noisy_program is not None: # Inherit readout error instructions from main Program readout_povm_instruction = [i for i in noisy_program.out().split('\n') if 'PRAGMA READOUT-POVM' in i] calibr_prog += readout_povm_instruction # Inherit any definitions of noisy gates from main Program kraus_instructions = [i for i in noisy_program.out().split('\n') if 'PRAGMA ADD-KRAUS' in i] calibr_prog += kraus_instructions # Prepare the +1 eigenstate for the out operator for q, op in observable.operations_as_set(): calibr_prog += _one_q_pauli_prep(label=op, index=0, qubit=q) # Measure the out operator in this state for q, op in observable.operations_as_set(): calibr_prog += _local_pauli_eig_meas(op, q) return calibr_prog
def prepare_random_prod_pauli_eigenstate(pauli_term: PauliTerm): opset = pauli_term.operations_as_set() prog = Program() s = ''.join([ random_local_pauli_eig_prep(prog, op, qubit) for (qubit, op) in opset ]) return prog
def prepare_prod_pauli_eigenstate(pauli_term: PauliTerm): """Returns a circuit to prepare a +1 eigenstate of the Pauli operator described in PauliTerm. :param pauli_term: The PauliTerm whose eigenstate we will prepare. :return: A program corresponding to the correct rotation into the eigenbasis for pauli_term.""" opset = pauli_term.operations_as_set() prog = Program() for (qubit, op) in opset: prog += local_pauli_eig_prep(op, qubit) return prog
def apply_clifford_to_pauli(self, clifford: Program, pauli_in: PauliTerm) -> PauliTerm: r""" Given a circuit that consists only of elements of the Clifford group, return its action on a PauliTerm. In particular, for Clifford C, and Pauli P, this returns the PauliTerm representing CPC^{\dagger}. :param clifford: A Program that consists only of Clifford operations. :param pauli_in: A PauliTerm to be acted on by clifford via conjugation. :return: A PauliTerm corresponding to clifford * pauli_in * clifford^{\dagger} """ # do nothing if `pauli_in` is the identity if is_identity(pauli_in): return pauli_in indices_and_terms = list(zip(*list(pauli_in.operations_as_set()))) payload = ConjugateByCliffordRequest( clifford=clifford.out(), pauli=rpcq.messages.PauliTerm(indices=list(indices_and_terms[0]), symbols=list(indices_and_terms[1])), ) response: ConjugateByCliffordResponse = self.client.call( "conjugate_pauli_by_clifford", payload) phase_factor, paulis = response.phase, response.pauli pauli_out = PauliTerm("I", 0, 1.0j**phase_factor) clifford_qubits = clifford.get_qubits() pauli_qubits = pauli_in.get_qubits() all_qubits = sorted( set(cast(List[int], pauli_qubits)).union(set(cast(List[int], clifford_qubits)))) # The returned pauli will have specified its value on all_qubits, sorted by index. # This is maximal set of qubits that can be affected by this conjugation. for i, pauli in enumerate(paulis): pauli_out = cast(PauliTerm, pauli_out * PauliTerm(pauli, all_qubits[i])) return cast(PauliTerm, pauli_out * pauli_in.coefficient)
def test_operations_as_set(): term_1 = PauliTerm("Z", 0, 1.0) * PauliTerm("Z", 1, 1.0) * PauliTerm("X", 5, 5) term_2 = PauliTerm("X", 5, 5) * PauliTerm("Z", 0, 1.0) * PauliTerm("Z", 1, 1.0) assert term_1.operations_as_set() == term_2.operations_as_set()
def prepare_all_prod_pauli_eigenstates(pauli_term: PauliTerm): opset = pauli_term.operations_as_set() prod_preps = itertools.product( *[local_pauli_eigs_prep(op, qubit) for (qubit, op) in opset]) return [Program().inst(list(prod)) for prod in prod_preps]
def measure_prod_pauli_eigenstate(pauli_term: PauliTerm): opset = pauli_term.operations_as_set() prog = Program() for (qubit, op) in opset: prog += local_pauli_eig_meas(op, qubit) return prog
def measure_prod_pauli_eigenstate(prog: Program, pauli_term: PauliTerm): opset = pauli_term.operations_as_set() for (idx, op) in opset: local_pauli_eig_meas(prog, op, idx) return prog