def qfunc1(): qml.Hadamard(wires=0) qml.PauliX(wires=1) qml.SWAP(wires=[0, 1]) qml.SWAP(wires=[0, 2]) qml.PauliY(wires=0) return qml.expval(qml.PauliZ(0))
def circuit(): """A combination of two and three qubit gates with the one_qubit_block and a simple PauliZ measurement, all acting on a four qubit input basis state""" qml.BasisState(np.array(basis_state), wires=[0, 1, 2, 3]) qml.RX(0.5, wires=0) qml.Hadamard(wires=1) qml.RY(0.9, wires=2) qml.Rot(0.1, -0.2, -0.3, wires=3) qml.CNOT(wires=[0, 1]) qml.CNOT(wires=[3, 1]) one_qubit_block(wires=3) qml.CNOT(wires=[2, 0]) qml.CZ(wires=[1, 0]) one_qubit_block(wires=0) qml.Toffoli(wires=[1, 0, 2]) one_qubit_block(wires=2) qml.SWAP(wires=[0, 1]) qml.SWAP(wires=[0, 2]) qml.Toffoli(wires=[1, 3, 2]) qml.CRX(0.5, wires=[1, 0]) qml.CSWAP(wires=[2, 1, 0]) qml.CRY(0.9, wires=[2, 1]) one_qubit_block(wires=1) qml.CRZ(0.02, wires=[0, 1]) qml.CRY(0.9, wires=[2, 3]) qml.CRot(0.2, 0.3, 0.7, wires=[2, 1]) qml.RZ(0.4, wires=0) qml.Toffoli(wires=[2, 1, 0]) return qml.expval(qml.PauliZ(0))
def qfunc(theta): qml.Hadamard(wires=0) qml.RX(theta[0], wires=1) qml.SWAP(wires=[0, 1]) qml.SWAP(wires=[0, 2]) qml.RY(theta[1], wires=0) return qml.expval(qml.PauliZ(0))
def test_SWAP(self): """Test SWAP gate special call""" with QuantumTape() as tape: qml.SWAP(wires=(0, 1)) _, ax = tape_mpl(tape) layer = 0 # two wires produce two lines and SWAP contains 5 more lines assert len(ax.lines) == 7 connecting_line = ax.lines[2] assert connecting_line.get_data() == ((layer, layer), [0, 1]) dx = 0.2 # check the coordinates of the swap lines x_lines = ax.lines[3:] for line in x_lines: assert line.get_xdata() == (layer - dx, layer + dx) assert x_lines[0].get_ydata() == (-dx, dx) assert x_lines[1].get_ydata() == (dx, -dx) assert x_lines[2].get_ydata() == (1 - dx, 1 + dx) assert x_lines[3].get_ydata() == (1 + dx, 1 - dx) plt.close()
def decomposition(wires): return [ qml.SWAP(wires=wires), qml.S(wires=[wires[0]]), qml.S(wires=[wires[1]]), qml.CZ(wires=wires), ]
def compute_decomposition(phi, wires): return [ qml.SWAP(wires=wires), qml.CNOT(wires=wires), qml.PhaseShift(phi, wires=[wires[1]]), qml.CNOT(wires=wires), ]
def qfunc(a, b, c, angles): qml.RX(a, wires=0) qml.RX(b, wires=1) qml.PauliZ(1) qml.CNOT(wires=[0, 1]).inv() qml.CRY(b, wires=[3, 1]) qml.RX(angles[0], wires=0) qml.RX(4 * angles[1], wires=1) qml.PhaseShift(17 / 9 * c, wires=2) qml.RZ(b, wires=3) qml.RX(angles[2], wires=2).inv() qml.CRY(0.3589, wires=[3, 1]).inv() qml.CSWAP(wires=[4, 2, 1]).inv() qml.QubitUnitary(np.eye(2), wires=[2]) qml.Toffoli(wires=[0, 2, 1]) qml.CNOT(wires=[0, 2]) qml.PauliZ(wires=[1]) qml.PauliZ(wires=[1]).inv() qml.CZ(wires=[0, 1]) qml.CZ(wires=[0, 2]).inv() qml.CNOT(wires=[2, 1]) qml.CNOT(wires=[0, 2]) qml.SWAP(wires=[0, 2]).inv() qml.CNOT(wires=[1, 3]) qml.RZ(b, wires=3) qml.CSWAP(wires=[4, 0, 1]) return [ qml.expval(qml.PauliY(0)), qml.var(qml.Hadamard(wires=1)), qml.sample(qml.PauliX(2)), qml.expval(qml.Hermitian(np.eye(4), wires=[3, 4])), ]
def circuit(): qml.Rot(theta, phi, delta, wires=0) qml.Rot(theta, phi, delta, wires=1) qml.SWAP(wires=[0, 1]) return ( qml.expval(qml.PauliX(0)), qml.expval(qml.PauliX(1)), )
def Turing(): # distinct fun names in functional placeholders= # [] qml.Hadamard(0) qml.PauliX(1) qml.PauliY(1) qml.PauliZ(1) qml.CNOT(wires=[0, 1]) qml.CZ(wires=[0, 1]) qml.SWAP(wires=[1, 0]) qml.RX(-6.283185307179586, wires=2) qml.RY(-6.283185307179586, wires=2) qml.RZ(-6.283185307179586, wires=2) qml.PhaseShift(3.141592653589793, wires=1) def rot(rad_ang_x, rad_ang_y, rad_ang_z): """ Returns exp(1j*(rad_ang_x*sig_x + rad_ang_y*sig_y + rad_ang_z*sig_z)) where rad_ang_x is an angle in radians and sig_x is the x Pauli matrix, etc. Parameters ---------- rad_ang_x : float rad_ang_y : float rad_ang_z : float Returns ------- np.ndarray """ ty = np.complex128 mat = np.zeros([2, 2], dtype=ty) vec = np.array([rad_ang_x, rad_ang_y, rad_ang_z]) n = np.linalg.norm(vec) # sqrt(dot(vec, vec.conj)) if abs(n) < 1e-8: mat[0, 0] = 1 mat[1, 1] = 1 else: nx = rad_ang_x / n ny = rad_ang_y / n nz = rad_ang_z / n c = np.cos(n) s = np.sin(n) mat[0, 0] = c + 1j * s * nz mat[0, 1] = s * ny + 1j * s * nx mat[1, 0] = -s * ny + 1j * s * nx mat[1, 1] = c - 1j * s * nz return mat qml.QubitUnitary(rot(-6.283185307179586, -6.283185307179586, -6.283185307179586), wires=0) return qml.expval.Hermitian(hamil)
def qft_circuit(): for wire in reversed(range(self.n)): qml.Hadamard(wire) for i in range(wire): qml.CRZ(np.pi / (2**(wire - i)), wires=[i, wire]) for i in range(self.n // 2): qml.SWAP(wires=[i, self.n - i - 1]) return qml.probs(wires=range(self.n))
def qft_U(params): # Execute QFT n_param = 0 for i in range(n_qubits): qml.Hadamard(wires=i) for j in range(i + 1, n_qubits): U0(params[n_param], wires=[0, 1, 2, 3]) n_param += 1 # Final swaps for n in range(n_qubits // 2): qml.SWAP(wires=[n, n_qubits - n - 1])
def qft(): # Execute QFT for i in range(n_qubits): qml.Hadamard(wires=i) for n_j, j in enumerate(range(i + 1, n_qubits)): R_k = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, np.exp(2j * π / (2**(n_j + 2)))]]) qml.QubitUnitary(R_k, wires=[j, i]) # Final swaps for n in range(n_qubits // 2): qml.SWAP(wires=[n, (n_qubits - 1) - n])
def op(op_name): ops_list = { "RX": qml.RX(0.123, wires=0), "RY": qml.RY(1.434, wires=0), "RZ": qml.RZ(2.774, wires=0), "S": qml.S(wires=0), "SX": qml.SX(wires=0), "T": qml.T(wires=0), "CNOT": qml.CNOT(wires=[0, 1]), "CZ": qml.CZ(wires=[0, 1]), "CY": qml.CY(wires=[0, 1]), "SWAP": qml.SWAP(wires=[0, 1]), "ISWAP": qml.ISWAP(wires=[0, 1]), "SISWAP": qml.SISWAP(wires=[0, 1]), "SQISW": qml.SQISW(wires=[0, 1]), "CSWAP": qml.CSWAP(wires=[0, 1, 2]), "PauliRot": qml.PauliRot(0.123, "Y", wires=0), "IsingXX": qml.IsingXX(0.123, wires=[0, 1]), "IsingXY": qml.IsingXY(0.123, wires=[0, 1]), "IsingYY": qml.IsingYY(0.123, wires=[0, 1]), "IsingZZ": qml.IsingZZ(0.123, wires=[0, 1]), "Identity": qml.Identity(wires=0), "Rot": qml.Rot(0.123, 0.456, 0.789, wires=0), "Toffoli": qml.Toffoli(wires=[0, 1, 2]), "PhaseShift": qml.PhaseShift(2.133, wires=0), "ControlledPhaseShift": qml.ControlledPhaseShift(1.777, wires=[0, 2]), "CPhase": qml.CPhase(1.777, wires=[0, 2]), "MultiRZ": qml.MultiRZ(0.112, wires=[1, 2, 3]), "CRX": qml.CRX(0.836, wires=[2, 3]), "CRY": qml.CRY(0.721, wires=[2, 3]), "CRZ": qml.CRZ(0.554, wires=[2, 3]), "Hadamard": qml.Hadamard(wires=0), "PauliX": qml.PauliX(wires=0), "PauliY": qml.PauliY(wires=0), "PauliZ": qml.PauliZ(wires=0), "CRot": qml.CRot(0.123, 0.456, 0.789, wires=[0, 1]), "DiagonalQubitUnitary": qml.DiagonalQubitUnitary(np.array([1.0, 1.0j]), wires=1), "ControlledQubitUnitary": qml.ControlledQubitUnitary( np.eye(2) * 1j, wires=[0], control_wires=[2] ), "MultiControlledX": qml.MultiControlledX(wires=(0, 1, 2), control_values="01"), "SingleExcitation": qml.SingleExcitation(0.123, wires=[0, 3]), "SingleExcitationPlus": qml.SingleExcitationPlus(0.123, wires=[0, 3]), "SingleExcitationMinus": qml.SingleExcitationMinus(0.123, wires=[0, 3]), "DoubleExcitation": qml.DoubleExcitation(0.123, wires=[0, 1, 2, 3]), "DoubleExcitationPlus": qml.DoubleExcitationPlus(0.123, wires=[0, 1, 2, 3]), "DoubleExcitationMinus": qml.DoubleExcitationMinus(0.123, wires=[0, 1, 2, 3]), "QFT": qml.QFT(wires=0), "QubitSum": qml.QubitSum(wires=[0, 1, 2]), "QubitCarry": qml.QubitCarry(wires=[0, 1, 2, 3]), "QubitUnitary": qml.QubitUnitary(np.eye(2) * 1j, wires=0), } return ops_list.get(op_name)
def test_four_qubit_random_circuit(self, device, tol): """Compare a four-qubit random circuit with lots of different gates to default.qubit""" n_wires = 4 dev = device(n_wires) dev_def = qml.device("default.qubit", wires=n_wires) if dev.name == dev_def.name: pytest.skip("Device is default.qubit.") if dev.shots is not None: pytest.skip("Device is in non-analytical mode.") gates = [ qml.PauliX(wires=0), qml.PauliY(wires=1), qml.PauliZ(wires=2), qml.S(wires=3), qml.T(wires=0), qml.RX(2.3, wires=1), qml.RY(1.3, wires=2), qml.RZ(3.3, wires=3), qml.Hadamard(wires=0), qml.Rot(0.1, 0.2, 0.3, wires=1), qml.CRot(0.1, 0.2, 0.3, wires=[2, 3]), qml.Toffoli(wires=[0, 1, 2]), qml.SWAP(wires=[1, 2]), qml.CSWAP(wires=[1, 2, 3]), qml.U1(1.0, wires=0), qml.U2(1.0, 2.0, wires=2), qml.U3(1.0, 2.0, 3.0, wires=3), qml.CRX(0.1, wires=[1, 2]), qml.CRY(0.2, wires=[2, 3]), qml.CRZ(0.3, wires=[3, 1]), ] layers = 3 np.random.seed(1967) gates_per_layers = [np.random.permutation(gates).numpy() for _ in range(layers)] def circuit(): """4-qubit circuit with layers of randomly selected gates and random connections for multi-qubit gates.""" np.random.seed(1967) for gates in gates_per_layers: for gate in gates: qml.apply(gate) return qml.expval(qml.PauliZ(0)) qnode_def = qml.QNode(circuit, dev_def) qnode = qml.QNode(circuit, dev) assert np.allclose(qnode(), qnode_def(), atol=tol(dev.shots))
def expand(self): with qml.tape.QuantumTape() as tape: # block of Hadamard and CR_k gates for i in range(len(self.wires)): qml.Hadamard(wires=self.wires[i]) for k in range(2,(len(self.wires)-i)+1): CR_k_inv(k,wires=[self.wires[i+(k-1)],self.wires[i]]) # block of SWAP gates # works both if len(wires)%2 == 0 or len(wires)%2 == 1 for i in range(int(len(self.wires)/2)): qml.SWAP(wires=[self.wires[i],self.wires[len(self.wires)-(i+1)]]) return tape
def test_swap_decomposition(self): """Tests the swap operator produces the correct output""" opr = qml.SWAP(wires=[0, 1]) decomp = opr.decompose() mat = [] for op in reversed(decomp): if isinstance(op, qml.CNOT) and op.wires.tolist() == [0, 1]: mat.append(CNOT) elif isinstance(op, qml.CNOT) and op.wires.tolist() == [1, 0]: mat.append(np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]])) decomposed_matrix = np.linalg.multi_dot(mat) assert np.allclose(decomposed_matrix, opr.matrix)
def circuit(): """A combination of two qubit gates with the one_qubit_block and a simple PauliZ measurement applied to an input basis state""" qml.BasisState(np.array(basis_state), wires=[0, 1]) qml.RX(0.5, wires=0) qml.Hadamard(wires=1) qml.CNOT(wires=[0, 1]) qml.CZ(wires=[1, 0]) one_qubit_block(wires=0) qml.SWAP(wires=[0, 1]) qml.CRX(0.5, wires=[1, 0]) qml.CRY(0.9, wires=[0, 1]) one_qubit_block(wires=1) qml.CRZ(0.02, wires=[0, 1]) qml.CRot(0.2, 0.3, 0.7, wires=[0, 1]) return qml.expval(qml.PauliZ(0))
def test_four_qubit_random_circuit(self, shots): """Test a four-qubit random circuit with the whole set of possible gates, the test is analog to a failing device test and is used to check the try/except expval function from the mixed_simulator device.""" dev = qml.device("cirq.mixedsimulator", wires=4) gates = [ qml.PauliX(wires=0), qml.PauliY(wires=1), qml.PauliZ(wires=2), qml.S(wires=3), qml.T(wires=0), qml.RX(2.3, wires=1), qml.RY(1.3, wires=2), qml.RZ(3.3, wires=3), qml.Hadamard(wires=0), qml.Rot(0.1, 0.2, 0.3, wires=1), qml.CRot(0.1, 0.2, 0.3, wires=[2, 3]), qml.Toffoli(wires=[0, 1, 2]), qml.SWAP(wires=[1, 2]), qml.CSWAP(wires=[1, 2, 3]), qml.U1(1.0, wires=0), qml.U2(1.0, 2.0, wires=2), qml.U3(1.0, 2.0, 3.0, wires=3), qml.CRX(0.1, wires=[1, 2]), qml.CRY(0.2, wires=[2, 3]), qml.CRZ(0.3, wires=[3, 1]), ] layers = 3 np.random.seed(1967) gates_per_layers = [pnp.random.permutation(gates).numpy() for _ in range(layers)] def circuit(): """4-qubit circuit with layers of randomly selected gates and random connections for multi-qubit gates.""" np.random.seed(1967) for gates in gates_per_layers: for gate in gates: qml.apply(gate) return qml.expval(qml.PauliZ(0)) qnode = qml.QNode(circuit, dev) assert np.allclose(qnode(), 0.0)
def compute_matrix_from_ops_two_qubit(ops, wire_order): """Given a list of two-qubit operations, construct its matrix representation.""" mat = qml.math.kron(I, I) for op in ops: if len(op.wires) == 1: if op.wires == qml.wires.Wires(wire_order[0]): mat = qml.math.dot(qml.math.kron(op.matrix, I), mat) else: mat = qml.math.dot(qml.math.kron(I, op.matrix), mat) else: if op.wires == qml.wires.Wires(wire_order): mat = qml.math.dot(op.matrix, mat) else: mat = qml.math.dot( qml.SWAP(wires=[0, 1]).matrix, qml.math.dot(op.matrix, mat)) return mat
def parameterized_qubit_tape(): """A parametrized qubit ciruit.""" a, b, c = 0.1, 0.2, 0.3 angles = np.array([0.4, 0.5, 0.6]) with qml.tape.QuantumTape() as tape: qml.RX(a, wires=0) qml.RX(b, wires=1) qml.PauliZ(1) qml.CNOT(wires=[0, 1]).inv() qml.CRY(b, wires=[3, 1]) qml.RX(angles[0], wires=0) qml.RX(4 * angles[1], wires=1) qml.PhaseShift(17 / 9 * c, wires=2) qml.RZ(b, wires=3) qml.RX(angles[2], wires=2).inv() qml.CRY(0.3589, wires=[3, 1]).inv() qml.CSWAP(wires=[4, 2, 1]).inv() qml.QubitUnitary(np.eye(2), wires=[2]) qml.ControlledQubitUnitary(np.eye(2), control_wires=[0, 1], wires=[2]) qml.MultiControlledX(control_wires=[0, 1, 2], wires=[3]) qml.Toffoli(wires=[0, 2, 1]) qml.CNOT(wires=[0, 2]) qml.PauliZ(wires=[1]) qml.PauliZ(wires=[1]).inv() qml.CZ(wires=[0, 1]) qml.CZ(wires=[0, 2]).inv() qml.CY(wires=[1, 2]) qml.CY(wires=[2, 0]).inv() qml.CNOT(wires=[2, 1]) qml.CNOT(wires=[0, 2]) qml.SWAP(wires=[0, 2]).inv() qml.CNOT(wires=[1, 3]) qml.RZ(b, wires=3) qml.CSWAP(wires=[4, 0, 1]) qml.expval(qml.PauliY(0)), qml.var(qml.Hadamard(wires=1)), qml.sample(qml.PauliX(2)), qml.expval(qml.Hermitian(np.eye(4), wires=[3, 4])), return tape
def permute_qubits(num_qubits): # A random permutation perm_order = list(rng.permutation(num_qubits)) working_order = list(range(num_qubits)) # We will permute by iterating through the permutation and swapping # things back to their proper place. for idx_here in range(num_qubits): if working_order[idx_here] != perm_order[idx_here]: # Where do we need to send the qubit at this location? idx_there = working_order.index(perm_order[idx_here]) qml.SWAP(wires=[idx_here, idx_there]) # Update the working order to account for the SWAP working_order[idx_here], working_order[idx_there] = ( working_order[idx_there], working_order[idx_here], )
def qft_3(): """ 3 qubit Quantum Fourier Transform. Returns: the probabilities of each of the basis states from qml.probs """ # The following 2 for loops represent the Quantum Fourier Transform for n in range(3, 0, -1): qml.Hadamard(wires=('wire' + str(n))) for k in range(n - 1, 0, -1): b = n - 1 U = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, np.exp((np.pi / float(2**(n - k))) * 1j)]]) qml.QubitUnitary(U, wires=[('wire' + str(k)), ('wire' + str(b + 1))]) qml.SWAP(wires=['wire1', 'wire3']) return qml.probs(wires=['wire3', 'wire2', 'wire1'])
def test_integration(): gates = [ qml.PauliX(wires=0), qml.PauliY(wires=0), qml.PauliZ(wires=0), qml.S(wires=0), qml.T(wires=0), qml.RX(0.4, wires=0), qml.RY(0.4, wires=0), qml.RZ(0.4, wires=0), qml.Hadamard(wires=0), qml.Rot(0.4, 0.5, 0.6, wires=1), qml.CRot(0.4, 0.5, 0.6, wires=(0, 1)), qml.Toffoli(wires=(0, 1, 2)), qml.SWAP(wires=(0, 1)), qml.CSWAP(wires=(0, 1, 2)), qml.U1(0.4, wires=0), qml.U2(0.4, 0.5, wires=0), qml.U3(0.4, 0.5, 0.6, wires=0), qml.CRX(0.4, wires=(0, 1)), qml.CRY(0.4, wires=(0, 1)), qml.CRZ(0.4, wires=(0, 1)), ] layers = 3 np.random.seed(1967) gates_per_layers = [np.random.permutation(gates) for _ in range(layers)] with qml.tape.QuantumTape() as tape: np.random.seed(1967) for gates in gates_per_layers: for gate in gates: qml.apply(gate) base_circ = from_pennylane(tape) tape_recovered = to_pennylane(base_circ) circ_recovered = from_pennylane(tape_recovered) u_1 = cirq.unitary(base_circ) u_2 = cirq.unitary(circ_recovered) cirq.testing.assert_allclose_up_to_global_phase(u_1, u_2, atol=0)
def qpe(): """ Quantum phase estimation on a single-qubit unitary with 3-bit prcision. Returns: the probabilities of each of the basis stats from qml.probs """ # Initialize qubit 4 to state 1 qml.PauliX(wires='wire4') # Transform the other 3 qubits into the Hadamard basis qml.Hadamard(wires='wire3') qml.Hadamard(wires='wire2') qml.Hadamard(wires='wire1') angle = 5 * (np.pi / 4) U1 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, np.exp(angle * 1j)]]) # The following two for loops represent the relevant controlled unitary operations iterations = 1 for i in range(3): for j in range(iterations): qml.QubitUnitary(U1, wires=[('wire' + str(i + 1)), 'wire4']) iterations = iterations * 2 qml.SWAP(wires=['wire1', 'wire3']) # The following two for loops represent the Inverse Quantum Fourier Transform for n in range(3): for k in range(n): U2 = np.array( [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, np.exp((-np.pi / float(2**(n - k))) * 1j)]]) qml.QubitUnitary(U2, wires=[('wire' + str(k + 1)), ('wire' + str(n + 1))]) qml.Hadamard(wires=('wire' + str(n + 1))) return qml.probs(wires=['wire3', 'wire2', 'wire1'])
def test_nested_tapes(self): with qml.tape.QuantumTape() as tape: with qml.tape.QuantumTape(): qml.PauliX(0) qml.CNOT(wires=[0, 2]) with qml.tape.QuantumTape(): qml.QuantumPhaseEstimation( qml.PauliY.matrix, target_wires=[1], estimation_wires=[2] ) qml.CNOT(wires=[1, 2]) qml.Hadamard(1) with qml.tape.QuantumTape(): qml.SWAP(wires=[0, 1]) qml.state() expected = ( " 0: ──╭QuantumTape:T0─────╭QuantumTape:T1──╭┤ State \n" + " 1: ──├QuantumTape:T0──H──╰QuantumTape:T1──├┤ State \n" + " 2: ──╰QuantumTape:T0──────────────────────╰┤ State \n" + "T0 =\n" + " 0: ──X──╭C───────────────────┤ \n" + " 2: ─────╰X──╭QuantumTape:T2──┤ \n" + " 1: ─────────╰QuantumTape:T2──┤ \n" + "T2 =\n" + " 1: ──╭QuantumPhaseEstimation(M0)──╭C──┤ \n" + " 2: ──╰QuantumPhaseEstimation(M0)──╰X──┤ \n" + "M0 =\n" + "[[ 0.+0.j -0.-1.j]\n" + " [ 0.+1.j 0.+0.j]]\n" + "\n" + "\n" + "T1 =\n" + " 0: ──╭SWAP──┤ \n" + " 1: ──╰SWAP──┤ \n" + "\n" ) assert tape.draw(wire_order=qml.wires.Wires([0, 1, 2])) == expected
def decomposition(wires): num_wires = len(wires) shifts = [2 * np.pi * 2**-i for i in range(2, num_wires + 1)] decomp_ops = [] for i, wire in enumerate(wires): decomp_ops.append(qml.Hadamard(wire)) for shift, control_wire in zip(shifts[:len(shifts) - i], wires[i + 1:]): op = qml.ControlledPhaseShift(shift, wires=[control_wire, wire]) decomp_ops.append(op) first_half_wires = wires[:num_wires // 2] last_half_wires = wires[-(num_wires // 2):] for wire1, wire2 in zip(first_half_wires, reversed(last_half_wires)): swap = qml.SWAP(wires=[wire1, wire2]) decomp_ops.append(swap) return decomp_ops
def qft_3_with_inverse_check(): """ 3 qubit Quantum Fourier Transform as well as a 3 Qubit Inverse Fourier Transform used to verify QFT implementation Returns: the probabilities of each of the basis states from qml.probs """ # Lets test with 100 qml.PauliX('wire1') # The following 2 for loops represent the Quantum Fourier Transform for n in range(3, 0, -1): qml.Hadamard(wires=('wire' + str(n))) for k in range(n - 1, 0, -1): b = n - 1 U1 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, np.exp((np.pi / float(2**(n - k))) * 1j)]]) qml.QubitUnitary(U1, wires=[('wire' + str(k)), ('wire' + str(b + 1))]) # The following 2 for loops represent the Inverse Quantum Fourier Transform used to ensure that # we can return to the original state after the Quantum Fourier Transform for n in range(3): for k in range(n): U2 = np.array( [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, np.exp((-np.pi / float(2**(n - k))) * 1j)]]) qml.QubitUnitary(U2, wires=[('wire' + str(k + 1)), ('wire' + str(n + 1))]) qml.Hadamard(wires=('wire' + str(n + 1))) qml.SWAP(wires=['wire1', 'wire3']) #return qml.probs(wires=['wire1' ,'wire2', 'wire3']) return qml.probs(wires=['wire3', 'wire2', 'wire1'])
def circuit2(): # create input state of 1 qml.PauliX(wires=3) # apply phase estimation circuit qml.Hadamard(wires=0) qml.Hadamard(wires=1) qml.Hadamard(wires=2) qml.CRZ(5*pi/2, wires=[2,3]) for i in range (2): qml.CRZ(5*pi/2, wires=[1,3]) for i in range(4): qml.CRZ(5*pi/2, wires=[0,3]) # QFT-1 qml.SWAP(wires=[0,2]) qml.Hadamard(wires=2) qml.CRZ(pi/2,wires=[2,1]).inv() qml.CRZ(pi/4,wires=[2,0]).inv() qml.Hadamard(wires=1) qml.CRZ(pi/2,wires=[1,0]).inv() qml.Hadamard(wires=0) return qml.probs(wires=[0,1,2])
class TestProgramConverter: """Test that PyQuil Program instances are properly converted.""" @pytest.mark.parametrize( "pyquil_operation,expected_pl_operation", [ (g.I(0), qml.Identity(wires=[0])), (g.H(0), qml.Hadamard(0)), (g.H(0).dagger(), qml.Hadamard(0).inv()), (g.H(0).dagger().dagger(), qml.Hadamard(0).inv().inv()), (g.S(0), qml.S(wires=[0])), (g.S(0).dagger(), qml.S(wires=[0]).inv()), (g.S(0).dagger().dagger(), qml.S(wires=[0]).inv().inv()), (g.T(0), qml.T(wires=[0])), (g.T(0).dagger(), qml.T(wires=[0]).inv()), (g.T(0).dagger().dagger(), qml.T(wires=[0]).inv().inv()), (g.X(0), qml.PauliX(0)), (g.X(0).dagger(), qml.PauliX(0).inv()), (g.X(0).dagger().dagger(), qml.PauliX(0).inv().inv()), (g.X(0).controlled(1), qml.CNOT(wires=[1, 0])), (g.X(0).controlled(1).dagger(), qml.CNOT(wires=[1, 0]).inv()), (g.X(0).controlled(1).dagger().dagger(), qml.CNOT(wires=[1, 0]).inv().inv()), (g.X(0).controlled(1).controlled(2), plf.ops.CCNOT(wires=[2, 1, 0])), (g.X(0).controlled(1).controlled(2).dagger(), plf.ops.CCNOT(wires=[2, 1, 0]).inv()), ( g.X(0).controlled(1).controlled(2).dagger().dagger(), plf.ops.CCNOT(wires=[2, 1, 0]).inv().inv(), ), (g.Y(0), qml.PauliY(0)), (g.Y(0).dagger(), qml.PauliY(0).inv()), (g.Y(0).dagger().dagger(), qml.PauliY(0).inv().inv()), (g.Z(0), qml.PauliZ(0)), (g.Z(0).dagger(), qml.PauliZ(0).inv()), (g.Z(0).dagger().dagger(), qml.PauliZ(0).inv().inv()), (g.Z(0).controlled(1), qml.CZ(wires=[1, 0])), (g.Z(0).controlled(1).dagger(), qml.CZ(wires=[1, 0]).inv()), (g.Z(0).controlled(1).dagger().dagger(), qml.CZ(wires=[1, 0]).inv().inv()), (g.CNOT(0, 1), qml.CNOT(wires=[0, 1])), (g.CNOT(0, 1).dagger(), qml.CNOT(wires=[0, 1]).inv()), (g.CNOT(0, 1).dagger().dagger(), qml.CNOT(wires=[0, 1]).inv().inv()), (g.CNOT(0, 1).controlled(2), plf.ops.CCNOT(wires=[2, 0, 1])), (g.CNOT(0, 1).controlled(2).dagger(), plf.ops.CCNOT(wires=[2, 0, 1]).inv()), ( g.CNOT(0, 1).controlled(2).dagger().dagger(), plf.ops.CCNOT(wires=[2, 0, 1]).inv().inv(), ), (g.SWAP(0, 1), qml.SWAP(wires=[0, 1])), (g.SWAP(0, 1).dagger(), qml.SWAP(wires=[0, 1]).inv()), (g.SWAP(0, 1).dagger().dagger(), qml.SWAP(wires=[0, 1]).inv().inv()), (g.SWAP(0, 1).controlled(2), qml.CSWAP(wires=[2, 0, 1])), (g.SWAP(0, 1).controlled(2).dagger(), qml.CSWAP(wires=[2, 0, 1]).inv()), (g.SWAP(0, 1).controlled(2).dagger().dagger(), qml.CSWAP(wires=[2, 0, 1]).inv().inv()), (g.ISWAP(0, 1), plf.ops.ISWAP(wires=[0, 1])), (g.ISWAP(0, 1).dagger(), plf.ops.ISWAP(wires=[0, 1]).inv()), (g.ISWAP(0, 1).dagger().dagger(), plf.ops.ISWAP(wires=[0, 1]).inv().inv()), (g.PSWAP(0.3, 0, 1), plf.ops.PSWAP(0.3, wires=[0, 1])), (g.PSWAP(0.3, 0, 1).dagger(), plf.ops.PSWAP(0.3, wires=[0, 1 ]).inv()), (g.PSWAP(0.3, 0, 1).dagger().dagger(), plf.ops.PSWAP(0.3, wires=[0, 1]).inv().inv()), (g.CZ(0, 1), qml.CZ(wires=[0, 1])), (g.CZ(0, 1).dagger(), qml.CZ(wires=[0, 1]).inv()), (g.CZ(0, 1).dagger().dagger(), qml.CZ(wires=[0, 1]).inv().inv()), (g.PHASE(0.3, 0), qml.PhaseShift(0.3, wires=[0])), (g.PHASE(0.3, 0).dagger(), qml.PhaseShift(0.3, wires=[0]).inv()), (g.PHASE(0.3, 0).dagger().dagger(), qml.PhaseShift( 0.3, wires=[0]).inv().inv()), (g.PHASE(0.3, 0).controlled(1), plf.ops.CPHASE( 0.3, 3, wires=[1, 0])), (g.PHASE(0.3, 0).controlled(1).dagger(), plf.ops.CPHASE(0.3, 3, wires=[1, 0]).inv()), ( g.PHASE(0.3, 0).controlled(1).dagger().dagger(), plf.ops.CPHASE(0.3, 3, wires=[1, 0]).inv().inv(), ), (g.RX(0.3, 0), qml.RX(0.3, wires=[0])), (g.RX(0.3, 0).dagger(), qml.RX(0.3, wires=[0]).inv()), (g.RX(0.3, 0).dagger().dagger(), qml.RX(0.3, wires=[0]).inv().inv()), (g.RX(0.3, 0).controlled(1), qml.CRX(0.3, wires=[1, 0])), (g.RX(0.3, 0).controlled(1).dagger(), qml.CRX(0.3, wires=[1, 0]).inv()), (g.RX(0.3, 0).controlled(1).dagger().dagger(), qml.CRX(0.3, wires=[1, 0]).inv().inv()), (g.RY(0.3, 0), qml.RY(0.3, wires=[0])), (g.RY(0.3, 0).dagger(), qml.RY(0.3, wires=[0]).inv()), (g.RY(0.3, 0).dagger().dagger(), qml.RY(0.3, wires=[0]).inv().inv()), (g.RY(0.3, 0).controlled(1), qml.CRY(0.3, wires=[1, 0])), (g.RY(0.3, 0).controlled(1).dagger(), qml.CRY(0.3, wires=[1, 0]).inv()), (g.RY(0.3, 0).controlled(1).dagger().dagger(), qml.CRY(0.3, wires=[1, 0]).inv().inv()), (g.RZ(0.3, 0), qml.RZ(0.3, wires=[0])), (g.RZ(0.3, 0).dagger(), qml.RZ(0.3, wires=[0]).inv()), (g.RZ(0.3, 0).dagger().dagger(), qml.RZ(0.3, wires=[0]).inv().inv()), (g.RZ(0.3, 0).controlled(1), qml.CRZ(0.3, wires=[1, 0])), (g.RZ(0.3, 0).controlled(1).dagger(), qml.CRZ(0.3, wires=[1, 0]).inv()), (g.RZ(0.3, 0).controlled(1).dagger().dagger(), qml.CRZ(0.3, wires=[1, 0]).inv().inv()), (g.CPHASE(0.3, 0, 1), plf.ops.CPHASE(0.3, 3, wires=[0, 1])), (g.CPHASE(0.3, 0, 1).dagger(), plf.ops.CPHASE(0.3, 3, wires=[0, 1]).inv()), ( g.CPHASE(0.3, 0, 1).dagger().dagger(), plf.ops.CPHASE(0.3, 3, wires=[0, 1]).inv().inv(), ), (g.CPHASE00(0.3, 0, 1), plf.ops.CPHASE(0.3, 0, wires=[0, 1])), (g.CPHASE00(0.3, 0, 1).dagger(), plf.ops.CPHASE(0.3, 0, wires=[0, 1]).inv()), ( g.CPHASE00(0.3, 0, 1).dagger().dagger(), plf.ops.CPHASE(0.3, 0, wires=[0, 1]).inv().inv(), ), (g.CPHASE01(0.3, 0, 1), plf.ops.CPHASE(0.3, 1, wires=[0, 1])), (g.CPHASE01(0.3, 0, 1).dagger(), plf.ops.CPHASE(0.3, 1, wires=[0, 1]).inv()), ( g.CPHASE01(0.3, 0, 1).dagger().dagger(), plf.ops.CPHASE(0.3, 1, wires=[0, 1]).inv().inv(), ), (g.CPHASE10(0.3, 0, 1), plf.ops.CPHASE(0.3, 2, wires=[0, 1])), (g.CPHASE10(0.3, 0, 1).dagger(), plf.ops.CPHASE(0.3, 2, wires=[0, 1]).inv()), ( g.CPHASE10(0.3, 0, 1).dagger().dagger(), plf.ops.CPHASE(0.3, 2, wires=[0, 1]).inv().inv(), ), (g.CSWAP(0, 1, 2), qml.CSWAP(wires=[0, 1, 2])), (g.CSWAP(0, 1, 2).dagger(), qml.CSWAP(wires=[0, 1, 2]).inv()), (g.CSWAP(0, 1, 2).dagger().dagger(), qml.CSWAP(wires=[0, 1, 2]).inv().inv()), (g.CCNOT(0, 1, 2), plf.ops.CCNOT(wires=[0, 1, 2])), (g.CCNOT(0, 1, 2).dagger(), plf.ops.CCNOT(wires=[0, 1, 2]).inv()), (g.CCNOT(0, 1, 2).dagger().dagger(), plf.ops.CCNOT(wires=[0, 1, 2]).inv().inv()), ], ) def test_convert_operation(self, pyquil_operation, expected_pl_operation): """Test that single pyquil gates are properly converted.""" program = pyquil.Program() program += pyquil_operation with OperationRecorder() as rec: loader = load_program(program) loader(wires=range(len(loader.defined_qubits))) assert rec.queue[0].name == expected_pl_operation.name assert rec.queue[0].wires == expected_pl_operation.wires assert rec.queue[0].params == expected_pl_operation.params def test_convert_simple_program(self): """Test that a simple program is properly converted.""" program = pyquil.Program() program += g.H(0) program += g.RZ(0.34, 1) program += g.CNOT(0, 3) program += g.H(2) program += g.H(7) program += g.X(7) program += g.Y(1) program += g.RZ(0.34, 1) with OperationRecorder() as rec: load_program(program)(wires=range(5)) # The wires should be assigned as # 0 1 2 3 7 # 0 1 2 3 4 expected_queue = [ qml.Hadamard(0), qml.RZ(0.34, wires=[1]), qml.CNOT(wires=[0, 3]), qml.Hadamard(2), qml.Hadamard(4), qml.PauliX(4), qml.PauliY(1), qml.RZ(0.34, wires=[1]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert converted.params == expected.params def test_convert_simple_program_with_parameters(self): """Test that a simple program with parameters is properly converted.""" program = pyquil.Program() alpha = program.declare("alpha", "REAL") beta = program.declare("beta", "REAL") gamma = program.declare("gamma", "REAL") program += g.H(0) program += g.CNOT(0, 1) program += g.RX(alpha, 1) program += g.RZ(beta, 1) program += g.RX(gamma, 1) program += g.CNOT(0, 1) program += g.H(0) a, b, c = 0.1, 0.2, 0.3 parameter_map = {"alpha": a, "beta": b, "gamma": c} with OperationRecorder() as rec: load_program(program)(wires=range(2), parameter_map=parameter_map) expected_queue = [ qml.Hadamard(0), qml.CNOT(wires=[0, 1]), qml.RX(0.1, wires=[1]), qml.RZ(0.2, wires=[1]), qml.RX(0.3, wires=[1]), qml.CNOT(wires=[0, 1]), qml.Hadamard(0), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert converted.params == expected.params def test_parameter_not_given_error(self): """Test that the correct error is raised if a parameter is not given.""" program = pyquil.Program() alpha = program.declare("alpha", "REAL") beta = program.declare("beta", "REAL") program += g.H(0) program += g.CNOT(0, 1) program += g.RX(alpha, 1) program += g.RZ(beta, 1) a = 0.1 parameter_map = {"alpha": a} with pytest.raises( qml.DeviceError, match= "The PyQuil program defines a variable .* that is not present in the given variable map", ): load_program(program)(wires=range(2), parameter_map=parameter_map) def test_convert_simple_program_with_parameters_mixed_keys(self): """Test that a parametrized program is properly converted when the variable map contains mixed key types.""" program = pyquil.Program() alpha = program.declare("alpha", "REAL") beta = program.declare("beta", "REAL") gamma = program.declare("gamma", "REAL") delta = program.declare("delta", "REAL") program += g.H(0) program += g.CNOT(0, 1) program += g.RX(alpha, 1) program += g.RZ(beta, 1) program += g.RX(gamma, 1) program += g.CNOT(0, 1) program += g.RZ(delta, 0) program += g.H(0) a, b, c, d = 0.1, 0.2, 0.3, 0.4 parameter_map = {"alpha": a, beta: b, gamma: c, "delta": d} with OperationRecorder() as rec: load_program(program)(wires=range(2), parameter_map=parameter_map) expected_queue = [ qml.Hadamard(0), qml.CNOT(wires=[0, 1]), qml.RX(0.1, wires=[1]), qml.RZ(0.2, wires=[1]), qml.RX(0.3, wires=[1]), qml.CNOT(wires=[0, 1]), qml.RZ(0.4, wires=[0]), qml.Hadamard(0), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert converted.params == expected.params def test_convert_simple_program_wire_assignment(self): """Test that the assignment of qubits to wires works as expected.""" program = pyquil.Program() program += g.H(0) program += g.RZ(0.34, 1) program += g.CNOT(0, 3) program += g.H(2) program += g.H(7) program += g.X(7) program += g.Y(1) program += g.RZ(0.34, 1) with OperationRecorder() as rec: load_program(program)(wires=[3, 6, 4, 9, 1]) # The wires should be assigned as # 0 1 2 3 7 # 3 6 4 9 1 expected_queue = [ qml.Hadamard(3), qml.RZ(0.34, wires=[6]), qml.CNOT(wires=[3, 9]), qml.Hadamard(4), qml.Hadamard(1), qml.PauliX(1), qml.PauliY(6), qml.RZ(0.34, wires=[6]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert converted.params == expected.params @pytest.mark.parametrize("wires", [[0, 1, 2, 3], [4, 5]]) def test_convert_wire_error(self, wires): """Test that the conversion raises an error if the given number of wires doesn't match the number of qubits in the Program.""" program = pyquil.Program() program += g.H(0) program += g.H(1) program += g.H(2) with pytest.raises( qml.DeviceError, match= "The number of given wires does not match the number of qubits in the PyQuil Program", ): load_program(program)(wires=wires) def test_convert_program_with_inverses(self): """Test that a program with inverses is properly converted.""" program = pyquil.Program() program += g.H(0) program += g.RZ(0.34, 1).dagger() program += g.CNOT(0, 3).dagger() program += g.H(2) program += g.H(7).dagger().dagger() program += g.X(7).dagger() program += g.X(7) program += g.Y(1) program += g.RZ(0.34, 1) with OperationRecorder() as rec: load_program(program)(wires=range(5)) expected_queue = [ qml.Hadamard(0), qml.RZ(0.34, wires=[1]).inv(), qml.CNOT(wires=[0, 3]).inv(), qml.Hadamard(2), qml.Hadamard(4), qml.PauliX(4).inv(), qml.PauliX(4), qml.PauliY(1), qml.RZ(0.34, wires=[1]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert converted.params == expected.params def test_convert_program_with_controlled_operations(self): """Test that a program with controlled operations is properly converted.""" program = pyquil.Program() program += g.RZ(0.34, 1) program += g.RY(0.2, 3).controlled(2) program += g.RX(0.4, 2).controlled(0) program += g.CNOT(1, 4) program += g.CNOT(1, 6).controlled(3) program += g.X(3).controlled(4).controlled(1) with OperationRecorder() as rec: load_program(program)(wires=range(6)) expected_queue = [ qml.RZ(0.34, wires=[1]), qml.CRY(0.2, wires=[2, 3]), qml.CRX(0.4, wires=[0, 2]), qml.CNOT(wires=[1, 4]), plf.ops.CCNOT(wires=[3, 1, 5]), plf.ops.CCNOT(wires=[1, 4, 3]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert converted.params == expected.params def test_convert_program_with_controlled_operations_not_in_pl_core( self, tol): """Test that a program with controlled operations out of scope of PL core/PLF is properly converted, i.e. the operations are replaced with controlled operations.""" program = pyquil.Program() CS_matrix = np.eye(4, dtype=complex) CS_matrix[3, 3] = 1j CCT_matrix = np.eye(8, dtype=complex) CCT_matrix[7, 7] = np.exp(1j * np.pi / 4) program += g.CNOT(0, 1) program += g.S(0).controlled(1) program += g.S(1).controlled(0) program += g.T(0).controlled(1).controlled(2) program += g.T(1).controlled(0).controlled(2) program += g.T(2).controlled(1).controlled(0) with OperationRecorder() as rec: load_program(program)(wires=range(3)) expected_queue = [ qml.CNOT(wires=[0, 1]), qml.QubitUnitary(CS_matrix, wires=[1, 0]), qml.QubitUnitary(CS_matrix, wires=[0, 1]), qml.QubitUnitary(CCT_matrix, wires=[2, 1, 0]), qml.QubitUnitary(CCT_matrix, wires=[2, 0, 1]), qml.QubitUnitary(CCT_matrix, wires=[0, 1, 2]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert np.allclose(converted.params, expected.params, atol=tol, rtol=0) def test_convert_program_with_controlled_dagger_operations(self): """Test that a program that combines controlled and daggered operations is properly converted.""" program = pyquil.Program() program += g.CNOT(0, 1).controlled(2) program += g.CNOT(0, 1).dagger().controlled(2) program += g.CNOT(0, 1).controlled(2).dagger() program += g.CNOT(0, 1).dagger().controlled(2).dagger() program += g.RX(0.3, 3).controlled(4) program += g.RX(0.2, 3).controlled(4).dagger() program += g.RX(0.3, 3).dagger().controlled(4) program += g.RX(0.2, 3).dagger().controlled(4).dagger() program += g.X(2).dagger().controlled(4).controlled(1).dagger() program += g.X(0).dagger().controlled(4).controlled(1) program += g.X(0).dagger().controlled(4).dagger().dagger().controlled( 1).dagger() with OperationRecorder() as rec: load_program(program)(wires=range(5)) expected_queue = [ plf.ops.CCNOT(wires=[2, 0, 1]), plf.ops.CCNOT(wires=[2, 0, 1]).inv(), plf.ops.CCNOT(wires=[2, 0, 1]).inv(), plf.ops.CCNOT(wires=[2, 0, 1]), qml.CRX(0.3, wires=[4, 3]), qml.CRX(0.2, wires=[4, 3]).inv(), qml.CRX(0.3, wires=[4, 3]).inv(), qml.CRX(0.2, wires=[4, 3]), plf.ops.CCNOT(wires=[1, 4, 2]), plf.ops.CCNOT(wires=[1, 4, 0]).inv(), plf.ops.CCNOT(wires=[1, 4, 0]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert converted.params == expected.params def test_convert_program_with_defgates(self): """Test that a program that defines its own gates is properly converted.""" program = pyquil.Program() sqrt_x = np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]]) sqrt_x_t2 = np.kron(sqrt_x, sqrt_x) sqrt_x_t3 = np.kron(sqrt_x, sqrt_x_t2) sqrt_x_definition = pyquil.quil.DefGate("SQRT-X", sqrt_x) SQRT_X = sqrt_x_definition.get_constructor() sqrt_x_t2_definition = pyquil.quil.DefGate("SQRT-X-T2", sqrt_x_t2) SQRT_X_T2 = sqrt_x_t2_definition.get_constructor() sqrt_x_t3_definition = pyquil.quil.DefGate("SQRT-X-T3", sqrt_x_t3) SQRT_X_T3 = sqrt_x_t3_definition.get_constructor() program += sqrt_x_definition program += sqrt_x_t2_definition program += sqrt_x_t3_definition program += g.CNOT(0, 1) program += SQRT_X(0) program += SQRT_X_T2(1, 2) program += SQRT_X_T3(1, 0, 2) program += g.CNOT(0, 1) program += g.CNOT(1, 2) program += g.CNOT(2, 0) with OperationRecorder() as rec: load_program(program)(wires=range(3)) expected_queue = [ qml.CNOT(wires=[0, 1]), qml.QubitUnitary(sqrt_x, wires=[0]), qml.QubitUnitary(sqrt_x_t2, wires=[1, 2]), qml.QubitUnitary(sqrt_x_t3, wires=[1, 0, 2]), qml.CNOT(wires=[0, 1]), qml.CNOT(wires=[1, 2]), qml.CNOT(wires=[2, 0]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert converted.params == expected.params def test_convert_program_with_controlled_defgates(self, tol): """Test that a program with controlled defined gates is properly converted.""" program = pyquil.Program() sqrt_x = np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]]) sqrt_x_t2 = np.kron(sqrt_x, sqrt_x) c_sqrt_x = np.eye(4, dtype=complex) c_sqrt_x[2:, 2:] = sqrt_x c_sqrt_x_t2 = np.eye(8, dtype=complex) c_sqrt_x_t2[4:, 4:] = sqrt_x_t2 sqrt_x_definition = pyquil.quil.DefGate("SQRT-X", sqrt_x) SQRT_X = sqrt_x_definition.get_constructor() sqrt_x_t2_definition = pyquil.quil.DefGate("SQRT-X-T2", sqrt_x_t2) SQRT_X_T2 = sqrt_x_t2_definition.get_constructor() program += sqrt_x_definition program += sqrt_x_t2_definition program += g.CNOT(0, 1) program += SQRT_X(0).controlled(1) program += SQRT_X_T2(1, 2).controlled(0) program += g.X(0).controlled(1) program += g.RX(0.4, 0) with OperationRecorder() as rec: load_program(program)(wires=range(3)) expected_queue = [ qml.CNOT(wires=[0, 1]), qml.QubitUnitary(c_sqrt_x, wires=[1, 0]), qml.QubitUnitary(c_sqrt_x_t2, wires=[0, 1, 2]), qml.CNOT(wires=[1, 0]), qml.RX(0.4, wires=[0]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert np.allclose(converted.params, expected.params, atol=tol, rtol=0) def test_convert_program_with_defpermutationgates(self): """Test that a program with gates defined via DefPermutationGate is properly converted.""" program = pyquil.Program() expected_matrix = np.eye(4) expected_matrix = expected_matrix[:, [1, 0, 3, 2]] x_plus_x_definition = pyquil.quil.DefPermutationGate( "X+X", [1, 0, 3, 2]) X_plus_X = x_plus_x_definition.get_constructor() program += x_plus_x_definition program += g.CNOT(0, 1) program += X_plus_X(0, 1) program += g.CNOT(0, 1) with OperationRecorder() as rec: load_program(program)(wires=range(2)) expected_queue = [ qml.CNOT(wires=[0, 1]), qml.QubitUnitary(expected_matrix, wires=[0, 1]), qml.CNOT(wires=[0, 1]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert np.array_equal(converted.params, expected.params) def test_convert_program_with_controlled_defpermutationgates(self): """Test that a program that uses controlled permutation gates is properly converted.""" program = pyquil.Program() expected_matrix = np.eye(4) expected_matrix = expected_matrix[:, [1, 0, 3, 2]] expected_controlled_matrix = np.eye(8) expected_controlled_matrix[4:, 4:] = expected_matrix x_plus_x_definition = pyquil.quil.DefPermutationGate( "X+X", [1, 0, 3, 2]) X_plus_X = x_plus_x_definition.get_constructor() program += x_plus_x_definition program += g.CNOT(0, 1) program += X_plus_X(0, 1).controlled(2) program += X_plus_X(1, 2).controlled(0) program += g.CNOT(0, 1) with OperationRecorder() as rec: load_program(program)(wires=range(3)) expected_queue = [ qml.CNOT(wires=[0, 1]), qml.QubitUnitary(expected_controlled_matrix, wires=[2, 0, 1]), qml.QubitUnitary(expected_controlled_matrix, wires=[0, 1, 2]), qml.CNOT(wires=[0, 1]), ] for converted, expected in zip(rec.queue, expected_queue): assert converted.name == expected.name assert converted.wires == expected.wires assert np.array_equal(converted.params, expected.params) def test_forked_gate_error(self): """Test that an error is raised if conversion of a forked gate is attempted.""" program = pyquil.Program() program += g.CNOT(0, 1) program += g.RX(0.3, 1).forked(2, [0.5]) program += g.CNOT(0, 1) with pytest.raises( qml.DeviceError, match= "Forked gates can not be imported into PennyLane, as this functionality is not supported", ): load_program(program)(wires=range(3))
def circuit(x): qml.RX(x, wires=[0]) qml.CNOT(wires=[0, 1]) qml.SWAP(wires=[1, 0]) qml.RZ(-0.2, wires=[1]) return qml.probs(wires=[0]), qml.var(qml.Hermitian(H, wires=1))