def lcu_controlled_unitary(eng, list_of_U, coefts, ctrl, sys, sys_dim): size = len(list_of_U) if not size: print('Error in lcu - I got an empty list of unitaries!') ctrl_dim = math.ceil(math.log(size, 2)) for i in range(0, size): temp = np.binary_repr(i) temp = temp.zfill(ctrl_dim) # pad with zeros for fixed length bin with Compute(eng): for j in range(0, ctrl_dim): if (int(temp[j]) == 0): X | ctrl[j] # if unitaries passed are qubitoperator, directly apply them, no unpacking required if isinstance(list_of_U[0], QubitOperator): with Control(eng, ctrl): list_of_U[i] | sys Uncompute(eng) else: with Control(eng, ctrl): if (isinstance(coefts[i], complex)): # can be i, or -1 Ph(0.5 * math.pi) | sys[j] # apply global phase i if (np.sign(-1j * coefts[i]) < 0): Ph(math.pi) | sys[j] # global phase is actually -i elif (np.sign(coefts[i]) < 0): Ph(math.pi) | sys[j] # apply global phase -1 for j in range(0, sys_dim): if (list_of_U[i][j] == I): continue list_of_U[i][j] | sys[j] Uncompute(eng)
def oracle(eng): ControlledGate(Ph(theta), 2) | (output_reg[2], des_output, ancilla2) X | output_reg[2] X | des_output ControlledGate(Ph(theta), 2) | (output_reg[2], des_output, ancilla2) X | output_reg[2] X | des_output
def oracle(eng): ControlledGate(Ph(theta), 2) | (output, des_output, ancilla_qubit2) X | output X | des_output ControlledGate(Ph(theta), 2) | (output, des_output, ancilla_qubit2) X | output X | des_output
def test_openqasm_test_qasm_single_qubit_gates(): backend = OpenQASMEngine() eng = MainEngine(backend=backend, engine_list=[]) qubit = eng.allocate_qubit() H | qubit S | qubit T | qubit Sdag | qubit Tdag | qubit X | qubit Y | qubit Z | qubit R(0.5) | qubit Rx(0.5) | qubit Ry(0.5) | qubit Rz(0.5) | qubit Ph(0.5) | qubit NOT | qubit Measure | qubit eng.flush() qasm = [l for l in backend.circuit.qasm().split('\n')[2:] if l] assert qasm == [ 'qreg q0[1];', 'creg c0[1];', 'h q0[0];', 's q0[0];', 't q0[0];', 'sdg q0[0];', 'tdg q0[0];', 'x q0[0];', 'y q0[0];', 'z q0[0];', 'u1(0.500000000000000) q0[0];', 'rx(0.500000000000000) q0[0];', 'ry(0.500000000000000) q0[0];', 'rz(0.500000000000000) q0[0];', 'u1(-0.250000000000000) q0[0];', 'x q0[0];', 'measure q0[0] -> c0[0];' ]
def _decompose_h2rx_M(cmd): """ Decompose the Ry gate.""" # Labelled 'M' for 'minus' because decomposition ends with a Ry(-pi/2) qubit = cmd.qubits[0] Rx(math.pi) | qubit Ph(math.pi / 2) | qubit Ry(-1 * math.pi / 2) | qubit
def _decompose_QAA(cmd): """ Decompose the Quantum Amplitude Apmplification algorithm as a gate. """ eng = cmd.engine # System-qubit is the first qubit/qureg. Ancilla qubit is the second qubit system_qubits = cmd.qubits[0] qaa_ancilla = cmd.qubits[1] # The Oracle and the Algorithm Oracle = cmd.gate.oracle A = cmd.gate.algorithm # Apply the oracle to invert the amplitude of the good states, S_Chi Oracle(eng, system_qubits, qaa_ancilla) # Apply the inversion of the Algorithm, # the inversion of the aplitude of |0> and the Algorithm with Compute(eng): with Dagger(eng): A(eng, system_qubits) All(X) | system_qubits with Control(eng, system_qubits[0:-1]): Z | system_qubits[-1] with CustomUncompute(eng): All(X) | system_qubits A(eng, system_qubits) Ph(math.pi) | system_qubits[0]
def test_openqasm_test_qasm_single_qubit_gates_control(): backend = OpenQASMEngine() eng = MainEngine(backend=backend, engine_list=[]) qubit = eng.allocate_qubit() ctrl = eng.allocate_qubit() with Control(eng, ctrl): H | qubit X | qubit Y | qubit Z | qubit NOT | qubit R(0.5) | qubit Rz(0.5) | qubit Ph(0.5) | qubit eng.flush() qasm = [l for l in backend.circuit.qasm().split('\n')[2:] if l] assert qasm == [ 'qreg q0[1];', 'qreg q1[1];', 'creg c0[1];', 'creg c1[1];', 'ch q1[0],q0[0];', 'cx q1[0],q0[0];', 'cy q1[0],q0[0];', 'cz q1[0],q0[0];', 'cx q1[0],q0[0];', 'cu1(0.500000000000000) q1[0],q0[0];', 'crz(0.500000000000000) q1[0],q0[0];', 'cu1(-0.250000000000000) q1[0],q0[0];' ]
def lcu_oaa(eng, list_of_unitaries, coefts, ctrl, sys, ctrl_dim, sys_dim, rounds=1): phi = -1 * math.pi for i in range(0, rounds): cond_phase(eng, ctrl, sys, phi) with Dagger(eng): lcu_basic(eng, list_of_unitaries, coefts, ctrl, sys, ctrl_dim, sys_dim) size = pow(2, ctrl_dim) for l in range(1, size): # -R flips sign of everything except 00..0 temp = np.binary_repr(i) temp = temp.zfill(ctrl_dim) # pad with zeros for fixed length bin with Compute(eng): for j in range(0, ctrl_dim): if (int(temp[j]) == 0): X | ctrl[j] with Control(eng, ctrl): Ph(phi) | sys[0] # flip sign using any one sys qubit Uncompute(eng) lcu_basic(eng, list_of_unitaries, coefts, ctrl, sys, ctrl_dim, sys_dim) print("Amplitudes of ctrl+sys state after {} rounds of OAA:\n".format( int(i) + 1)) print_amplitudes(eng, ctrl + sys, ctrl_dim + sys_dim)
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 _decompose_arb1qubit(cmd): """ Use Z-Y decomposition of Nielsen and Chuang (Theorem 4.1). An arbitrary one qubit gate matrix can be writen as U = [[exp(j*(a-b/2-d/2))*cos(c/2), -exp(j*(a-b/2+d/2))*sin(c/2)], [exp(j*(a+b/2-d/2))*sin(c/2), exp(j*(a+b/2+d/2))*cos(c/2)]] where a,b,c,d are real numbers. Then U = exp(j*a) Rz(b) Ry(c) Rz(d). If the matrix is element of SU(2) (determinant == 1), then we can choose a = 0. """ matrix = cmd.gate.matrix.tolist() a, b_half, c_half, d_half = _find_parameters(matrix) qb = cmd.qubits eng = cmd.engine with Control(eng, cmd.control_qubits): if Rz(2 * d_half) != Rz(0): Rz(2 * d_half) | qb if Ry(2 * c_half) != Ry(0): Ry(2 * c_half) | qb if Rz(2 * b_half) != Rz(0): Rz(2 * b_half) | qb if a != 0: Ph(a) | qb
def _decompose_state_preparation(cmd): # pylint: disable=too-many-locals """Implement state preparation based on arXiv:quant-ph/0407010v1.""" eng = cmd.engine if len(cmd.qubits) != 1: raise ValueError( 'StatePreparation does not support multiple quantum registers!') num_qubits = len(cmd.qubits[0]) qureg = cmd.qubits[0] final_state = cmd.gate.final_state if len(final_state) != 2**num_qubits: raise ValueError("Length of final_state is invalid.") norm = 0.0 for amplitude in final_state: norm += abs(amplitude)**2 if norm < 1 - 1e-10 or norm > 1 + 1e-10: raise ValueError("final_state is not normalized.") with Control(eng, cmd.control_qubits): # As in the paper reference, we implement the inverse: with Dagger(eng): # Cancel all the relative phases phase_of_blocks = [] for amplitude in final_state: phase_of_blocks.append(cmath.phase(amplitude)) for qubit_idx, qubit in enumerate(qureg): angles = [] phase_of_next_blocks = [] for block in range(2**(len(qureg) - qubit_idx - 1)): phase0 = phase_of_blocks[2 * block] phase1 = phase_of_blocks[2 * block + 1] angles.append(phase0 - phase1) phase_of_next_blocks.append((phase0 + phase1) / 2.0) UniformlyControlledRz(angles) | ( qureg[(qubit_idx + 1):], # noqa: E203 qubit, ) phase_of_blocks = phase_of_next_blocks # Cancel global phase Ph(-phase_of_blocks[0]) | qureg[-1] # Remove amplitudes from states which contain a bit value 1: abs_of_blocks = [] for amplitude in final_state: abs_of_blocks.append(abs(amplitude)) for qubit_idx, qubit in enumerate(qureg): angles = [] abs_of_next_blocks = [] for block in range(2**(len(qureg) - qubit_idx - 1)): a0 = abs_of_blocks[2 * block] # pylint: disable=invalid-name a1 = abs_of_blocks[2 * block + 1] # pylint: disable=invalid-name if a0 == 0 and a1 == 0: angles.append(0) else: angles.append(-2.0 * math.acos(a0 / math.sqrt(a0**2 + a1**2))) abs_of_next_blocks.append(math.sqrt(a0**2 + a1**2)) UniformlyControlledRy(angles) | ( qureg[(qubit_idx + 1):], # noqa: E203 qubit, ) abs_of_blocks = abs_of_next_blocks
def _decompose_h2rx_N(cmd): """ Decompose the Ry gate.""" # Labelled 'N' for 'neutral' because decomposition doesn't end with # Ry(pi/2) or Ry(-pi/2) qubit = cmd.qubits[0] Ry(math.pi / 2) | qubit Ph(3 * math.pi / 2) | qubit Rx(-1 * math.pi) | qubit
def ffft_2d(engine, register, system_size): """Apply the 2D fermionic fast Fourier transform to a register. Args: engine (projectq.MainEngine): The simulator engine with the register. register (projectq.QuReg): The register to apply the 2D FFFT to. system_size (int): The side length of the system. register must thus have system_size ** 2 qubits. Notes: This algorithm uses radix-2 decimation-in-time, so system_size must be a binary power. This decimation is head recursive (the 2-mode FFFT is applied as the first part of the 4-mode FFFT, which is applied as the first part of the 8-mode FFFT, etc). """ # Apply the FFFT along one axis of the register. for i in range(system_size): ffft(engine, register[system_size * i:system_size * i + system_size], system_size) Ph(3 * numpy.pi / 4) | register[0] # To apply the FFFT along the second axis, we must fermionically # swap qubits into the correct positions. In 2D this is equivalent # to flipping all qubits across the "diagonal" of the grid. key_2d = (index_of_position_in_1d_array, (0, 1)) arr = [(i, j) for i in range(system_size) for j in range(system_size)] swaps = parallel_bubble_sort(arr, key_2d, system_size) all_swaps = [swap for swap_layer in swaps for swap in swap_layer] # Fermionically swap into position to FFFT along the second axis. for swap in all_swaps: Swap | (register[swap[0]], register[swap[1]]) C(Z) | (register[swap[0]], register[swap[1]]) # Perform the FFFT along the second axis. for i in range(system_size): ffft(engine, register[system_size * i:system_size * i + system_size], system_size) Ph(3 * numpy.pi / 4) | register[0] # Undo the fermionic swap network to restore the original ordering. for swap in all_swaps[::-1]: Swap | (register[swap[0]], register[swap[1]]) C(Z) | (register[swap[0]], register[swap[1]])
def run_circuit(eng): qureg = eng.allocate_qureg(4) All(H) | qureg CRz(3.0) | (qureg[0], qureg[1]) Toffoli | (qureg[1], qureg[2], qureg[3]) with Control(eng, qureg[0:2]): Ph(1.43) | qureg[2] return qureg
def _decompose_R(cmd): """ Decompose the (controlled) phase-shift gate, denoted by R(phase). """ ctrl = cmd.control_qubits eng = cmd.engine gate = cmd.gate with Control(eng, ctrl): Ph(.5 * gate._angle) | cmd.qubits Rz(gate._angle) | cmd.qubits
def _decompose_R(cmd): # pylint: disable=invalid-name """Decompose the (controlled) phase-shift gate, denoted by R(phase).""" ctrl = cmd.control_qubits eng = cmd.engine gate = cmd.gate with Control(eng, ctrl): Ph(0.5 * gate.angle) | cmd.qubits Rz(gate.angle) | cmd.qubits
def test_ionq_invalid_command(): """Test that this backend raises out with invalid commands.""" # Ph gate is not a valid gate qb = WeakQubitRef(None, 1) cmd = Command(None, gate=Ph(math.pi), qubits=[(qb, )]) backend = _ionq.IonQBackend(verbose=True) with pytest.raises(InvalidCommandError): backend.receive([cmd])
def _decompose_cnot2rxx_M(cmd): # pylint: disable=invalid-name """Decompose CNOT gate into Rxx gate.""" # Labelled 'M' for 'minus' because decomposition ends with a Ry(-pi/2) ctrl = cmd.control_qubits Ry(math.pi / 2) | ctrl[0] Ph(7 * math.pi / 4) | ctrl[0] Rx(-math.pi / 2) | ctrl[0] Rx(-math.pi / 2) | cmd.qubits[0][0] Rxx(math.pi / 2) | (ctrl[0], cmd.qubits[0][0]) Ry(-1 * math.pi / 2) | ctrl[0]
def _decompose_cnot2rxx_P(cmd): """ Decompose CNOT gate into Rxx gate. """ # Labelled 'P' for 'plus' because decomposition ends with a Ry(+pi/2) ctrl = cmd.control_qubits Ry(-math.pi / 2) | ctrl[0] Ph(math.pi / 4) | ctrl[0] Rx(-math.pi / 2) | ctrl[0] Rx(math.pi / 2) | cmd.qubits[0][0] Rxx(math.pi / 2) | (ctrl[0], cmd.qubits[0][0]) Ry(math.pi / 2) | ctrl[0]
def _decompose_state_preparation(cmd): """ Implements state preparation based on arXiv:quant-ph/0407010v1. """ eng = cmd.engine assert len(cmd.qubits) == 1 num_qubits = len(cmd.qubits[0]) qureg = cmd.qubits[0] final_state = cmd.gate.final_state if len(final_state) != 2**num_qubits: raise ValueError("Length of final_state is invalid.") norm = 0. for amplitude in final_state: norm += abs(amplitude)**2 if norm < 1 - 1e-10 or norm > 1 + 1e-10: raise ValueError("final_state is not normalized.") with Control(eng, cmd.control_qubits): # As in the paper reference, we implement the inverse: with Dagger(eng): # Cancel all the relative phases phase_of_blocks = [] for amplitude in final_state: phase_of_blocks.append(cmath.phase(amplitude)) for target_qubit in range(len(qureg)): angles = [] phase_of_next_blocks = [] for block in range(2**(len(qureg) - target_qubit - 1)): phase0 = phase_of_blocks[2 * block] phase1 = phase_of_blocks[2 * block + 1] angles.append(phase0 - phase1) phase_of_next_blocks.append((phase0 + phase1) / 2.) UniformlyControlledRz(angles) | (qureg[(target_qubit + 1):], qureg[target_qubit]) phase_of_blocks = phase_of_next_blocks # Cancel global phase Ph(-phase_of_blocks[0]) | qureg[-1] # Remove amplitudes from states which contain a bit value 1: abs_of_blocks = [] for amplitude in final_state: abs_of_blocks.append(abs(amplitude)) for target_qubit in range(len(qureg)): angles = [] abs_of_next_blocks = [] for block in range(2**(len(qureg) - target_qubit - 1)): a0 = abs_of_blocks[2 * block] a1 = abs_of_blocks[2 * block + 1] if a0 == 0 and a1 == 0: angles.append(0) else: angles.append(-2. * math.acos(a0 / math.sqrt(a0**2 + a1**2))) abs_of_next_blocks.append(math.sqrt(a0**2 + a1**2)) UniformlyControlledRy(angles) | (qureg[(target_qubit + 1):], qureg[target_qubit]) abs_of_blocks = abs_of_next_blocks
def test_is_available_correct_result(self): self.__is_available_assert_equal(NOT, True, count=1) self.__is_available_assert_equal(NOT, False, count=3) self.__is_available_assert_equal(CNOT, False, count=0) self.__is_available_assert_equal(Z, True, count=1) self.__is_available_assert_equal(Z, False, count=3) self.__is_available_assert_equal(Ph(0.4), False) self.__is_available_assert_equal(Toffoli, False) for gate in [Measure, Allocate, Deallocate, Barrier, T, Tdag, S, Sdag, Swap, H, X, Y, Z, Rx(0.1), Ry(0.2), Rz(0.3)]: self.__is_available_assert_equal(gate, True)
def run_grover(eng, n, oracle): """ Runs Grover's algorithm on n qubit using the provided quantum oracle. Args: eng (MainEngine): Main compiler engine to run Grover on. n (int): Number of bits in the solution. oracle (function): Function accepting the engine, an n-qubit register, and an output qubit which is flipped by the oracle for the correct bit string. Returns: solution (list<int>): Solution bit-string. """ x = eng.allocate_qureg(n) # start in uniform superposition All(H) | x # number of iterations we have to run: num_it = int(math.pi / 4. * math.sqrt(1 << n)) print("Number of iterations we have to run: {}".format(num_it)) # prepare the oracle output qubit (the one that is flipped to indicate the # solution. start in state 1/sqrt(2) * (|0> - |1>) s.t. a bit-flip turns # into a (-1)-phase. oracle_out = eng.allocate_qubit() X | oracle_out H | oracle_out # run num_it iterations with Loop(eng, num_it): # oracle adds a (-1)-phase to the solution oracle(eng, x, oracle_out) # reflection across uniform superposition with Compute(eng): All(H) | x All(X) | x with Control(eng, x[0:-1]): Z | x[-1] Uncompute(eng) All(Ph(math.pi / n)) | x All(Measure) | x Measure | oracle_out eng.flush() # return result return [int(qubit) for qubit in x]
def test_recognize_correct_gates(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend) qubit = eng.allocate_qubit() Ph(0.1) | qubit R(0.2) | qubit Rx(0.3) | qubit X | qubit eng.flush(deallocate_qubits=True) # Don't test initial allocate and trailing deallocate and flush gate. for cmd in saving_backend.received_commands[1:-2]: assert arb1q._recognize_arb1qubit(cmd)
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_decompose_commuting_terms(): saving_backend = DummyEngine(save_commands=True) def my_filter(self, cmd): if len(cmd.qubits[0]) <= 2 or isinstance(cmd.gate, ClassicalInstructionGate): return True return False rules = DecompositionRuleSet([te.rule_commuting_terms]) replacer = AutoReplacer(rules) filter_eng = InstructionFilter(my_filter) eng = MainEngine(backend=saving_backend, engine_list=[replacer, filter_eng]) qureg = eng.allocate_qureg(5) with Control(eng, qureg[3]): op1 = QubitOperator("X1 Y2", 0.7) op2 = QubitOperator("Y2 X4", -0.8) op3 = QubitOperator((), 0.6) TimeEvolution(1.5, op1 + op2 + op3) | qureg cmd1 = saving_backend.received_commands[5] cmd2 = saving_backend.received_commands[6] cmd3 = saving_backend.received_commands[7] found = [False, False, False] scaled_op1 = QubitOperator("X0 Y1", 0.7) scaled_op2 = QubitOperator("Y0 X1", -0.8) for cmd in [cmd1, cmd2, cmd3]: if (cmd.gate == Ph(-1.5 * 0.6) and cmd.qubits[0][0].id == qureg[1].id and cmd.control_qubits[0].id == qureg[3].id # 1st qubit of [1,2,4] ): found[0] = True elif (isinstance(cmd.gate, TimeEvolution) and cmd.gate.hamiltonian.isclose(scaled_op1) and cmd.gate.time == pytest.approx(1.5) and cmd.qubits[0][0].id == qureg[1].id and cmd.qubits[0][1].id == qureg[2].id and cmd.control_qubits[0].id == qureg[3].id): found[1] = True elif (isinstance(cmd.gate, TimeEvolution) and cmd.gate.hamiltonian.isclose(scaled_op2) and cmd.gate.time == pytest.approx(1.5) and cmd.qubits[0][0].id == qureg[2].id and cmd.qubits[0][1].id == qureg[4].id and cmd.control_qubits[0].id == qureg[3].id): found[2] = True assert all(found)
def test_recognize_correct_gates(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend) qubit = eng.allocate_qubit() ctrl_qubit = eng.allocate_qubit() eng.flush() with Control(eng, ctrl_qubit): Ph(0.1) | qubit R(0.2) | qubit Rx(0.3) | qubit X | qubit eng.flush(deallocate_qubits=True) # Don't test initial two allocate and flush and trailing deallocate # and flush gate. for cmd in saving_backend.received_commands[3:-3]: assert carb1q._recognize_carb1qubit(cmd)
def _decompose_qubitop(cmd): assert len(cmd.qubits) == 1 qureg = cmd.qubits[0] eng = cmd.engine qubit_op = cmd.gate with Control(eng, cmd.control_qubits): (term, coefficient), = qubit_op.terms.items() phase = cmath.phase(coefficient) Ph(phase) | qureg[0] for index, action in term: if action == "X": X | qureg[index] elif action == "Y": Y | qureg[index] elif action == "Z": Z | qureg[index]
def test_or_gate_identity(): saving_backend = DummyEngine(save_commands=True) eng = MainEngine(backend=saving_backend, engine_list=[]) qureg = eng.allocate_qureg(4) hamiltonian = QubitOperator((), 3.4) correct_h = copy.deepcopy(hamiltonian) gate = te.TimeEvolution(2.1, hamiltonian) gate | qureg eng.flush() cmd = saving_backend.received_commands[4] assert isinstance(cmd.gate, Ph) assert cmd.gate == Ph(-3.4 * 2.1) correct = numpy.array([[cmath.exp(-1j * 3.4 * 2.1), 0], [0, cmath.exp(-1j * 3.4 * 2.1)]]) print(correct) print(cmd.gate.matrix) assert numpy.allclose(cmd.gate.matrix, correct)
def _decompose_qubitop(cmd): if len(cmd.qubits) != 1: raise ValueError('QubitOperator decomposition can only accept a single quantum register') qureg = cmd.qubits[0] eng = cmd.engine qubit_op = cmd.gate with Control(eng, cmd.control_qubits): ((term, coefficient),) = qubit_op.terms.items() phase = cmath.phase(coefficient) Ph(phase) | qureg[0] for index, action in term: if action == "X": X | qureg[index] elif action == "Y": Y | qureg[index] elif action == "Z": Z | qureg[index]
def alternating_bits_oracle_modified(eng, qubits, output, phi): """ Marks the solution string 0,1,0,... by applying phase gate to the output bits, conditioned on qubits being equal to the alternating bit-string. Args: eng (MainEngine): Main compiler engine the algorithm is being run on. qubits (Qureg): n-qubit quantum register Grover search is run on. output (Qubit): Output qubit to mark the solution by a phase gate with parameter phi. """ with Compute(eng): All(X) | qubits[1::2] with Control(eng, qubits): Rz(phi) | output Ph(phi/2) | output Uncompute(eng)