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"""
|
"""State vector representing quantum state"""
|
||||||
super().__init__(m, *args, **kwargs)
|
super().__init__(m, *args, **kwargs)
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.measurement_result = None
|
||||||
if not self._is_normalized():
|
if not self._is_normalized():
|
||||||
raise TypeError("Not a normalized state vector")
|
raise TypeError("Not a normalized state vector")
|
||||||
|
|
||||||
@ -246,9 +247,10 @@ class State(Vector):
|
|||||||
|
|
||||||
def measure(self):
|
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: 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?
|
If it's measured twice, should it return the same state?
|
||||||
What about if measured twice but in different bases?
|
What about if measured twice but in different bases?
|
||||||
E.g. measure1 -> computation -> A
|
E.g. measure1 -> computation -> A
|
||||||
@ -257,10 +259,13 @@ class State(Vector):
|
|||||||
measure4 -> +/- basis -> should it return B again or random weighted?
|
measure4 -> +/- basis -> should it return B again or random weighted?
|
||||||
:return: binary representation of the measured qubit (e.g. "011")
|
: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))]
|
weights = [self.get_prob(j) for j in range(len(self))]
|
||||||
format_str = self.get_fmt_of_element()
|
format_str = self.get_fmt_of_element()
|
||||||
choices = [format_str.format(i) for i in range(len(weights))]
|
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):
|
def measure_with_op(self, mo):
|
||||||
"""
|
"""
|
||||||
@ -270,15 +275,24 @@ class State(Vector):
|
|||||||
m = mo.on(self) / np.sqrt(mo.get_prob(self))
|
m = mo.on(self) / np.sqrt(mo.get_prob(self))
|
||||||
return State(m)
|
return State(m)
|
||||||
|
|
||||||
def measure_n(self, n=1):
|
def measure_partial(self, qubit_n):
|
||||||
"""measures n times
|
"""Partial measurement of state
|
||||||
TODO: Does this make sense? When a state is measured once, it should "collapse"
|
Measures the n-th qubit with probability sum(a_n),
|
||||||
|
adjusting the probability of the rest of the state
|
||||||
"""
|
"""
|
||||||
measurements = defaultdict(int)
|
max_qubits = int(np.log2(len(self)))
|
||||||
for _ in range(n):
|
if not (0 < qubit_n <= max_qubits):
|
||||||
k = self.measure()
|
raise Exception("Partial measurement of qubit_n must be between 1 and {}".format(max_qubits))
|
||||||
measurements[k] += 1
|
format_str = self.get_fmt_of_element()
|
||||||
return measurements
|
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):
|
def pretty_print(self):
|
||||||
format_str = self.get_fmt_of_element() + " | {}"
|
format_str = self.get_fmt_of_element() + " | {}"
|
||||||
@ -312,6 +326,11 @@ class State(Vector):
|
|||||||
return [x, y, z]
|
return [x, y, z]
|
||||||
|
|
||||||
|
|
||||||
|
def test_measure_partial():
|
||||||
|
state = s("|000>")
|
||||||
|
state.measure_partial(2)
|
||||||
|
|
||||||
|
|
||||||
def normalize_state(state_vector: ListOrNdarray):
|
def normalize_state(state_vector: ListOrNdarray):
|
||||||
"""Normalize a state by dividing by the square root of sum of the squares of states"""
|
"""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))
|
norm_coef = np.sqrt(np.sum(np.array(state_vector) ** 2))
|
||||||
@ -923,16 +942,6 @@ def test_to_from_angles():
|
|||||||
assert s == qbit
|
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):
|
def naive_load_test(N):
|
||||||
import os
|
import os
|
||||||
import psutil
|
import psutil
|
||||||
@ -1154,6 +1163,7 @@ def test_quantum_processor():
|
|||||||
|
|
||||||
def test_light():
|
def test_light():
|
||||||
# TODO: Are these measurement operators the correct way to represent hor/ver/diag filter?
|
# 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')
|
hor_filter = MeasurementOperator.create_from_prob(Matrix(_0.m), name='h')
|
||||||
diag_filter = MeasurementOperator.create_from_prob(Matrix(_p.m), name='d')
|
diag_filter = MeasurementOperator.create_from_prob(Matrix(_p.m), name='d')
|
||||||
ver_filter = MeasurementOperator.create_from_prob(Matrix(_1.m), name='v')
|
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]])
|
qc = QuantumCircuit(1, initial_steps=[[random_light]])
|
||||||
|
|
||||||
# add three filters as operators
|
# add three filters as operators
|
||||||
|
# qc.add_row([hor_filter, ver_filter])
|
||||||
qc.add_row([hor_filter, diag_filter, ver_filter])
|
qc.add_row([hor_filter, diag_filter, ver_filter])
|
||||||
qc.print()
|
qc.print()
|
||||||
qp = QuantumProcessor(qc)
|
qp = QuantumProcessor(qc)
|
||||||
@ -1173,6 +1184,7 @@ def test_light():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test()
|
# test()
|
||||||
test_quantum_processor()
|
# test_quantum_processor()
|
||||||
# test_light()
|
# test_light()
|
||||||
|
test_measure_partial()
|
||||||
|
Loading…
Reference in New Issue
Block a user