def test_Ph_eigenvectors(): rule_set = DecompositionRuleSet(modules=[pe, dqft]) eng = MainEngine(backend=Simulator(), engine_list=[ AutoReplacer(rule_set), ]) results = np.array([]) for i in range(100): autovector = eng.allocate_qureg(1) theta = cmath.pi * 2. * 0.125 unit = Ph(theta) ancillas = eng.allocate_qureg(3) QPE(unit) | (ancillas, autovector) All(Measure) | ancillas fasebinlist = [int(q) for q in ancillas] fasebin = ''.join(str(j) for j in fasebinlist) faseint = int(fasebin, 2) phase = faseint / (2.**(len(ancillas))) results = np.append(results, phase) All(Measure) | autovector eng.flush() num_phase = (results == 0.125).sum() assert num_phase / 100. >= 0.35, "Statistics phase calculation are not correct (%f vs. %f)" % ( num_phase / 100., 0.35)
def test_toffoli_size_of_modular_offset(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ pivot_flip_rules, offset_rules, addition_rules, swap2cnot, increment_rules, multi_not_rules, modular_addition_rules, comparison_rules, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) controls = eng.allocate_qureg(15) target = eng.allocate_qureg(16) dirty = eng.allocate_qureg(2) modulus = 0xAEFD offset = 0x9E0A ModularOffsetGate(offset, modulus) & controls | target assert dirty is not None assert 5000 < len(rec.received_commands) < 15000
def test_toffoli_size_of_modular_addition(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ pivot_flip_rules, offset_rules, addition_rules, swap2cnot, increment_rules, multi_not_rules, modular_addition_rules, comparison_rules, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) controls = eng.allocate_qureg(15) target1 = eng.allocate_qureg(16) target2 = eng.allocate_qureg(16) modulus = 0xAEFD ModularAdditionGate(modulus) & controls | (target1, target2) assert 10000 < len(rec.received_commands) < 15000
def test_toffoli_size_of_modular_negate(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ swap2cnot, multi_not_rules, addition_rules, increment_rules, pivot_flip_rules, offset_rules, comparison_rules, modular_negate_rules, ])), LimitedCapabilityEngine(allow_toffoli=True, ), ]) t = eng.allocate_qureg(5) controls = eng.allocate_qureg(1) workspace = eng.allocate_qureg(2) modulus = 29 ModularNegate(modulus) & controls | t assert 100 < len(rec.received_commands) < 200 assert workspace is not None
def test_simulator_is_available(): backend = DummyEngine(save_commands=True) eng = MainEngine(backend, []) qureg = eng.allocate_qureg(2) X | qureg[0] S | qureg[0] H | qureg[0] CNOT | (qureg[0], qureg[1]) Measure | qureg[0] qureg[0].__del__() qureg[1].__del__() assert len(backend.received_commands) == 9 # Test that allocate, measure, and deallocate are available. sim = StabilizerSimulator(3) for cmd in backend.received_commands: assert sim.is_available(cmd) eng = MainEngine(sim, []) qureg = eng.allocate_qureg(3) X | qureg[0] S | qureg[0] H | qureg[0] CNOT | (qureg[0], qureg[1]) All(Measure) | qureg with pytest.raises(Exception): Toffoli | (qureg[0], qureg[1], qureg[2]) eng.flush() with pytest.raises(Exception): with Control(eng, qureg[1:]): X | qureg[0] eng.flush()
def record_decomposition(gate, decomposition_rule, register_sizes, control_size=0, workspace=0): """ Args: gate (projectq.ops.BasicMathGate| dirty_period_finding.extensions.BasicGateEx): decomposition_rule (projectq.cengines.DecompositionRule): register_sizes (list[int]): control_size (int): workspace (int): """ assert isinstance(gate, decomposition_rule.gate_class) rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[]) controls = eng.allocate_qureg(control_size) regs = tuple(eng.allocate_qureg(size) for size in register_sizes) junk = eng.allocate_qureg(workspace) if len(junk): JunkGate() | junk command = CommandEx(eng, gate, regs, controls) assert decomposition_rule.gate_recognizer(command) decomposition_rule.gate_decomposer(command) return rec.received_commands
def test_toffoli_size_of_bimultiplication(): rec = DummyEngine(save_commands=True) eng = MainEngine(backend=rec, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[ swap2cnot, multi_not_rules, addition_rules, increment_rules, modular_addition_rules, modular_bimultiplication_rules, modular_scaled_addition_rules, pivot_flip_rules, offset_rules, modular_double_rules, rotate_bits_rules, reverse_bits_rules, modular_negate_rules, comparison_rules, ])), LimitedCapabilityEngine(allow_toffoli=True), ]) t1 = eng.allocate_qureg(5) t2 = eng.allocate_qureg(5) controls = eng.allocate_qureg(1) modulus = 29 factor = 17 ModularBimultiplicationGate(factor, modulus) & controls | (t1, t2) assert 5000 < len(rec.received_commands) < 10000
def test_swapandcnotflipper_is_available(): flipper = _swapandcnotflipper.SwapAndCNOTFlipper(set()) dummy = DummyEngine() dummy.is_available = lambda x: False flipper.next_engine = dummy eng = MainEngine(DummyEngine(save_commands=True), []) qubit1, qubit2 = eng.allocate_qureg(2) Swap | (qubit1, qubit2) swap_count = 0 for cmd in eng.backend.received_commands: if cmd.gate == Swap: swap_count += 1 assert flipper.is_available(cmd) assert swap_count == 1 eng = MainEngine(DummyEngine(save_commands=True), []) qubit1, qubit2, qubit3 = eng.allocate_qureg(3) with Control(eng, qubit3): Swap | (qubit1, qubit2) swap_count = 0 for cmd in eng.backend.received_commands: if cmd.gate == Swap: swap_count += 1 assert not flipper.is_available(cmd) assert swap_count == 1
def simulate_sample_period(base, modulus): sim = Simulator() eng = MainEngine(backend=sim, engine_list=[ AutoReplacerEx( DecompositionRuleSet(modules=[decompositions])), LimitedCapabilityEngine( allow_arithmetic= not DECOMPOSE_INTO_TOFFOLIS_AND_GO_VERY_VERY_SLOW, allow_toffoli=True, allow_single_qubit_gates=True), ]) n = int(math.ceil(math.log(modulus, 2))) ancilla_qureg = eng.allocate_qureg(n) for q in ancilla_qureg[:-1]: if random.random() < 0.5: X | q before = ancilla_qureg.measure() result = shor_find_period(base=base, modulus=modulus, precision=n * 2, phase_qubit=eng.allocate_qubit(), work_qureg=eng.allocate_qureg(n), ancilla_qureg=ancilla_qureg) after = ancilla_qureg.measure() assert after == before return result
def test_or_two_quregs_error(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend, engine_list=[]) qureg = eng.allocate_qureg(2) qureg2 = eng.allocate_qureg(2) hamiltonian = QubitOperator("Z0", 2) with pytest.raises(TypeError): te.TimeEvolution(2.1, hamiltonian) | (qureg, qureg2)
def simon_quantum_step(function, input_size): """ Performs the quantum portion of Simon's algorithm, by finding an input string X where (X · S) % 2 = 0 (AKA x0*s0 ⊕ x1*s1 ⊕ ... ⊕ xN*sN = 0). Parameters: function (function): The black-box function to run the algorithm on (the function being evaluated). It should take a Program as its first input, an input Qureg as its second argument, and an output Qureg as its third argument. input_size (int): The number of bits that the function expects in its input and output registers. Returns: A bit string representing the measured result of the function. This bit string is a vector X where (X · S) % 2 = 0. Note that this will be the measured result of the INPUT register after it's been evaluated. The OUTPUT register is thrown away, because it doesn't actually matter to the algorithm at all. Remarks: A lot of literature out there will say that this returns a string where s · x = 0. This is misleading, because what they really mean is "dot product mod-2" and they don't usually say the "mod-2" part. Basically, this finds an input value that, when dot product'd with S, gives an even number. """ # Construct the engine and registers engine = MainEngine() input = engine.allocate_qureg(input_size) output = engine.allocate_qureg(input_size) # Run the function with |+...+> as the input and |0...0> as the output All(H) | input function(input, output) All(H) | input # At this point, the input bit string has been transformed # from |0...0> into X, where X is some string that is guaranteed # to be even when dot product'd with S. The math behind why this # is true is way beyond an explanation here - you have to look # at the literature to see why this is the case. # Measure the resulting input register and return it as a list[bool] for # classical postprocessing measurement = [False] * input_size for i in range(0, input_size): Measure | input[i] measurement[i] = (int(input[i]) == 1) reset(output ) # This isn't strictly necessary, but the simulator will complain engine.flush( ) # about deleting qubits that are still in a superposition even return measurement # though the program is finished.
def test_uniformly_controlled_ry(n, gate_classes): random_angles = [ 0.5, 0.8, 1.2, 2.5, 4.4, 2.32, 6.6, 15.12, 1, 2, 9.54, 2.1, 3.1415, 1.1, 0.01, 0.99 ] angles = random_angles[:2**n] for basis_state_index in range(0, 2**(n + 1)): basis_state = [0] * 2**(n + 1) basis_state[basis_state_index] = 1. correct_dummy_eng = DummyEngine(save_commands=True) correct_eng = MainEngine(backend=Simulator(), engine_list=[correct_dummy_eng]) rule_set = DecompositionRuleSet(modules=[ucr2cnot]) test_dummy_eng = DummyEngine(save_commands=True) test_eng = MainEngine(backend=Simulator(), engine_list=[ AutoReplacer(rule_set), InstructionFilter(_decomp_gates), test_dummy_eng ]) test_sim = test_eng.backend correct_sim = correct_eng.backend correct_qb = correct_eng.allocate_qubit() correct_ctrl_qureg = correct_eng.allocate_qureg(n) correct_eng.flush() test_qb = test_eng.allocate_qubit() test_ctrl_qureg = test_eng.allocate_qureg(n) test_eng.flush() correct_sim.set_wavefunction(basis_state, correct_qb + correct_ctrl_qureg) test_sim.set_wavefunction(basis_state, test_qb + test_ctrl_qureg) gate_classes[1](angles) | (test_ctrl_qureg, test_qb) slow_implementation(angles=angles, control_qubits=correct_ctrl_qureg, target_qubit=correct_qb, eng=correct_eng, gate_class=gate_classes[0]) test_eng.flush() correct_eng.flush() for fstate in range(2**(n + 1)): binary_state = format(fstate, '0' + str(n + 1) + 'b') test = test_sim.get_amplitude(binary_state, test_qb + test_ctrl_qureg) correct = correct_sim.get_amplitude( binary_state, correct_qb + correct_ctrl_qureg) assert correct == pytest.approx(test, rel=1e-10, abs=1e-10) All(Measure) | test_qb + test_ctrl_qureg All(Measure) | correct_qb + correct_ctrl_qureg test_eng.flush(deallocate_qubits=True) correct_eng.flush(deallocate_qubits=True)
def test_qubitop2singlequbit(): num_qubits = 4 random_initial_state = [ 0.2 + 0.1 * x * cmath.exp(0.1j + 0.2j * x) for x in range(2**(num_qubits + 1)) ] rule_set = DecompositionRuleSet(modules=[qubitop2onequbit]) test_eng = MainEngine( backend=Simulator(), engine_list=[AutoReplacer(rule_set), InstructionFilter(_decomp_gates)], ) test_qureg = test_eng.allocate_qureg(num_qubits) test_ctrl_qb = test_eng.allocate_qubit() test_eng.flush() test_eng.backend.set_wavefunction(random_initial_state, test_qureg + test_ctrl_qb) correct_eng = MainEngine() correct_qureg = correct_eng.allocate_qureg(num_qubits) correct_ctrl_qb = correct_eng.allocate_qubit() correct_eng.flush() correct_eng.backend.set_wavefunction(random_initial_state, correct_qureg + correct_ctrl_qb) qubit_op_0 = QubitOperator("X0 Y1 Z3", -1.0j) qubit_op_1 = QubitOperator("Z0 Y1 X3", cmath.exp(0.6j)) qubit_op_0 | test_qureg with Control(test_eng, test_ctrl_qb): qubit_op_1 | test_qureg test_eng.flush() correct_eng.backend.apply_qubit_operator(qubit_op_0, correct_qureg) with Control(correct_eng, correct_ctrl_qb): Ph(0.6) | correct_qureg[0] Z | correct_qureg[0] Y | correct_qureg[1] X | correct_qureg[3] correct_eng.flush() for fstate in range(2**(num_qubits + 1)): binary_state = format(fstate, '0' + str(num_qubits + 1) + 'b') test = test_eng.backend.get_amplitude(binary_state, test_qureg + test_ctrl_qb) correct = correct_eng.backend.get_amplitude( binary_state, correct_qureg + correct_ctrl_qb) assert correct == pytest.approx(test, rel=1e-10, abs=1e-10) All(Measure) | correct_qureg + correct_ctrl_qb All(Measure) | test_qureg + test_ctrl_qb correct_eng.flush() test_eng.flush()
def test_simulator_bit_repositioning(): sim = ClassicalSimulator() eng = MainEngine(sim, []) a = eng.allocate_qureg(4) b = eng.allocate_qureg(5) c = eng.allocate_qureg(6) sim.write_register(a, 9) sim.write_register(b, 17) sim.write_register(c, 33) for q in b: eng.deallocate_qubit(q) assert sim.read_register(a) == 9 assert sim.read_register(c) == 33
def test_recognize(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend, engine_list=[]) ctrl_qureg = eng.allocate_qureg(2) qureg = eng.allocate_qureg(2) with Control(eng, ctrl_qureg): QubitOperator("X0 Y1") | qureg with Control(eng, ctrl_qureg[0]): QubitOperator("X0 Y1") | qureg eng.flush() cmd0 = saving_backend.received_commands[4] cmd1 = saving_backend.received_commands[5] assert not qubitop2onequbit._recognize_qubitop(cmd0) assert qubitop2onequbit._recognize_qubitop(cmd1)
def test_ffft_2d_4x4_equal_expectation_values(self): system_size = 4 n_qubits = 16 grid = Grid(dimensions=2, length=system_size, scale=1.0) dual_basis = jellium_model(grid, spinless=True, plane_wave=False) ffft_result = operator_2d_fft_with_reordering(dual_basis, system_size) jw_dual_basis = jordan_wigner(dual_basis) jw_plane_wave = jordan_wigner(ffft_result) # Do plane wave and dual basis calculations together. pw_engine = MainEngine() pw_wavefunction = pw_engine.allocate_qureg(system_size ** 2) db_engine = MainEngine() db_wavefunction = db_engine.allocate_qureg(system_size ** 2) pw_engine.flush() db_engine.flush() # Choose random state. state = numpy.zeros(2 ** n_qubits, dtype=complex) for i in range(len(state)): state[i] = (random.random() * numpy.exp(1j * 2 * numpy.pi * random.random())) state /= numpy.linalg.norm(state) # Put randomly chosen state in the registers. pw_engine.backend.set_wavefunction(state, pw_wavefunction) db_engine.backend.set_wavefunction(state, db_wavefunction) # Apply the FFFT to the dual basis wave function. ffft_2d(db_engine, db_wavefunction, system_size) # Flush the engine and compute expectation values and eigenvalues. pw_engine.flush() db_engine.flush() plane_wave_expectation_value = ( pw_engine.backend.get_expectation_value( jw_dual_basis, pw_wavefunction)) dual_basis_expectation_value = ( db_engine.backend.get_expectation_value( jw_plane_wave, db_wavefunction)) All(Measure) | pw_wavefunction All(Measure) | db_wavefunction self.assertAlmostEqual(plane_wave_expectation_value, dual_basis_expectation_value)
def test_control(): backend = DummyEngine(save_commands=True) eng = MainEngine(backend=backend, engine_list=[DummyEngine()]) qureg = eng.allocate_qureg(2) with _control.Control(eng, qureg): qubit = eng.allocate_qubit() with Compute(eng): Rx(0.5) | qubit H | qubit Uncompute(eng) with _control.Control(eng, qureg[0]): H | qubit eng.flush() assert len(backend.received_commands) == 8 assert len(backend.received_commands[0].control_qubits) == 0 assert len(backend.received_commands[1].control_qubits) == 0 assert len(backend.received_commands[2].control_qubits) == 0 assert len(backend.received_commands[3].control_qubits) == 0 assert len(backend.received_commands[4].control_qubits) == 2 assert len(backend.received_commands[5].control_qubits) == 0 assert len(backend.received_commands[6].control_qubits) == 1 assert len(backend.received_commands[7].control_qubits) == 0 assert backend.received_commands[4].control_qubits[0].id == qureg[0].id assert backend.received_commands[4].control_qubits[1].id == qureg[1].id assert backend.received_commands[6].control_qubits[0].id == qureg[0].id
def test_drawer_getlatex(ordered): old_latex = _drawer.to_latex _drawer.to_latex = lambda x, drawing_order, draw_gates_in_parallel: x drawer = CircuitDrawer() drawer.set_qubit_locations({0: 1, 1: 0}) drawer2 = CircuitDrawer() eng = MainEngine(drawer, [drawer2]) qureg = eng.allocate_qureg(2) H | qureg[1] H | qureg[0] X | qureg[0] CNOT | (qureg[0], qureg[1]) lines = drawer2.get_latex(ordered=ordered) assert len(lines) == 2 assert len(lines[0]) == 4 assert len(lines[1]) == 3 # check if it was sent on correctly: lines = drawer.get_latex(ordered=ordered) assert len(lines) == 2 assert len(lines[0]) == 3 assert len(lines[1]) == 4 _drawer.to_latex = old_latex
def test_simulator_read_write(mapper): engine_list = [] if mapper is not None: engine_list.append(mapper) sim = ClassicalSimulator() eng = MainEngine(sim, engine_list) a = eng.allocate_qureg(32) b = eng.allocate_qureg(32) assert sim.read_register(a) == 0 assert sim.read_register(b) == 0 assert sim.read_bit(a[0]) == 0 assert sim.read_bit(b[0]) == 0 sim.write_register(a, 123) sim.write_register(b, 456) assert sim.read_register(a) == 123 assert sim.read_register(b) == 456 assert sim.read_bit(a[0]) == 1 assert sim.read_bit(b[0]) == 0 sim.write_bit(b[0], 1) assert sim.read_register(a) == 123 assert sim.read_register(b) == 457 assert sim.read_bit(a[0]) == 1 assert sim.read_bit(b[0]) == 1
def test_or_not_enough_qubits(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend, engine_list=[]) qureg = eng.allocate_qureg(2) hamiltonian = QubitOperator("Z0 X3", 2) with pytest.raises(ValueError): te.TimeEvolution(2.1, hamiltonian) | qureg
def test_simulator_bit_repositioning(mapper): engine_list = [] if mapper is not None: engine_list.append(mapper) sim = ClassicalSimulator() eng = MainEngine(sim, engine_list) a = eng.allocate_qureg(4) b = eng.allocate_qureg(5) c = eng.allocate_qureg(6) sim.write_register(a, 9) sim.write_register(b, 17) sim.write_register(c, 33) for q in b: eng.deallocate_qubit(q) assert sim.read_register(a) == 9 assert sim.read_register(c) == 33
def test_or_one_qubit(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend, engine_list=[]) qureg = eng.allocate_qureg(3) eng.flush() identity = qo.QubitOperator("", 1j) x = qo.QubitOperator("X1", cmath.exp(0.5j)) y = qo.QubitOperator("Y2", cmath.exp(0.6j)) z = qo.QubitOperator("Z0", cmath.exp(4.5j)) identity | qureg eng.flush() x | qureg eng.flush() y | qureg eng.flush() z | qureg eng.flush() assert saving_backend.received_commands[4].gate == Ph(math.pi / 2.) assert saving_backend.received_commands[6].gate == X assert saving_backend.received_commands[6].qubits == ([qureg[1]], ) assert saving_backend.received_commands[7].gate == Ph(0.5) assert saving_backend.received_commands[7].qubits == ([qureg[1]], ) assert saving_backend.received_commands[9].gate == Y assert saving_backend.received_commands[9].qubits == ([qureg[2]], ) assert saving_backend.received_commands[10].gate == Ph(0.6) assert saving_backend.received_commands[10].qubits == ([qureg[2]], ) assert saving_backend.received_commands[12].gate == Z assert saving_backend.received_commands[12].qubits == ([qureg[0]], ) assert saving_backend.received_commands[13].gate == Ph(4.5) assert saving_backend.received_commands[13].qubits == ([qureg[0]], )
def test_qubit_allocations_at_zero(): drawer = _drawer.CircuitDrawer() eng = MainEngine(drawer, []) old_tolatex = _drawer.to_latex _drawer.to_latex = lambda x: x a = eng.allocate_qureg(4) CNOT | (a[0], a[2]) CNOT | (a[0], a[3]) CNOT | (a[0], a[2]) CNOT | (a[1], a[3]) del a eng.flush() circuit_lines = drawer.get_latex() _drawer.to_latex = old_tolatex settings = _to_latex.get_default_settings() settings['gates']['AllocateQubitGate']['allocate_at_zero'] = True code = _to_latex._body(copy.deepcopy(circuit_lines), settings) assert code.count("gate0) at (0") == 4 settings['gates']['AllocateQubitGate']['allocate_at_zero'] = False code = _to_latex._body(copy.deepcopy(circuit_lines), settings) assert code.count("gate0) at (0") == 3 del settings['gates']['AllocateQubitGate']['allocate_at_zero'] code = _to_latex._body(copy.deepcopy(circuit_lines), settings) assert code.count("gate0) at (0") == 3
def circuit_no_ancilla(param=0, M=1): Engine = MainEngine() q1 = Engine.allocate_qureg(1) Rx(param) | q1 # [R * c-Pi * R^\dag * P * R * c-Pi * R^\dag * P] for _ in range(int(M / 2)): Z | q1 DaggeredGate(Rx(param)) | q1 Z | q1 Rx(param) | q1 Z | q1 DaggeredGate(Rx(param)) | q1 Z | q1 Rx(param) | q1 DaggeredGate(Rx(param)) | q1 Measure | q1 Engine.flush() return (int(q1))
def test_simulator_collapse_wavefunction(sim): eng = MainEngine(sim) qubits = eng.allocate_qureg(4) # unknown qubits: raises with pytest.raises(RuntimeError): eng.backend.collapse_wavefunction(qubits, [0] * 4) eng.flush() eng.backend.collapse_wavefunction(qubits, [0] * 4) assert pytest.approx(eng.backend.get_probability([0] * 4, qubits)) == 1. All(H) | qubits[1:] eng.flush() assert pytest.approx(eng.backend.get_probability([0] * 4, qubits)) == .125 # impossible outcome: raises with pytest.raises(RuntimeError): eng.backend.collapse_wavefunction(qubits, [1] + [0] * 3) eng.backend.collapse_wavefunction(qubits[:-1], [0, 1, 0]) assert (pytest.approx(eng.backend.get_probability([0, 1, 0, 1], qubits)) == .5) eng.backend.set_wavefunction([1.] + [0.] * 15, qubits) H | qubits[0] CNOT | (qubits[0], qubits[1]) eng.flush() eng.backend.collapse_wavefunction([qubits[0]], [1]) assert (pytest.approx(eng.backend.get_probability([1, 1], qubits[0:2])) == 1.)
def test_simulator_amplitude(sim): eng = MainEngine(sim) qubits = eng.allocate_qureg(6) All(X) | qubits All(H) | qubits eng.flush() bits = [0, 0, 1, 0, 1, 0] assert eng.backend.get_amplitude(bits, qubits) == pytest.approx(1. / 8.) bits = [0, 0, 0, 0, 1, 0] assert eng.backend.get_amplitude(bits, qubits) == pytest.approx(-1. / 8.) bits = [0, 1, 1, 0, 1, 0] assert eng.backend.get_amplitude(bits, qubits) == pytest.approx(-1. / 8.) All(H) | qubits All(X) | qubits Ry(2 * math.acos(0.3)) | qubits[0] eng.flush() bits = [0] * 6 assert eng.backend.get_amplitude(bits, qubits) == pytest.approx(0.3) bits[0] = 1 assert (eng.backend.get_amplitude(bits, qubits) == pytest.approx( math.sqrt(0.91))) Measure | qubits # raises if not all qubits are in the list: with pytest.raises(RuntimeError): eng.backend.get_amplitude(bits, qubits[:-1]) # doesn't just check for length: with pytest.raises(RuntimeError): eng.backend.get_amplitude(bits, qubits[:-1] + [qubits[0]]) extra_qubit = eng.allocate_qubit() eng.flush() # there is a new qubit now! with pytest.raises(RuntimeError): eng.backend.get_amplitude(bits, qubits)
def test_simulator_probability(sim): eng = MainEngine(sim) qubits = eng.allocate_qureg(6) All(H) | qubits eng.flush() bits = [0, 0, 1, 0, 1, 0] for i in range(6): assert (eng.backend.get_probability( bits[:i], qubits[:i]) == pytest.approx(0.5**i)) extra_qubit = eng.allocate_qubit() with pytest.raises(RuntimeError): eng.backend.get_probability([0], extra_qubit) del extra_qubit All(H) | qubits Ry(2 * math.acos(math.sqrt(0.3))) | qubits[0] eng.flush() assert eng.backend.get_probability([0], [qubits[0]]) == pytest.approx(0.3) Ry(2 * math.acos(math.sqrt(0.4))) | qubits[2] eng.flush() assert eng.backend.get_probability([0], [qubits[2]]) == pytest.approx(0.4) assert (eng.backend.get_probability([0, 0], qubits[:3:2]) == pytest.approx(0.12)) assert (eng.backend.get_probability([0, 1], qubits[:3:2]) == pytest.approx(0.18)) assert (eng.backend.get_probability([1, 0], qubits[:3:2]) == pytest.approx(0.28)) Measure | qubits
def test_ibm_backend_is_available_control_not(num_ctrl_qubits, is_available): eng = MainEngine(backend=DummyEngine(), engine_list=[DummyEngine()]) qubit1 = eng.allocate_qubit() qureg = eng.allocate_qureg(num_ctrl_qubits) ibm_backend = _ibm.IBMBackend() cmd = Command(eng, NOT, (qubit1, ), controls=qureg) assert ibm_backend.is_available(cmd) == is_available
def test_flip_bits_can_be_applied_to_various_qubit_qureg_formats(): eng = MainEngine() qubits = eng.allocate_qureg(4) eng.flush() assert pytest.approx(eng.backend.get_probability('0000', qubits)) == 1. FlipBits([0, 1, 1, 0]) | qubits eng.flush() assert pytest.approx(eng.backend.get_probability('0110', qubits)) == 1. FlipBits([1]) | qubits[0] eng.flush() assert pytest.approx(eng.backend.get_probability('1110', qubits)) == 1. FlipBits([1]) | (qubits[0], ) eng.flush() assert pytest.approx(eng.backend.get_probability('0110', qubits)) == 1. FlipBits([1, 1]) | [qubits[0], qubits[1]] eng.flush() assert pytest.approx(eng.backend.get_probability('1010', qubits)) == 1. FlipBits(-1) | qubits eng.flush() assert pytest.approx(eng.backend.get_probability('0101', qubits)) == 1. FlipBits(-4) | [qubits[0], qubits[1], qubits[2], qubits[3]] eng.flush() assert pytest.approx(eng.backend.get_probability('0110', qubits)) == 1. FlipBits(2) | [qubits[0]] + [qubits[1], qubits[2]] eng.flush() assert pytest.approx(eng.backend.get_probability('0010', qubits)) == 1. All(Measure) | qubits
def test_simulator_flip_bits(bits_to_flip, result): eng = MainEngine() qubits = eng.allocate_qureg(4) FlipBits(bits_to_flip) | qubits eng.flush() assert pytest.approx(eng.backend.get_probability(result, qubits)) == 1. All(Measure) | qubits
def run_circuit(self, circuit): """Run a circuit and return a single Result. Args: circuit (dict): JSON circuit from qobj circuits list Returns: dict: A dictionary of results which looks something like:: { "data": { #### DATA CAN BE A DIFFERENT DICTIONARY FOR EACH BACKEND #### "counts": {'00000': XXXX, '00001': XXXXX}, "time" : xx.xxxxxxxx }, "status": --status (string)-- } Raises: SimulatorError: if an error occurred. """ # pylint: disable=expression-not-assigned,pointless-statement ccircuit = circuit['compiled_circuit'] self._number_of_qubits = ccircuit['header']['number_of_qubits'] self._number_of_clbits = ccircuit['header']['number_of_clbits'] self._statevector = 0 self._classical_state = 0 cl_reg_index = [] # starting bit index of classical register cl_reg_nbits = [] # number of bits in classical register clbit_index = 0 qobj_quregs = OrderedDict(_get_register_specs( ccircuit['header']['qubit_labels'])) eng = MainEngine(backend=self._sim) for cl_reg in ccircuit['header']['clbit_labels']: cl_reg_nbits.append(cl_reg[1]) cl_reg_index.append(clbit_index) clbit_index += cl_reg[1] # let circuit seed override qobj default if 'config' in circuit: if 'seed' in circuit['config']: if circuit['config']['seed'] is not None: self._sim._simulator = CppSim(circuit['config']['seed']) outcomes = [] start = time.time() for _ in range(self._shots): self._statevector = np.zeros(1 << self._number_of_qubits, dtype=complex) self._statevector[0] = 1 # initialize starting state self._classical_state = 0 unmeasured_qubits = list(range(self._number_of_qubits)) projq_qureg_dict = OrderedDict(((key, eng.allocate_qureg(size)) for key, size in qobj_quregs.items())) qureg = [qubit for sublist in projq_qureg_dict.values() for qubit in sublist] # Do each operation in this shot for operation in ccircuit['operations']: if 'conditional' in operation: mask = int(operation['conditional']['mask'], 16) if mask > 0: value = self._classical_state & mask while (mask & 0x1) == 0: mask >>= 1 value >>= 1 if value != int(operation['conditional']['val'], 16): continue # Check if single gate if operation['name'] in ['U', 'u3']: params = operation['params'] qubit = qureg[operation['qubits'][0]] Rz(params[2]) | qubit Ry(params[0]) | qubit Rz(params[1]) | qubit elif operation['name'] in ['u1']: params = operation['params'] qubit = qureg[operation['qubits'][0]] Rz(params[0]) | qubit elif operation['name'] in ['u2']: params = operation['params'] qubit = qureg[operation['qubits'][0]] Rz(params[1] - np.pi/2) | qubit Rx(np.pi/2) | qubit Rz(params[0] + np.pi/2) | qubit elif operation['name'] == 't': qubit = qureg[operation['qubits'][0]] T | qubit elif operation['name'] == 'h': qubit = qureg[operation['qubits'][0]] H | qubit elif operation['name'] == 's': qubit = qureg[operation['qubits'][0]] S | qubit elif operation['name'] in ['CX', 'cx']: qubit0 = qureg[operation['qubits'][0]] qubit1 = qureg[operation['qubits'][1]] CX | (qubit0, qubit1) elif operation['name'] in ['id', 'u0']: pass # Check if measure elif operation['name'] == 'measure': qubit_index = operation['qubits'][0] qubit = qureg[qubit_index] clbit = operation['clbits'][0] Measure | qubit bit = 1 << clbit self._classical_state = ( self._classical_state & (~bit)) | (int(qubit) << clbit) # check whether we already measured this qubit if operation['qubits'][0] in unmeasured_qubits: unmeasured_qubits.remove(operation['qubits'][0]) # Check if reset elif operation['name'] == 'reset': qubit = operation['qubits'][0] raise SimulatorError('Reset operation not yet implemented ' 'for ProjectQ C++ backend') elif operation['name'] == 'barrier': pass else: backend = self._configuration['name'] err_msg = '{0} encountered unrecognized operation "{1}"' raise SimulatorError(err_msg.format(backend, operation['name'])) for ind in unmeasured_qubits: qubit = qureg[ind] Measure | qubit eng.flush() # Turn classical_state (int) into bit string state = format(self._classical_state, 'b') outcomes.append(state.zfill(self._number_of_clbits)) # Return the results counts = dict(Counter(outcomes)) data = {'counts': _format_result( counts, cl_reg_index, cl_reg_nbits)} if self._shots == 1: # TODO: deprecated -- remove in v0.6 data['statevector'] = self._statevector data['quantum_state'] = self._statevector data['classical_state'] = self._classical_state end = time.time() return {'name': circuit['name'], 'seed': self._seed, 'shots': self._shots, 'data': data, 'status': 'DONE', 'success': True, 'time_taken': (end-start)}