Skip to content

Commit

Permalink
wrote an exhaustive test for ladder operator measurement and fixed al…
Browse files Browse the repository at this point in the history
…l appearing bugs
  • Loading branch information
positr0nium committed Nov 7, 2024
1 parent 8fe7a12 commit 6fbc1fc
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 60 deletions.
46 changes: 23 additions & 23 deletions src/qrisp/alg_primitives/logic_synthesis/truth_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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):
Expand Down
50 changes: 17 additions & 33 deletions src/qrisp/operators/qubit/measurement.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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):
"""
Expand All @@ -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)


Expand Down
2 changes: 1 addition & 1 deletion src/qrisp/operators/qubit/pauli_measurement.py
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand Down
8 changes: 5 additions & 3 deletions src/qrisp/operators/qubit/qubit_term.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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):

Expand Down
59 changes: 59 additions & 0 deletions tests/hamiltonian_tests/test_measurement_method.py
Original file line number Diff line number Diff line change
@@ -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])





0 comments on commit 6fbc1fc

Please sign in to comment.