def test_sampler_expectation_value() -> None: c = Circuit(2) c.H(0) c.CX(0, 1) op = QubitPauliOperator({ QubitPauliString({ Qubit(0): Pauli.Z, Qubit(1): Pauli.Z }): 1.0, QubitPauliString({ Qubit(0): Pauli.X, Qubit(1): Pauli.X }): 0.3, QubitPauliString({ Qubit(0): Pauli.Z, Qubit(1): Pauli.Y }): 0.8j, QubitPauliString({Qubit(0): Pauli.Y}): -0.4j, }) b = MySampler() b.compile_circuit(c) expectation = get_operator_expectation_value(c, op, b, n_shots=2000, seed=0) assert (np.real(expectation), np.imag(expectation)) == pytest.approx( (1.3, 0.0), abs=0.1)
def test_expectation_value() -> None: c = Circuit(2) c.H(0) c.CX(0, 1) op = QubitPauliOperator({ QubitPauliString({ Qubit(0): Pauli.Z, Qubit(1): Pauli.Z }): 1.0, QubitPauliString({ Qubit(0): Pauli.X, Qubit(1): Pauli.X }): 0.3, QubitPauliString({ Qubit(0): Pauli.Z, Qubit(1): Pauli.Y }): 0.8j, QubitPauliString({Qubit(0): Pauli.Y}): -0.4j, }) b = MyBackend() b.compile_circuit(c) assert get_operator_expectation_value(c, op, b) == pytest.approx(1.3)
def test_aer_placed_expectation() -> None: # bug TKET-695 n_qbs = 3 c = Circuit(n_qbs, n_qbs) c.X(0) c.CX(0, 2) c.CX(1, 2) c.H(1) # c.measure_all() b = AerBackend() operator = QubitPauliOperator({ QubitPauliString(Qubit(0), Pauli.Z): 1.0, QubitPauliString(Qubit(1), Pauli.X): 0.5, }) assert b.get_operator_expectation_value(c, operator) == (-0.5 + 0j) with open(os.path.join(sys.path[0], "ibmqx2_properties.pickle"), "rb") as f: properties = pickle.load(f) noise_model = NoiseModel.from_backend(properties) noise_b = AerBackend(noise_model) with pytest.raises(RuntimeError) as errorinfo: noise_b.get_operator_expectation_value(c, operator) assert "not supported with noise model" in str(errorinfo.value) c.rename_units({Qubit(1): Qubit("node", 1)}) with pytest.raises(ValueError) as errorinfoCirc: b.get_operator_expectation_value(c, operator) assert "default register Qubits" in str(errorinfoCirc.value)
def tk_to_mycircuit(tkc: Circuit) -> MyCircuit: """Convert a pytket Circuit to a MyCircuit object. Supports Rz, Rx, Ry, and ZZMax gates. :param tkc: The Circuit to convert :type tkc: Circuit :return: An equivalent MyCircuit object :rtype: MyCircuit """ circ = MyCircuit(tkc.qubits) for command in tkc: optype = command.op.type if optype == OpType.Rx: circ.add_gate(QubitPauliString(command.args[0], Pauli.X), np.pi * command.op.params[0]) elif optype == OpType.Ry: circ.add_gate(QubitPauliString(command.args[0], Pauli.Y), np.pi * command.op.params[0]) elif optype == OpType.Rz: circ.add_gate(QubitPauliString(command.args[0], Pauli.Z), np.pi * command.op.params[0]) elif optype == OpType.ZZMax: circ.add_gate(QubitPauliString(command.args, [Pauli.Z, Pauli.Z]), np.pi * 0.5) else: raise ValueError("Cannot convert optype to MyCircuit: ", optype) return circ
def test_hadamard() -> None: c = MyCircuit([Qubit(0), Qubit(1)], [Bit(0), Bit(1)]) c.add_gate(QubitPauliString(Qubit(0), Pauli.Z), np.pi / 2) c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi / 2) c.add_gate(QubitPauliString(Qubit(0), Pauli.Z), np.pi / 2) c.add_measure(Qubit(0), Bit(0)) counts = get_counts(c, n_shots=100, seed=11) assert counts == {(0, 0): 50, (0, 1): 50}
def test_operator_statevector(qvm: None, quilc: None) -> None: c = Circuit(2, 2) c.Rz(0.5, 0) b = ForestStateBackend() zi = QubitPauliString(Qubit(0), Pauli.Z) iz = QubitPauliString(Qubit(1), Pauli.Z) op = QubitPauliOperator({zi: 0.3, iz: -0.1}) assert get_operator_expectation_value(c, op, b) == pytest.approx(0.2) c.X(0) assert get_operator_expectation_value(c, op, b) == pytest.approx(-0.4)
def test_basic_ordering() -> None: # Test that final bit readouts are in the intended order (DLO) c = MyCircuit([Qubit(0)], [Bit(0), Bit(1), Bit(2)]) c.add_measure(Qubit(0), Bit(0)) c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi) c.add_measure(Qubit(0), Bit(2)) c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi / 2) c.add_measure(Qubit(0), Bit(1)) counts = get_counts(c, n_shots=100, seed=11) assert counts == {(1, 0, 0): 50, (1, 1, 0): 50}
def test_overwrite() -> None: # Test that classical data is overwritten by later measurements appropriately c = MyCircuit([Qubit(0)], [Bit(0), Bit(1)]) c.add_measure(Qubit(0), Bit(0)) c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi) c.add_measure(Qubit(0), Bit(0)) c.add_measure(Qubit(0), Bit(1)) c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi / 2) c.add_measure(Qubit(0), Bit(1)) counts = get_counts(c, n_shots=100, seed=11) assert counts == {(0, 1): 50, (1, 1): 50}
def test_operator_sim(qvm: None, quilc: None) -> None: c = Circuit(2, 2) c.Rz(0.5, 0) b = ForestBackend("9q-square") zi = QubitPauliString(Qubit(0), Pauli.Z) iz = QubitPauliString(Qubit(1), Pauli.Z) op = QubitPauliOperator({zi: 0.3, iz: -0.1}) assert get_operator_expectation_value(c, op, b, 10) == pytest.approx(0.2, rel=0.001) c.X(0) assert get_operator_expectation_value(c, op, b, 10) == pytest.approx(-0.4, rel=0.001)
def test_conditional_rotation() -> None: c = MyCircuit([Qubit(0)], [Bit(0), Bit(1)]) # Randomise qubit state c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi / 2) c.add_measure(Qubit(0), Bit(0)) # Correct qubit state to |1> - this should only happen when the measurement was 0 c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi, {Bit(0): 0, Bit(1): 0}) # Randomise final measurement - this should never happen c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi / 2, {Bit(0): 0, Bit(1): 1}) c.add_measure(Qubit(0), Bit(1)) counts = get_counts(c, n_shots=100, seed=11) assert counts == {(1, 0): 50, (1, 1): 50}
def test_expectation() -> None: b = BraketBackend(local=True) assert b.supports_expectation c = Circuit(2, 2) c.Rz(0.5, 0) zi = QubitPauliString(Qubit(0), Pauli.Z) iz = QubitPauliString(Qubit(1), Pauli.Z) op = QubitPauliOperator({zi: 0.3, iz: -0.1}) assert get_pauli_expectation_value(c, zi, b) == 1 assert get_operator_expectation_value(c, op, b) == pytest.approx(0.2) c.X(0) assert get_pauli_expectation_value(c, zi, b) == -1 assert get_operator_expectation_value(c, op, b) == pytest.approx(-0.4)
def test_simulator() -> None: b = BraketBackend( s3_bucket=S3_BUCKET, s3_folder=S3_FOLDER, device_type="quantum-simulator", provider="amazon", device="sv1", ) assert b.supports_shots c = Circuit(2).H(0).CX(0, 1) b.compile_circuit(c) n_shots = 100 h0, h1 = b.process_circuits([c, c], n_shots) res0 = b.get_result(h0) readouts = res0.get_shots() assert all(readouts[i][0] == readouts[i][1] for i in range(n_shots)) res1 = b.get_result(h1) counts = res1.get_counts() assert len(counts) <= 2 assert sum(counts.values()) == n_shots zi = QubitPauliString(Qubit(0), Pauli.Z) assert b.get_pauli_expectation_value( c, zi, poll_timeout_seconds=60, poll_interval_seconds=1 ) == pytest.approx(0) # Circuit with unused qubits c = Circuit(3).H(1).CX(1, 2) b.compile_circuit(c) h = b.process_circuit(c, 1) res = b.get_result(h) readout = res.get_shots()[0] assert readout[1] == readout[2]
def get_pauli_expectation_value( self, state_circuit: Circuit, pauli: QubitPauliString, valid_check: bool = True, ) -> complex: """Calculates the expectation value of the given circuit using the built-in ProjectQ functionality :param state_circuit: Circuit that generates the desired state :math:`\\left|\\psi\\right>`. :type state_circuit: Circuit :param pauli: Pauli operator :type pauli: QubitPauliString :param valid_check: Explicitly check that the circuit satisfies all required predicates to run on the backend. Defaults to True :type valid_check: bool, optional :return: :math:`\\left<\\psi | P | \\psi \\right>` :rtype: complex """ pauli_tuple = tuple( (_default_q_index(q), p.name) for q, p in pauli.to_dict().items()) return self._expectation_value(state_circuit, projectq.ops.QubitOperator(pauli_tuple), valid_check)
def _gen_PauliTerm(self, term: QubitPauliString, coeff: complex = 1.0) -> PauliTerm: pauli_term = ID() * coeff for q, p in term.to_dict().items(): pauli_term *= PauliTerm(p.name, _default_q_index(q)) return pauli_term # type: ignore
def test_operator() -> None: c = circuit_gen() b = ProjectQBackend() zz = QubitPauliOperator( {QubitPauliString([Qubit(0), Qubit(1)], [Pauli.Z, Pauli.Z]): 1.0}) assert np.isclose(get_operator_expectation_value(c, zz, b), complex(1.0)) c.X(0) assert np.isclose(get_operator_expectation_value(c, zz, b), complex(-1.0))
def qps_from_openfermion(paulis: QubitOperator) -> QubitPauliString: """ Utility function to translate from openfermion format to a QubitPauliString """ qlist = [] plist = [] for q, p in paulis: qlist.append(Qubit(q)) plist.append(pauli_sym[p]) return QubitPauliString(qlist, plist)
def test_pauli() -> None: c = Circuit(2) c.Rz(0.5, 0) b = ProjectQBackend() zi = QubitPauliString({Qubit(0): Pauli.Z}) assert np.isclose(get_pauli_expectation_value(c, zi, b), complex(1)) c.X(0) assert np.isclose(get_pauli_expectation_value(c, zi, b), complex(-1))
def test_pauli_statevector(qvm: None, quilc: None) -> None: c = Circuit(2, 2) c.Rz(0.5, 0) b = ForestStateBackend() zi = QubitPauliString(Qubit(0), Pauli.Z) assert get_pauli_expectation_value(c, zi, b) == 1 c.X(0) assert get_pauli_expectation_value(c, zi, b) == -1
def qps_from_openfermion(paulis): # translate from openfermion format to a QubitPauliString qlist = [] plist = [] for q, p in paulis: qlist.append(Qubit(q)) plist.append(pauli_sym[p]) return QubitPauliString(qlist, plist)
def test_operator() -> None: for b in [AerBackend(), AerStateBackend()]: c = circuit_gen() zz = QubitPauliOperator( {QubitPauliString([Qubit(0), Qubit(1)], [Pauli.Z, Pauli.Z]): 1.0}) assert cmath.isclose(get_operator_expectation_value(c, zz, b), 1.0) c.X(0) assert cmath.isclose(get_operator_expectation_value(c, zz, b), -1.0)
def test_device() -> None: c = circuit_gen(False) b = IBMQBackend("ibmq_santiago", hub="ibm-q", group="open", project="main") assert b._max_per_job == 75 operator = QubitPauliOperator({ QubitPauliString(Qubit(0), Pauli.Z): 1.0, QubitPauliString(Qubit(0), Pauli.X): 0.5, }) val = get_operator_expectation_value(c, operator, b, 8000) print(val) c1 = circuit_gen(True) c2 = circuit_gen(True) b.compile_circuit(c1) b.compile_circuit(c2) print(b.get_shots(c1, n_shots=10)) print(b.get_shots(c2, n_shots=10))
def test_pauli() -> None: for b in [AerBackend(), AerStateBackend()]: c = Circuit(2) c.Rz(0.5, 0) b.compile_circuit(c) zi = QubitPauliString(Qubit(0), Pauli.Z) assert cmath.isclose(get_pauli_expectation_value(c, zi, b), 1) c.X(0) assert cmath.isclose(get_pauli_expectation_value(c, zi, b), -1)
def test_pauli_statevector() -> None: c = Circuit(2) c.Rz(0.5, 0) Transform.OptimisePostRouting().apply(c) b = AerStateBackend() zi = QubitPauliString(Qubit(0), Pauli.Z) assert get_pauli_expectation_value(c, zi, b) == 1 c.X(0) assert get_pauli_expectation_value(c, zi, b) == -1
def _sparse_to_qiskit_pauli(pauli: QubitPauliString, n_qubits: int) -> qk_Pauli: x = [False] * n_qubits z = [False] * n_qubits for q, p in pauli.to_dict().items(): i = _default_q_index(q) z[i] = p in (Pauli.Z, Pauli.Y) x[i] = p in (Pauli.X, Pauli.Y) return qk_Pauli((z, x))
def add_operator_term(circuit: Circuit, term: QubitPauliString, angle: float): qubits = [] for q, p in term.to_dict().items(): if p != Pauli.I: qubits.append(q) if p == Pauli.X: circuit.H(q) elif p == Pauli.Y: circuit.V(q) for i in range(len(qubits) - 1): circuit.CX(i, i + 1) circuit.Rz(angle, len(qubits) - 1) for i in reversed(range(len(qubits) - 1)): circuit.CX(i, i + 1) for q, p in term.to_dict().items(): if p == Pauli.X: circuit.H(q) elif p == Pauli.Y: circuit.Vdg(q)
def test_pauli_sim(qvm: None, quilc: None) -> None: c = Circuit(2, 2) c.Rz(0.5, 0) b = ForestBackend("9q-square") zi = QubitPauliString(Qubit(0), Pauli.Z) energy = get_pauli_expectation_value(c, zi, b, 10) assert abs(energy - 1) < 0.001 c.X(0) energy = get_pauli_expectation_value(c, zi, b, 10) assert abs(energy + 1) < 0.001
def _sparse_to_qiskit_pauli(pauli: QubitPauliString, n_qubits: int) -> qk_Pauli: empty = np.zeros(n_qubits) q_pauli = qk_Pauli(empty, empty) for q, p in pauli.to_dict().items(): i = _default_q_index(q) if p in (Pauli.X, Pauli.Y): q_pauli._x[i] = True if p in (Pauli.Z, Pauli.Y): q_pauli._z[i] = True return q_pauli
def test_pauli_sim() -> None: c = Circuit(2, 2) c.Rz(0.5, 0) Transform.OptimisePostRouting().apply(c) b = AerBackend() zi = QubitPauliString(Qubit(0), Pauli.Z) energy = get_pauli_expectation_value(c, zi, b, 8000) assert abs(energy - 1) < 0.001 c.X(0) energy = get_pauli_expectation_value(c, zi, b, 8000) assert abs(energy + 1) < 0.001
def test_conditional_measurement() -> None: c = MyCircuit([Qubit(0), Qubit(1)], [Bit(0), Bit(1), Bit(2), Bit(3)]) # Get a random number c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi / 2) c.add_measure(Qubit(0), Bit(0)) # If random number is 0 then flip to give |1> # Otherwise, randomly generate |+i> or |-i> c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi / 2) c.add_measure(Qubit(0), Bit(1), {Bit(0): 1}) c.add_gate(QubitPauliString(Qubit(0), Pauli.X), np.pi / 2) # Deterministic if Bit(0) == 0, random if Bit(0) == 1 c.add_measure(Qubit(0), Bit(2)) # Test end-of-circuit conditions by copying Bit(2) to Bit(3) c.add_gate(QubitPauliString(Qubit(1), Pauli.X), np.pi) c.add_measure(Qubit(1), Bit(3), {Bit(2): 1}) counts = get_counts(c, n_shots=10000, seed=11) assert counts[(1, 1, 0, 0)] == pytest.approx(5000, rel=0.02) assert counts[(0, 0, 0, 1)] == pytest.approx(1250, rel=0.02) assert counts[(1, 1, 0, 1)] == pytest.approx(1250, rel=0.02) assert counts[(0, 0, 1, 1)] == pytest.approx(1250, rel=0.02) assert counts[(1, 1, 1, 1)] == pytest.approx(1250, rel=0.02)
def apply_Pauli_rot(self, qps: QubitPauliString, angle: float): """Applies e^{-0.5i * qps * angle} to the state :param qps: Pauli to rotate around :type qps: QubitPauliString :param angle: Angle of rotation in radians :type angle: float """ pauli_tensor = qps.to_sparse_matrix(self._qubits) exponent = -0.5 * angle self._qstate = np.cos(exponent) * self._qstate + 1j * np.sin( exponent) * pauli_tensor.dot(self._qstate)