sequential measurements are memoized
This commit is contained in:
parent
09d9b78683
commit
08bce98b6d
43
lib.py
43
lib.py
@ -164,6 +164,7 @@ class State(Vector):
|
||||
super().__init__(m, *args, **kwargs)
|
||||
self.name = name
|
||||
self.measurement_result = None
|
||||
self.last_basis = None
|
||||
# TODO: SHOULD WE NORMALIZE?
|
||||
# if not self._is_normalized():
|
||||
# raise TypeError("Not a normalized state vector")
|
||||
@ -287,6 +288,7 @@ class State(Vector):
|
||||
Measures in the computational basis.
|
||||
Irreversable operation. Measuring again will result in the same result
|
||||
TODO: Should we memoize per basis?
|
||||
Currently it's memoized if the basis is the same
|
||||
If it's measured twice, should it return the same state?
|
||||
What about if measured twice but in different bases?
|
||||
E.g. measure1 -> computation -> A
|
||||
@ -297,15 +299,15 @@ class State(Vector):
|
||||
random weighted?
|
||||
:return: binary representation of the measured qubit (e.g. "011")
|
||||
"""
|
||||
# if self.measurement_result:
|
||||
# return self.measurement_result
|
||||
weights, m_ops = [], []
|
||||
if not basis:
|
||||
basis = []
|
||||
for j in range(len(self)):
|
||||
# Default is computational basis
|
||||
e_j = self.get_computational_basis_vector(j)
|
||||
m = MeasurementOperator.create_from_basis(e_j)
|
||||
m_ops.append(m)
|
||||
basis.append(State(e_j))
|
||||
else:
|
||||
assert len(basis) == len(self)
|
||||
for i, e_j in enumerate(basis):
|
||||
@ -314,6 +316,9 @@ class State(Vector):
|
||||
assert e_j.is_orthogonal(basis[0])
|
||||
m_ops.append(MeasurementOperator.create_from_basis(e_j))
|
||||
|
||||
if self.measurement_result and self.last_basis == basis:
|
||||
return self.measurement_result
|
||||
|
||||
for m_op in m_ops:
|
||||
prob = self.get_prob_from_measurement_op(m_op)
|
||||
weights += [prob]
|
||||
@ -327,13 +332,14 @@ class State(Vector):
|
||||
# TODO: This may be wrong
|
||||
# normalize the weights
|
||||
weights = list(np.array(weights) / sum(weights))
|
||||
# assert np.isclose(sum(weights), 1.0)
|
||||
|
||||
format_str = self.get_fmt_of_element()
|
||||
choices = empty_choices + [format_str.format(i) for i in
|
||||
range(len(weights))]
|
||||
weights = empty_weights + weights
|
||||
self.measurement_result = random.choices(choices, weights)[0]
|
||||
|
||||
self.last_basis = basis
|
||||
return self.measurement_result
|
||||
|
||||
def measure_with_op(self, mo):
|
||||
@ -841,7 +847,8 @@ T = lambda phi: Gate([[1, 0],
|
||||
#
|
||||
# Decomposed CNOT :
|
||||
# reverse engineered from
|
||||
# https://quantumcomputing.stackexchange.com/questions/4252/how-to-derive-the-cnot-matrix-for-a-3-qbit-system-where-the-control-target-qbi
|
||||
# https://quantumcomputing.stackexchange.com/questions/4252/how-to-derive-the
|
||||
# -cnot-matrix-for-a-3-qbit-system-where-the-control-target-qbi
|
||||
#
|
||||
# CNOT(q1, I, q2):
|
||||
# |0><0| x I_2 x I_2 + |1><1| x I_2 x X
|
||||
@ -890,7 +897,6 @@ SWAP = Gate([
|
||||
CNOT.on(CNOT.on(CNOT.on(state, [x, y]), [y, x]), [x, y])
|
||||
)
|
||||
|
||||
|
||||
TOFF = Gate([
|
||||
[1, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0],
|
||||
@ -1040,7 +1046,8 @@ def test_partials():
|
||||
assert CNOT.on(CNOT.on(CNOT.on(s("|10>")), which_qbit=[1, 0])) == s("|01>")
|
||||
|
||||
# Test SWAP via 3 successive CNOTs, the 0<->2 are swapped
|
||||
assert CNOT.on(CNOT.on(CNOT.on(s("|100>"), [0, 2]), [2, 0]), [0, 2]) == s("|001>")
|
||||
assert CNOT.on(CNOT.on(CNOT.on(s("|100>"), [0, 2]), [2, 0]), [0, 2]) == s(
|
||||
"|001>")
|
||||
|
||||
# apply on 0, 1 of 3qbit state
|
||||
assert CNOT.on(s("|000>"), which_qbit=[0, 1]) == s("|000>")
|
||||
@ -1085,6 +1092,28 @@ def test_partials():
|
||||
assert TOFF.on(s("|10100>"), which_qbit=[0, 2, 4]) == s("|10101>")
|
||||
|
||||
|
||||
def test_sequential_measurements():
|
||||
st = H.on(s("|0>"))
|
||||
meas1 = st.measure()
|
||||
assert st.measurement_result is not None
|
||||
assert st.last_basis == computational_basis
|
||||
|
||||
# Measuring more times should return the same result
|
||||
for i in range(10):
|
||||
meas2 = st.measure()
|
||||
assert meas2 == meas1
|
||||
|
||||
# Measuring in different basis might not yield the same result
|
||||
meas3 = st.measure(basis=plus_minus_basis)
|
||||
assert st.measurement_result is not None
|
||||
assert st.last_basis == plus_minus_basis
|
||||
|
||||
# But measuring more times should still return the same result
|
||||
for i in range(10):
|
||||
meas4 = st.measure(basis=plus_minus_basis)
|
||||
assert meas4 == meas3
|
||||
|
||||
|
||||
def test():
|
||||
# Test properties of Hilbert vector space
|
||||
# The four postulates of Quantum Mechanics
|
||||
@ -1189,6 +1218,8 @@ def test():
|
||||
# Test measurement operators
|
||||
test_measurement_ops()
|
||||
|
||||
test_sequential_measurements()
|
||||
|
||||
# IV: Compositing | The state space of a composite physical system
|
||||
# is the tensor product of the state spaces
|
||||
# of the component physical systems.
|
||||
|
Loading…
Reference in New Issue
Block a user