diff --git a/src/qrisp/alg_primitives/logic_synthesis/truth_tables.py b/src/qrisp/alg_primitives/logic_synthesis/truth_tables.py index 29a2232f..4766f55b 100644 --- a/src/qrisp/alg_primitives/logic_synthesis/truth_tables.py +++ b/src/qrisp/alg_primitives/logic_synthesis/truth_tables.py @@ -339,25 +339,25 @@ def rw_spectrum(f): return np.dot(T(n), f) -def C(f): - size = len(f) +# def C(f): +# size = len(f) - if np.log2(size) != int(np.log2(size)): - raise Exception( - "The given function does not have the length to properly represent " - "a truth table" - ) +# if np.log2(size) != int(np.log2(size)): +# raise Exception( +# "The given function does not have the length to properly represent " +# "a truth table" +# ) - n = int(np.log2(size)) +# n = int(np.log2(size)) - rw_spec = rw_spectrum(f) - sum_ = 0 - for i in range(size): - sum_ += sum(int_as_array(i, n)) * rw_spec[i] ** 2 +# rw_spec = rw_spectrum(f) +# sum_ = 0 +# for i in range(size): +# sum_ += sum(int_as_array(i, n)) * rw_spec[i] ** 2 - sum_ = sum_ / 2 ** (n - 2) +# sum_ = sum_ / 2 ** (n - 2) - return 1 / 2 * (n * size - sum_) +# return 1 / 2 * (n * size - sum_) def NZ(f): @@ -370,17 +370,17 @@ def NZ(f): return sum_ -def D(f): - size = len(f) - if np.log2(size) != int(np.log2(size)): - raise Exception( - "The given function does not have the length to properly represent " - "a truth table" - ) +# def D(f): +# size = len(f) +# if np.log2(size) != int(np.log2(size)): +# raise Exception( +# "The given function does not have the length to properly represent " +# "a truth table" +# ) - n = int(np.log2(size)) +# n = int(np.log2(size)) - return int(n * 2 ** (n - 3) * NZ(f) + C(f)) +# return int(n * 2 ** (n - 3) * NZ(f) + C(f)) def synth_poly(truth_table, column=0, coeff=None): diff --git a/src/qrisp/operators/qubit/measurement.py b/src/qrisp/operators/qubit/measurement.py index 8fd3aac2..df2e34b3 100644 --- a/src/qrisp/operators/qubit/measurement.py +++ b/src/qrisp/operators/qubit/measurement.py @@ -158,6 +158,7 @@ def get_measurement( qubits = [qarg[i] for i in range(circuit.num_qubits())] curr.append(circuit.to_gate(), qubits) + # print(curr.transpile()) res = get_measurement_from_qc(curr.transpile(), list(qarg), backend, meas_shots[index]) results.append(res) @@ -169,35 +170,6 @@ def get_measurement( # Evaluate expectation # -def evaluate_observable(observable: int, x: int): - """ - This method evaluates an observable that is a tensor product of Pauli-:math:`Z` operators - with respect to a measurement outcome. - - A Pauli operator of the form :math:`\prod_{i\in I}Z_i`, for some finite set of indices :math:`I\subset \mathbb N`, - is identified with an integer: - We identify the Pauli operator with the binary string that has ones at positions :math:`i\in I` - and zeros otherwise, and then convert this binary string to an integer. - - Parameters - ---------- - - observable : int - The observable represented as integer. - x : int - The measurement outcome represented as integer. - - Returns - ------- - int - The value of the observable with respect to the measurement outcome. - - """ - - if bin(observable & x).count('1') % 2 == 0: - return 1 - else: - return -1 def evaluate_observable(observable: tuple, x: int): """ @@ -224,20 +196,32 @@ def evaluate_observable(observable: tuple, x: int): """ - z_int, AND_bits, AND_ctrl_state = observable + z_int, AND_bits, AND_ctrl_state, contains_ladder = observable sign_flip = bin(z_int & x).count('1') + from qrisp import bin_rep temp = (x ^ AND_ctrl_state) + # if AND_bits != 0: + # print(bin_rep(AND_ctrl_state, 3)) + # print(bin_rep(AND_bits, 3)) + # print(bin_rep(temp, 3)) + # print(bin_rep(z_int, 3)) + # print("=====") + if contains_ladder: + prefactor = 0.5 + else: + prefactor = 1 if AND_bits == 0: - return (-1)**sign_flip + return prefactor*(-1)**sign_flip - if temp & AND_bits == 0 or AND_bits == 0: - return (-1)**sign_flip/2 + if temp & AND_bits == 0: + return prefactor*(-1)**sign_flip else: return 0 + return (-1)**(sign_flip) diff --git a/src/qrisp/operators/qubit/pauli_measurement.py b/src/qrisp/operators/qubit/pauli_measurement.py index 6e8a06ec..797f78b9 100644 --- a/src/qrisp/operators/qubit/pauli_measurement.py +++ b/src/qrisp/operators/qubit/pauli_measurement.py @@ -152,7 +152,7 @@ def measurement_circuits(self): qc.x(anchor_factor[0]) for j in range(len(ladder_operators)-1): - qc.cx(anchor_factor[0], j) + qc.cx(anchor_factor[0], ladder_operators[j][0]) if len(ladder_operators): if anchor_factor[1] == "A": diff --git a/src/qrisp/operators/qubit/qubit_term.py b/src/qrisp/operators/qubit/qubit_term.py index 164d8e26..801c7e8b 100644 --- a/src/qrisp/operators/qubit/qubit_term.py +++ b/src/qrisp/operators/qubit/qubit_term.py @@ -63,13 +63,13 @@ def serialize(self): if factor_dict[i] in ["X", "Y", "Z"]: z_int |= bit - last_ladder_factor continue elif factor_dict[i] == "A": ctrl_int |= bit - last_ladder_factor + last_ladder_factor = bit pass elif factor_dict[i] == "C": + last_ladder_factor = bit pass elif factor_dict[i] == "P0": pass @@ -82,9 +82,11 @@ def serialize(self): and_int |= bit if last_ladder_factor is not None: + pass and_int ^= last_ladder_factor + z_int ^= last_ladder_factor - return (z_int, and_int, ctrl_int) + return (z_int, and_int, ctrl_int, last_ladder_factor is not None) def to_pauli(self): diff --git a/tests/hamiltonian_tests/test_measurement_method.py b/tests/hamiltonian_tests/test_measurement_method.py new file mode 100644 index 00000000..a00c8949 --- /dev/null +++ b/tests/hamiltonian_tests/test_measurement_method.py @@ -0,0 +1,59 @@ +""" +\******************************************************************************** +* Copyright (c) 2024 the Qrisp authors +* +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0. +* +* This Source Code may also be made available under the following Secondary +* Licenses when the conditions for such availability set forth in the Eclipse +* Public License, v. 2.0 are satisfied: GNU General Public License, version 2 +* with the GNU Classpath Exception which is +* available at https://www.gnu.org/software/classpath/license.html. +* +* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 +********************************************************************************/ +""" + +from qrisp.operators import X, Y, Z, A, C, P0, P1 +from numpy.linalg import norm +from qrisp import * + +def test_measurement_method(): + + def testing_helper(qv): + operator_list = [lambda x : 1, X, Y, Z, A, C, P0, P1] + for O0 in operator_list: + for O1 in operator_list: + for O2 in operator_list: + for O3 in operator_list: + H = O0(0)*O1(1)*O2(2)*O3(3) + if isinstance(H, int): + continue + + print(H) + assert abs(H.get_measurement(qv, precision = 0.001) - H.to_pauli().get_measurement(qv, precision = 0.001)) < 1E-2 + + qv = QuantumVariable(4) + + testing_helper(qv) + + h(qv[0]) + + testing_helper(qv) + + cx(qv[0], qv[1]) + + testing_helper(qv) + + cx(qv[0], qv[2]) + + testing_helper(qv) + + h(qv[0]) + + + + + \ No newline at end of file