diff --git a/06_krisis.py b/06_krisis.py index 1284345..e83eade 100644 --- a/06_krisis.py +++ b/06_krisis.py @@ -1,25 +1,49 @@ -import cirq -from math import pi +import numpy as np +from collections import defaultdict + +from lib_q_computer_math import State, QuantumCircuit, QuantumProcessor, C, H, x, _, _0, _1 -def superdense(): - # Pick a qubit. - q0 = cirq.GridQubit(0, 0) +def from_angles_1(theta, phi): + theta, phi = State._normalize_angles(theta, phi) + m0 = -np.sin(theta / 2) + m1 = np.cos(theta / 2) * np.power(np.e, (1j * phi)) + m = m0 * _0 + m1 * _1 + return State(m.m) - # Create a circuit - circuit = cirq.Circuit( - cirq.rx(pi/8).on(q0), - cirq.rz(pi/2).on(q0), - cirq.measure(q0, key='q0'), - ) - print("Circuit:") - print(circuit) - simulator = cirq.Simulator() - result = simulator.run(circuit, repetitions=100) - print("Results:") - print(result) +def krisi(q2func, iterations=100, sample_count=1): + all_samples = defaultdict(int) + for i in range(iterations): + # print("Running iteration {}".format(i)) + theta = round(np.random.uniform(0, np.pi), 3) + phi = round(np.random.uniform(0, 2 * np.pi), 3) + # print("theta: {:.2f} ({:.2f} deg) | phi: {:.2f} ({:.2f} deg)".format( + # theta, np.rad2deg(theta), + # phi, np.rad2deg(phi))) + q1 = State.from_angles(theta, phi) + q2 = q2func(theta, phi) + + qc = QuantumCircuit(2, [[q1, q2], ]) + qc.add_row([C, H]) + qc.add_row([x, _]) + qp = QuantumProcessor(qc) + this_samples = qp.get_sample(sample_count) + for k, v in this_samples.items(): + all_samples[k] += v + print("------------- ALL SAMPLES for {}".format(q2func.__name__)) + for k, v in sorted(all_samples.items(), key=lambda x: x[0]): + print("{}: {}".format(k, v)) + print("==============================================") + + +def krisi_0(): + krisi(q2func=State.from_angles) + + +def krisi_1(): + krisi(q2func=from_angles_1) if __name__ == "__main__": - superdense() + krisi_0() diff --git a/lib_q_computer_math.py b/lib_q_computer_math.py index 474704c..800066b 100644 --- a/lib_q_computer_math.py +++ b/lib_q_computer_math.py @@ -129,8 +129,17 @@ class State(Vector): def _is_normalized(self): return np.isclose(np.sum(np.abs(self.m ** 2)), 1.0) + @staticmethod + def _normalize_angles(theta, phi): + # theta is between [0 and pi] + theta = theta.real % np.pi if theta.real != np.pi else theta.real + # phi is between (0 and 2*pi] + phi = phi.real % (2 * np.pi) + return theta, phi + @classmethod def from_angles(cls, theta, phi): + theta, phi = cls._normalize_angles(theta, phi) m0 = np.cos(theta / 2) m1 = np.sin(theta / 2) * np.power(np.e, (1j * phi)) m = m0 * _0 + m1 * _1 @@ -147,8 +156,9 @@ class State(Vector): theta += np.pi assert 0 <= theta <= np.pi - div = np.sin(theta/2) + div = np.sin(theta / 2) if div == 0: + # here is doesn't matter what phi is as phase at the poles is arbitrary phi = 0 else: exp = m1 / div @@ -159,17 +169,18 @@ class State(Vector): return theta, phi def __repr__(self): - if self.name: - return '|{}>'.format(self.name) - for well_known_state in well_known_states: - if self == well_known_state: - return repr(well_known_state) - for used_state in UNIVERSE_STATES: - if self.m == used_state: - return repr(used_state) - next_state_sub = ''.join([REPR_MATH_SUBSCRIPT_NUMBERS[int(d)] for d in str(len(UNIVERSE_STATES))]) - state_name = '|{}{}>'.format(REPR_GREEK_PSI, next_state_sub) - UNIVERSE_STATES.append(self.m) + if not self.name: + for well_known_state in well_known_states: + if self == well_known_state: + return repr(well_known_state) + for used_state in UNIVERSE_STATES: + if self == used_state: + return repr(used_state) + next_state_sub = ''.join([REPR_MATH_SUBSCRIPT_NUMBERS[int(d)] for d in str(len(UNIVERSE_STATES))]) + self.name = '{}{}'.format(REPR_GREEK_PSI, next_state_sub) + UNIVERSE_STATES.append(self) + matrix_rep = "{}".format(self.m).replace('[', '').replace(']', '').replace('\n', '|').strip() + state_name = '|{}> = {}'.format(self.name, matrix_rep) return state_name def norm(self): @@ -570,11 +581,18 @@ def naive_load_test(N): class QuantumCircuit(object): - def __init__(self, n_qubits: int): + def __init__(self, n_qubits: int, initial_steps=None): self.n_qubits = n_qubits - self.steps = [[_0 for _ in range(n_qubits)], ] + if not initial_steps: + self.steps = [[_0 for _ in range(n_qubits)], ] + else: + self.steps = initial_steps self._called_add_row = 0 + @property + def rows(self): + return self._called_add_row + def add_row_step(self, row: int, step: int, qbit_state): if len(self.steps) <= step: self.steps += [[I for _ in range(self.n_qubits)] for _ in range(len(self.steps) - step + 1)] @@ -663,6 +681,10 @@ class QuantumProcessor(object): RUNNING_STATE = "RUNNING" def __init__(self, circuit: QuantumCircuit): + if circuit.rows != circuit.n_qubits: + raise Exception("Declared circuit with n_qubits: {} but called add_row: {}".format( + circuit.n_qubits, circuit.rows + )) self.circuit = circuit self.c_step = 0 self.c_q_state = None @@ -726,9 +748,12 @@ class QuantumProcessor(object): result = self.measure() rv[result] += 1 self.reset() + return rv + + @staticmethod + def print_sample(rv): for k, v in sorted(rv.items(), key=lambda x: x[0]): print("{}: {}".format(k, v)) - return rv def test_quantum_processor():