def test_idempotent_del(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[]) q = eng.allocate_qubit()[0] rec.received_commands = [] assert len(rec.received_commands) == 0 q.__del__() assert len(rec.received_commands) == 1 q.__del__() assert len(rec.received_commands) == 1
def check_phase_circuit(register_sizes, expected_turns, engine_list, actions): """ Args: register_sizes (list[int]): expected_turns (function(register_sizes: tuple[int], register_vals: tuple[int])): engine_list (list[projectq.cengines.BasicEngine]): actions (function(eng: MainEngine, registers: list[Qureg])): """ sim = Simulator() rec = DummyEngine(save_commands=True) eng = MainEngine(backend=sim, engine_list=list(engine_list) + [rec]) registers = [eng.allocate_qureg(size) for size in register_sizes] # Simulate all. for reg in registers: for q in reg: H | q rec.received_commands = [] actions(eng, registers) state = np.array(sim.cheat()[1]) magnitude_factor = math.sqrt(len(state)) actions = list(rec.received_commands) for reg in registers: for q in reg: Measure | q # Compare. for i in range(len(state)): vals = [] t = 0 for r in register_sizes: vals.append((i >> t) & ((1 << r) - 1)) t += r vals = tuple(vals) actual_factor = state[i] expected_turn = expected_turns(register_sizes, vals) actual_turn = cmath.phase(state[i]) / (2 * math.pi) delta_turn = abs((actual_turn - expected_turn + 0.5) % 1 - 0.5) if not (delta_turn < 0.00001): print(commands_to_ascii_circuit(actions)) print("Register Sizes", register_sizes) print("Conflicting state: {}".format(vals)) print("Expected phase: {} deg".format(float(expected_turn)*360)) print("Actual phase: {} deg".format(actual_turn*360)) assert abs(abs(actual_factor * magnitude_factor) - 1) < 0.00001 assert delta_turn < 0.00001
def fuzz_permutation_circuit(register_sizes, permutation, actions, engine_list=(), register_limits=None): """ Args: register_sizes (list[int]): permutation (function(register_vals: tuple[int], register_sizes: tuple[int]) : tuple[int]): actions (function(eng: MainEngine, registers: list[Qureg])): engine_list (list[projectq.cengines.BasicEngine]): register_limits (list[int]): """ n = len(register_sizes) if register_limits is None: register_limits = [1 << size for size in register_sizes] assert len(register_limits) == n inputs = tuple(random.randint(0, limit - 1) for limit in register_limits) outputs = [e % (1 << d) for e, d in zip(permutation(register_sizes, inputs), register_sizes)] sim = ClassicalSimulator() rec = DummyEngine(save_commands=True) eng = MainEngine(backend=sim, engine_list=list(engine_list) + [rec]) registers = tuple(eng.allocate_qureg(size) for size in register_sizes) # Encode inputs. for i in range(n): for b in range(register_sizes[i]): if inputs[i] & (1 << b): X | registers[i][b] # Simulate. rec.received_commands = [] actions(eng, registers) # Compare outputs. actual_outputs = [sim.read_register(registers[i]) for i in range(n)] if outputs != actual_outputs: print(commands_to_ascii_circuit(rec.received_commands)) print("Register Sizes", register_sizes) print("Register Limits", register_limits) print("Inputs", inputs) print("Expected Outputs", outputs) print("Actual Outputs", actual_outputs) assert outputs == actual_outputs
def check_quantum_permutation_circuit(register_size, permutation_func, actions, engine_list=()): """ Args: register_size (int): permutation_func (function(register_sizes: tuple[int], register_vals: tuple[int]) : tuple[int]): actions (function(eng: MainEngine, registers: list[Qureg])): engine_list (list[projectq.cengines.BasicEngine]): """ sim = Simulator() rec = DummyEngine(save_commands=True) eng = MainEngine(backend=sim, engine_list=list(engine_list) + [rec]) reg = eng.allocate_qureg(register_size) All(H) | reg for i in range(len(reg)): Rz(math.pi / 2**i) | reg[i] pre_state = np.array(sim.cheat()[1]) # Simulate. rec.received_commands = [] actions(eng, [reg]) actions = list(rec.received_commands) post_state = np.array(sim.cheat()[1]) for q in reg: Measure | q denom = math.sqrt(len(pre_state)) pre_state *= denom post_state *= denom for i in range(len(pre_state)): j = permutation_func([register_size], [i]) & ((1 << len(reg)) - 1) if not (abs(post_state[j] - pre_state[i]) < 0.000000001): print(commands_to_ascii_circuit(actions)) print("Input", i) print("Expected Output", j) print("Input Amp at " + str(i), pre_state[i]) print("Actual Amp at " + str(j), post_state[j]) assert abs(post_state[j] - pre_state[i]) < 0.000000001
def test_ibm5qubitmapper_optimizeifpossible(): backend = DummyEngine(save_commands=True) connectivity = {(2, 1), (4, 2), (2, 0), (3, 2), (3, 4), (1, 0)} eng = MainEngine( backend=backend, engine_list=[ _ibm5qubitmapper.IBM5QubitMapper(connections=connectivity), SwapAndCNOTFlipper(connectivity), ], ) qb0 = eng.allocate_qubit() # noqa: F841 qb1 = eng.allocate_qubit() qb2 = eng.allocate_qubit() qb3 = eng.allocate_qubit() # noqa: F841 CNOT | (qb1, qb2) CNOT | (qb2, qb1) CNOT | (qb1, qb2) eng.flush() hadamard_count = 0 for cmd in backend.received_commands: if cmd.gate == H: hadamard_count += 1 assert hadamard_count == 4 backend.received_commands = [] CNOT | (qb2, qb1) CNOT | (qb1, qb2) CNOT | (qb2, qb1) eng.flush() hadamard_count = 0 for cmd in backend.received_commands: if cmd.gate == H: hadamard_count += 1 assert hadamard_count == 4
def test_ibmcnotmapper_optimizeifpossible(): backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[_ibmcnotmapper.IBMCNOTMapper()]) qb0 = eng.allocate_qubit() qb1 = eng.allocate_qubit() qb2 = eng.allocate_qubit() qb3 = eng.allocate_qubit() CNOT | (qb1, qb2) CNOT | (qb2, qb1) CNOT | (qb1, qb2) eng.flush() hadamard_count = 0 for cmd in backend.received_commands: if cmd.gate == H: hadamard_count += 1 if cmd.gate == X: assert cmd.qubits[0][0].id == qb2[0].id assert hadamard_count == 4 backend.received_commands = [] CNOT | (qb2, qb1) CNOT | (qb1, qb2) CNOT | (qb2, qb1) eng.flush() hadamard_count = 0 for cmd in backend.received_commands: if cmd.gate == H: hadamard_count += 1 if cmd.gate == X: assert cmd.qubits[0][0].id == qb1[0].id assert hadamard_count == 4
def _recursive_decompose(self, cmd): if self.is_available(cmd): return [cmd] canonical_cmd, id_map, key, used, avail = self._canonicalize(cmd) if key in self._cached_results: if self._cached_results == 'IN PROGRESS': raise NoGateDecompositionError( 'Cyclic decomposition for {}.'.format(cmd)) return self._translate(cmd, self._cached_results[key], id_map) self._cached_results[key] = 'IN PROGRESS' rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ LocalOptimizer(), SimpleAdjacentCombiner(self.merge_rules), ]) involved = eng.allocate_qureg(used) workspace = eng.allocate_qureg(avail) eng.flush() rec.received_commands = [] canonical_cmd.engine = eng self._pick_decomp_for(cmd).decompose(canonical_cmd) eng.flush() intermediate_result = rec.received_commands[:-1] assert involved is not None assert workspace is not None flattened_result = [ leaf for child in intermediate_result for leaf in self._recursive_decompose(child) ] self._cached_results[key] = flattened_result return self._translate(cmd, flattened_result, id_map)