def test_defgate(): dg = DefGate("TEST", np.array([[1., 0.], [0., 1.]])) assert dg.out() == "DEFGATE TEST:\n 1.0, 0.0\n 0.0, 1.0\n" test = dg.get_constructor() tg = test(DirectQubit(1), DirectQubit(2)) assert tg.out() == "TEST 1 2"
def test_defgate(): # regression test for https://github.com/rigetti/pyquil/issues/1059 theta = np.pi / 2 U = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, np.cos(theta / 2), -1j * np.sin(theta / 2)], [0, 0, -1j * np.sin(theta / 2), np.cos(theta / 2)]]) gate_definition = DefGate('U_test', U) U_test = gate_definition.get_constructor() p = Program() p += gate_definition p += X(1) p += U_test(1, 0) qam = PyQVM(n_qubits=2, quantum_simulator_type=NumpyWavefunctionSimulator) qam.execute(p) wf1 = qam.wf_simulator.wf should_be = np.zeros((2, 2), dtype=np.complex128) one_over_sqrt2 = 1 / np.sqrt(2) should_be[0, 1] = one_over_sqrt2 should_be[1, 1] = -1j * one_over_sqrt2 np.testing.assert_allclose(wf1, should_be) # Ensure the output of the custom U_test gate matches the standard RX gate. Something like # RX(theta, 0).controlled(1) would be a more faithful reproduction of U_test, but # NumpyWavefunctionSimulator doesn't (yet) support gate modifiers, so just apply the RX gate # unconditionally. p = Program() p += X(1) p += RX(theta, 0) qam = PyQVM(n_qubits=2, quantum_simulator_type=NumpyWavefunctionSimulator) qam.execute(p) wf2 = qam.wf_simulator.wf np.testing.assert_allclose(wf1, wf2)
def test_defgate(): dg = DefGate("TEST", np.array([[0 + 0.5j, 0.5], [0.5, 0 - 0.5j]])) assert dg.out( ) == "DEFGATE TEST:\n 0.0+0.5i, 0.5+0.0i\n 0.5+0.0i, 0.0-0.5i\n" test = dg.get_constructor() tg = test(DirectQubit(1), DirectQubit(2)) assert tg.out() == "TEST 1 2"
def controlled_i_X(n, a, b): theta = Parameter('theta') cirx = controlled_i( np.array([[quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [-1j * quil_sin(theta / 2), quil_cos(theta / 2)]])) CIRX = DefGate('CIRX', cirx, [theta]) return str(CIRX) + '\n' + str(CIRX.get_constructor()(n)(a, b))
def controlled_sY(program): csy = np.array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 0., -1.j], [0., 0., 1.j, 0.]]) dg = DefGate('CSY', csy) program.inst(dg) return dg.get_constructor()
def test_dagger(): # these gates are their own inverses p = Program().inst(I(0), X(0), Y(0), Z(0), H(0), CNOT(0, 1), CCNOT(0, 1, 2), SWAP(0, 1), CSWAP(0, 1, 2)) assert p.dagger().out() == 'CSWAP 0 1 2\nSWAP 0 1\n' \ 'CCNOT 0 1 2\nCNOT 0 1\nH 0\n' \ 'Z 0\nY 0\nX 0\nI 0\n' # these gates require negating a parameter p = Program().inst(PHASE(pi, 0), RX(pi, 0), RY(pi, 0), RZ(pi, 0), CPHASE(pi, 0, 1), CPHASE00(pi, 0, 1), CPHASE01(pi, 0, 1), CPHASE10(pi, 0, 1), PSWAP(pi, 0, 1)) assert p.dagger().out() == 'PSWAP(-pi) 0 1\n' \ 'CPHASE10(-pi) 0 1\n' \ 'CPHASE01(-pi) 0 1\n' \ 'CPHASE00(-pi) 0 1\n' \ 'CPHASE(-pi) 0 1\n' \ 'RZ(-pi) 0\n' \ 'RY(-pi) 0\n' \ 'RX(-pi) 0\n' \ 'PHASE(-pi) 0\n' # these gates are special cases p = Program().inst(S(0), T(0), ISWAP(0, 1)) assert p.dagger().out() == 'PSWAP(pi/2) 0 1\n' \ 'RZ(pi/4) 0\n' \ 'PHASE(-pi/2) 0\n' # must invert defined gates G = np.array([[0, 1], [0 + 1j, 0]]) p = Program().defgate("G", G).inst(("G", 0)) assert p.dagger().out() == 'DEFGATE G-INV:\n' \ ' 0.0, -i\n' \ ' 1.0, 0.0\n\n' \ 'G-INV 0\n' # can also pass in a list of inverses inv_dict = {"G": "J"} p = Program().defgate("G", G).inst(("G", 0)) assert p.dagger(inv_dict=inv_dict).out() == 'J 0\n' # defined parameterized gates cannot auto generate daggered version https://github.com/rigetticomputing/pyquil/issues/304 theta = Parameter('theta') gparam_matrix = np.array([[quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [-1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) g_param_def = DefGate('GPARAM', gparam_matrix, [theta]) p = Program(g_param_def) with pytest.raises(TypeError): p.dagger() # defined parameterized gates should passback parameters https://github.com/rigetticomputing/pyquil/issues/304 GPARAM = g_param_def.get_constructor() p = Program(GPARAM(pi)(1, 2)) assert p.dagger().out() == 'GPARAM-INV(pi) 1 2\n'
def test_def_gate(): sqrt_x = DefGate("SQRT-X", np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]])) hadamard = DefGate("HADAMARD", np.array([[1 / np.sqrt(2), 1 / np.sqrt(2)], [1 / np.sqrt(2), -1 / np.sqrt(2)]])) defgates = """ DEFGATE SQRT-X: 0.5+0.5i, 0.5-0.5i 0.5-0.5i, 0.5+0.5i DEFGATE HADAMARD: 1/SQRT(2), 1/SQRT(2) 1/SQRT(2), -1/SQRT(2) """.strip() parse_equals(defgates, sqrt_x, hadamard)
def controlled_Ry(program): theta = Parameter('theta') cry = np.array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., quil_cos(0.5 * theta), quil_sin(0.5 * theta)], [0., 0., -quil_sin(0.5 * theta), quil_cos(0.5 * theta)]]) dg = DefGate('CRY', cry, [theta]) program.inst(dg) return dg.get_constructor()
def get_combined_gate(matrix: np.ndarray, name: str) -> Gate: """ :param matrix: The matrix of the combined gate :param name: The of the combined gate :return: A Gate (matrix, noisy_name) corresponding to the representation [matrix, name] :rtype: Gate """ p = Program() combined_gate_definition = DefGate(name, matrix) p.inst(combined_gate_definition) combined_gate = combined_gate_definition.get_constructor() return combined_gate
def test_def_gate_with_parameters(): theta = Parameter('theta') rx = np.array([[quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [-1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) p = Program().defgate("RX", rx, [theta]) assert p.out() == 'DEFGATE RX(%theta):\n' \ ' cos(%theta/2), -i*sin(%theta/2)\n' \ ' -i*sin(%theta/2), cos(%theta/2)\n\n' dg = DefGate('MY_RX', rx, [theta]) MY_RX = dg.get_constructor() p = Program().inst(MY_RX(np.pi)(0)) assert p.out() == 'MY_RX(pi) 0\n'
def exitDefGate(self, ctx): # type: (QuilParser.DefGateContext) -> None gate_name = ctx.name().getText() if ctx.variable(): raise NotImplementedError("%variables are not supported yet") matrix = _matrix(ctx.matrix()) self.result.append(DefGate(gate_name, matrix))
def CRX_diags(n): M = np.identity(2**n).astype(object) parameters = [Parameter('p' + str(i)) for i in range(2**(n - 1))] for i, p in enumerate(parameters): M[2 * i:2 * (i + 1), 2 * i:2 * (i + 1)] = X(p) CRX_diag = DefGate('CRX_diag_{}'.format(n), M, parameters) return str(CRX_diag)
def test_def_gate_with_parameters(): theta = Parameter("theta") rx = np.array([ [quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [-1j * quil_sin(theta / 2), quil_cos(theta / 2)], ]) p = Program().defgate("RX", rx, [theta]) assert (p.out() == "DEFGATE RX(%theta):\n" " COS(%theta/2), -i*SIN(%theta/2)\n" " -i*SIN(%theta/2), COS(%theta/2)\n\n") dg = DefGate("MY_RX", rx, [theta]) MY_RX = dg.get_constructor() p = Program().inst(MY_RX(np.pi)(0)) assert p.out() == "MY_RX(pi) 0\n"
def state_two_prep(state, qubits): if not isinstance(state, Program): print("The input *state* must be in the form of a PyQuil Program") # Define the new gate from a matrix theta = Parameter('theta') crtest = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_cos(theta / 2), -quil_sin(theta / 2)], [0, 0, quil_sin(theta / 2), quil_cos(theta / 2)]]) gate_definition = DefGate('CRTEST', crtest, [theta]) CRTEST = gate_definition.get_constructor() state += gate_definition state += H(qubits[0]) state += Z(qubits[0]) state += CRTEST(np.pi / 42)(qubits[0], qubits[1]) return state
def exitDefGate(self, ctx: QuilParser.DefGateContext): gate_name = ctx.name().getText() gate_type = ctx.gatetype() if gate_type and gate_type.getText() == 'PERMUTATION': permutation = _permutation(ctx.matrix()) self.result.append(DefPermutationGate(gate_name, permutation)) else: matrix = _matrix(ctx.matrix()) parameters = [_variable(v) for v in ctx.variable()] self.result.append(DefGate(gate_name, matrix, parameters))
def defgate(self, name, matrix): """ Define a new static gate. :param name: (int) The name of the gate (str). :param matrix: List of lists or Numpy 2d array. :return: The Program instance. """ self.defined_gates.append(DefGate(name, matrix)) return self
def defgate(self, name, matrix): """ Define a new static gate. :param string name: The name of the gate. :param array-like matrix: List of lists or Numpy 2d array. :return: The Program instance. :rtype: Program """ self.defined_gates.append(DefGate(name, matrix)) return self
def test_def_gate_with_variables(): # Note that technically the RX gate includes -i instead of just i but this messes a bit with the test since # it's not smart enough to figure out that -1*i == -i theta = Parameter('theta') rx = np.array([[quil_cos(theta / 2), 1j * quil_sin(theta / 2)], [1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) defgate = 'DEFGATE RX(%theta):\n' \ ' cos(%theta/2), i*sin(%theta/2)\n' \ ' i*sin(%theta/2), cos(%theta/2)\n\n' parse_equals(defgate, DefGate('RX', rx, [theta]))
def test_def_gate_with_variables(): # Note that technically the RX gate includes -i instead of just i but this messes a bit with # the test since it's not smart enough to figure out that -1*i == -i theta = Parameter("theta") rx = np.array([ [quil_cos(theta / 2), 1j * quil_sin(theta / 2)], [1j * quil_sin(theta / 2), quil_cos(theta / 2)], ]) defgate = "DEFGATE RX(%theta):\n" " COS(%theta/2), i*SIN(%theta/2)\n" " i*SIN(%theta/2), COS(%theta/2)\n\n" parse_equals(defgate, DefGate("RX", rx, [theta]))
def create_CH(): """ Defining control RX pyquil Gate :return: instruction for CRZ """ ch = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1/sqrt(2), 1/sqrt(2)], [0, 0, 1/sqrt(2), -1/sqrt(2)]]) dg = DefGate('CH', ch) return dg
def u2_replacement(phi: float, lam: float): """ implemented with a custom gate """ # implemented with X90 pulse: https://qiskit.org/documentation/stubs/qiskit.circuit.library.U2Gate.html # p = Program() # p += RZ(phi + np.pi/2, 0) # p += RX(np.pi/2, 0) # p += RZ(lam - np.pi/2, 0) phi_param = Parameter('phi') lam_param = Parameter('lam') matrix = np.array( [[1 / np.sqrt(2), -quil_exp(1j * lam_param) * 1 / np.sqrt(2)], [ quil_exp(1j * phi_param) * 1 / np.sqrt(2), quil_exp(1j * (phi_param + lam_param)) * 1 / np.sqrt(2) ]]) definition = DefGate('U2', matrix, [phi_param, lam_param]) U2 = definition.get_constructor() p = Program() p += definition p += U2(phi, lam)(0) return p
def u3_replacement(theta: float, phi: float, lam: float): """ implemented with a custom gate """ # implemented with two X90 pulse: https://arxiv.org/pdf/1707.03429.pdf # p = Program() # p += RZ(phi + 3*np.pi, 0) # p += RX(np.pi/2, 0) # p += RZ(np.pi + theta, 0) # p += RX(np.pi/2, 0) # p += RZ(lam, 0) # formula from https://qiskit.org/documentation/stubs/qiskit.circuit.library.U3Gate.html (13.07.2020) gives wrong results # p = Program() # p += RZ(phi - np.pi/2, 0) # p += RX(np.pi/2, 0) # p += RZ(np.pi - theta, 0) # p += RX(np.pi/2, 0) # p += RZ(lam - np.pi/2, 0) theta_param = Parameter('theta') phi_param = Parameter('phi') lam_param = Parameter('lam') matrix = np.array( [[ quil_cos(theta_param / 2), -quil_exp(1j * lam_param) * quil_sin(theta_param / 2) ], [ quil_exp(1j * phi_param) * quil_sin(theta_param / 2), quil_exp(1j * (phi_param + lam_param)) * quil_cos(theta_param / 2) ]]) definition = DefGate('U3', matrix, [theta_param, phi_param, lam_param]) U3 = definition.get_constructor() p = Program() p += definition p += U3(theta, phi, lam)(0) return p
def create_CRX(): """ Defining control RX pyquil Gate :return: instruction for CRX """ theta = Parameter('theta') crx = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_cos(theta / 2), -1j * quil_sin(theta / 2)], [0, 0, -1j * quil_sin(theta / 2), quil_cos(theta / 2)]]) dg = DefGate('CRX', crx, [theta]) return dg
def create_CRZ(): """ Defining control RX pyquil Gate :return: instruction for CRZ """ theta = Parameter('theta') crz = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, quil_exp(-1j*theta / 2), 0], [0, 0, 0, quil_exp(1j*theta / 2)]]) dg = DefGate('CRZ', crz, [theta]) return dg
def defgate(self, name, matrix, parameters=None): """ Define a new static gate. .. note:: The matrix elements along each axis are ordered by bitstring. For two qubits the order is ``00, 01, 10, 11``, where the the bits **are ordered in reverse** by the qubit index, i.e., for qubits 0 and 1 the bitstring ``01`` indicates that qubit 0 is in the state 1. See also :ref:`the related documentation section in the QVM Overview <basis-ordering>`. :param string name: The name of the gate. :param array-like matrix: List of lists or Numpy 2d array. :param list parameters: list of parameters that are used in this gate :return: The Program instance. :rtype: Program """ return self.inst(DefGate(name, matrix, parameters))
def defgate( self, name: str, matrix: Union[List[List[Any]], np.ndarray, np.matrix], parameters: Optional[List[Parameter]] = None, ) -> "Program": """ Define a new static gate. .. note:: The matrix elements along each axis are ordered by bitstring. For two qubits the order is ``00, 01, 10, 11``, where the the bits **are ordered in reverse** by the qubit index, i.e., for qubits 0 and 1 the bitstring ``01`` indicates that qubit 0 is in the state 1. See also :ref:`the related docs in the WavefunctionSimulator Overview <basis_ordering>`. :param name: The name of the gate. :param matrix: List of lists or Numpy 2d array. :param parameters: list of parameters that are used in this gate :return: The Program instance. """ return self.inst(DefGate(name, matrix, parameters))
def def_gate_matrix(self, name, variables, matrix): return DefGate(name, matrix=matrix, parameters=variables)
def test_prog_merge(): prog_0 = Program(X(0)) prog_1 = Program(Y(0)) assert merge_programs([prog_0, prog_1]).out() == (prog_0 + prog_1).out() test_def = DefGate("test", np.eye(2)) TEST = test_def.get_constructor() prog_0.inst(test_def) prog_0.inst(TEST(0)) prog_1.inst(test_def) prog_1.inst(TEST(0)) assert (merge_programs([prog_0, prog_1]).out() == """DEFGATE test: 1.0, 0 0, 1.0 X 0 test 0 Y 0 test 0 """) perm_def = DefPermutationGate("PERM", [0, 1, 3, 2]) PERM = perm_def.get_constructor() prog_0.inst(perm_def) prog_0.inst(PERM(0, 1)) prog_1.inst(perm_def) prog_1.inst(PERM(1, 0)) assert (merge_programs([prog_0, prog_1]).out() == """DEFGATE PERM AS PERMUTATION: 0, 1, 3, 2 DEFGATE test: 1.0, 0 0, 1.0 X 0 test 0 PERM 0 1 Y 0 test 0 PERM 1 0 """) assert (merge_programs([ Program("DECLARE ro BIT[1]"), Program("H 0"), Program("MEASURE 0 ro[0]") ]).out() == """DECLARE ro BIT[1] H 0 MEASURE 0 ro[0] """) q0 = QubitPlaceholder() q0_str = "{" + str(q0) + "}" p0 = Program(X(q0)) p1 = Program(Z(q0)) merged = merge_programs([p0, p1]) assert (str(merged) == f"""X {q0_str} Z {q0_str} """) assert (address_qubits(merged, {q0: 1}).out() == """X 1 Z 1 """) q1 = QubitPlaceholder() p2 = Program(Z(q1)) assert (address_qubits(merge_programs([p0, p2]), { q0: 1, q1: 2 }).out() == """X 1 Z 2 """) p0 = address_qubits(p0, {q0: 2}) p1 = address_qubits(p1, {q0: 1}) assert (merge_programs([p0, p1]).out() == """X 2 Z 1 """)
def test_defgate_param(): dgp = DefGate("TEST", [[1.0, 0.0], [0.0, 1.0]]) assert dgp.out() == "DEFGATE TEST:\n 1.0, 0\n 0, 1.0\n" test = dgp.get_constructor() tg = test(Qubit(1)) assert tg.out() == "TEST 1"
def test_defgate_non_unitary_should_throw_error(): with pytest.raises(ValueError) as error_info: DefGate("TEST", np.array([[0, 1], [2, 3]])) assert str(error_info.value) == "Matrix must be unitary."
from pyquil.quil import Program from pyquil.gates import * from pyquil.parameters import Parameter, quil_sin, quil_cos from pyquil.quilbase import DefGate #from pyquil.api import QVMConnection from referenceqvm.api import QVMConnection import numpy as np theta = Parameter('theta') cry = np.array([[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, quil_cos( theta / 2), -1 * quil_sin(theta / 2)], [0.0, 0.0, quil_sin(theta / 2), quil_cos(theta / 2)]]) dg = DefGate('CRY', cry, [theta]) CRY = dg.get_constructor() p = Program() p.inst(dg) p.inst(X(0)) p.inst(X(1)) p.inst(CRY(4.304)(0, 2)) qvm = QVMConnection() wf = qvm.wavefunction(p) print(wf)