partial measurement half-implemented
This commit is contained in:
parent
14bee6764a
commit
aa06605f6c
@ -140,6 +140,7 @@ class State(Vector):
|
||||
"""State vector representing quantum state"""
|
||||
super().__init__(m, *args, **kwargs)
|
||||
self.name = name
|
||||
self.measurement_result = None
|
||||
if not self._is_normalized():
|
||||
raise TypeError("Not a normalized state vector")
|
||||
|
||||
@ -246,9 +247,10 @@ class State(Vector):
|
||||
|
||||
def measure(self):
|
||||
"""
|
||||
Measures in the computational basis
|
||||
Measures in the computational basis.
|
||||
Irreversable operation. Measuring again will result in the same result
|
||||
TODO: Generalize the method so it takes a basis
|
||||
TODO: Should we memoize the result? Should we memoize per basis?
|
||||
TODO: Should we memoize per basis?
|
||||
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
|
||||
@ -257,10 +259,13 @@ class State(Vector):
|
||||
measure4 -> +/- basis -> should it return B again or random weighted?
|
||||
:return: binary representation of the measured qubit (e.g. "011")
|
||||
"""
|
||||
if self.measurement_result:
|
||||
return self.measurement_result
|
||||
weights = [self.get_prob(j) for j in range(len(self))]
|
||||
format_str = self.get_fmt_of_element()
|
||||
choices = [format_str.format(i) for i in range(len(weights))]
|
||||
return random.choices(choices, weights)[0]
|
||||
self.measurement_result = random.choices(choices, weights)[0]
|
||||
return self.measurement_result
|
||||
|
||||
def measure_with_op(self, mo):
|
||||
"""
|
||||
@ -270,15 +275,24 @@ class State(Vector):
|
||||
m = mo.on(self) / np.sqrt(mo.get_prob(self))
|
||||
return State(m)
|
||||
|
||||
def measure_n(self, n=1):
|
||||
"""measures n times
|
||||
TODO: Does this make sense? When a state is measured once, it should "collapse"
|
||||
def measure_partial(self, qubit_n):
|
||||
"""Partial measurement of state
|
||||
Measures the n-th qubit with probability sum(a_n),
|
||||
adjusting the probability of the rest of the state
|
||||
"""
|
||||
measurements = defaultdict(int)
|
||||
for _ in range(n):
|
||||
k = self.measure()
|
||||
measurements[k] += 1
|
||||
return measurements
|
||||
max_qubits = int(np.log2(len(self)))
|
||||
if not (0 < qubit_n <= max_qubits):
|
||||
raise Exception("Partial measurement of qubit_n must be between 1 and {}".format(max_qubits))
|
||||
format_str = self.get_fmt_of_element()
|
||||
bin_repr = [format_str.format(i) for i in range(len(self))]
|
||||
partial_measurement_of_qbit = [int(b[qubit_n - 1]) for b in bin_repr]
|
||||
indexes_for_p_0 = [i for i, index in enumerate(partial_measurement_of_qbit) if index==0]
|
||||
weights_0 = [self.get_prob(j) for j in indexes_for_p_0]
|
||||
choices_0 = [format_str.format(i) for i in indexes_for_p_0]
|
||||
measurement_result = random.choices(choices_0, weights_0)[0]
|
||||
# TODO: collapse the state and change the probabilities of the rest
|
||||
# https://www.youtube.com/watch?v=MG_9JWsrKtM&list=PL1826E60FD05B44E4&index=16
|
||||
return measurement_result
|
||||
|
||||
def pretty_print(self):
|
||||
format_str = self.get_fmt_of_element() + " | {}"
|
||||
@ -312,6 +326,11 @@ class State(Vector):
|
||||
return [x, y, z]
|
||||
|
||||
|
||||
def test_measure_partial():
|
||||
state = s("|000>")
|
||||
state.measure_partial(2)
|
||||
|
||||
|
||||
def normalize_state(state_vector: ListOrNdarray):
|
||||
"""Normalize a state by dividing by the square root of sum of the squares of states"""
|
||||
norm_coef = np.sqrt(np.sum(np.array(state_vector) ** 2))
|
||||
@ -923,16 +942,6 @@ def test_to_from_angles():
|
||||
assert s == qbit
|
||||
|
||||
|
||||
def test_measure_n():
|
||||
qq = State([
|
||||
[0.5],
|
||||
[0.5],
|
||||
[0.5],
|
||||
[0.5],
|
||||
])
|
||||
qq.measure_n(100)
|
||||
|
||||
|
||||
def naive_load_test(N):
|
||||
import os
|
||||
import psutil
|
||||
@ -1154,6 +1163,7 @@ def test_quantum_processor():
|
||||
|
||||
def test_light():
|
||||
# TODO: Are these measurement operators the correct way to represent hor/ver/diag filter?
|
||||
# No, becuase they are not unitaries
|
||||
hor_filter = MeasurementOperator.create_from_prob(Matrix(_0.m), name='h')
|
||||
diag_filter = MeasurementOperator.create_from_prob(Matrix(_p.m), name='d')
|
||||
ver_filter = MeasurementOperator.create_from_prob(Matrix(_1.m), name='v')
|
||||
@ -1164,6 +1174,7 @@ def test_light():
|
||||
qc = QuantumCircuit(1, initial_steps=[[random_light]])
|
||||
|
||||
# add three filters as operators
|
||||
# qc.add_row([hor_filter, ver_filter])
|
||||
qc.add_row([hor_filter, diag_filter, ver_filter])
|
||||
qc.print()
|
||||
qp = QuantumProcessor(qc)
|
||||
@ -1173,6 +1184,7 @@ def test_light():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
||||
test_quantum_processor()
|
||||
# test()
|
||||
# test_quantum_processor()
|
||||
# test_light()
|
||||
test_measure_partial()
|
||||
|
Loading…
Reference in New Issue
Block a user