def test_def_circuit(): defcircuit = """ DEFCIRCUIT bell a b: H a CNOT a b """.strip() gate = "bell 0 1" defcircuit_no_qubits = """ DEFCIRCUIT bell: H 0 CNOT 0 1 """.strip() gate_no_qubits = "bell" defcircuit_param = """ DEFCIRCUIT parameterized(%theta, %phi) a: RX(%theta) a RZ(%phi) a """.strip() gate_param = "parameterized(0.0, 1.0) 0" parse_equals(defcircuit + "\n" + gate, RawInstr(defcircuit), Gate("bell", [], [Qubit(0), Qubit(1)])) parse_equals( defcircuit_no_qubits + "\n" + gate_no_qubits, RawInstr(defcircuit_no_qubits), RawInstr(gate_no_qubits), ) parse_equals( defcircuit_param + "\n" + gate_param, RawInstr(defcircuit_param), Gate("parameterized", [0.0, 1.0], [Qubit(0)]), )
def _resolve_gate(gate): """Resolve the given pyquil Gate as far as possible. For example, the gate ``CONTROLLED CONTROLLED X`` will be resolved to ``CCNOT``. The gate ``CONTROLLED CONTROLLED RX(0.3)`` will be resolved to ``CONTROLLED CRX(0.3)``. Args: gate (pyquil.quil.Gate): The gate that should be resolved Returns: pyquil.quil.Gate: The maximally resolved gate """ for i, modifier in enumerate(gate.modifiers): if modifier == "CONTROLLED": if gate.name in _control_map: stripped_gate = Gate(_control_map[gate.name], gate.params, gate.qubits) stripped_gate.modifiers = gate.modifiers.copy() del stripped_gate.modifiers[i] return _resolve_gate(stripped_gate) else: break return gate
def gate(self, modifiers, name, params, qubits): # TODO Don't like this. modifiers = modifiers or [] params = params or [] # Some gate modifiers increase the arity of the base gate. The # new qubit arguments prefix the old ones. modifier_qubits = [] for m in modifiers: if m in ["CONTROLLED", "FORKED"]: modifier_qubits.append(qubits[len(modifier_qubits)]) base_qubits = qubits[len(modifier_qubits):] forked_offset = len(params) >> modifiers.count("FORKED") base_params = params[:forked_offset] if name in QUANTUM_GATES: if base_params: gate = QUANTUM_GATES[name](*base_params, *base_qubits) else: gate = QUANTUM_GATES[name](*base_qubits) else: gate = Gate(name, base_params, base_qubits) for modifier in modifiers[::-1]: if modifier == "CONTROLLED": gate.controlled(modifier_qubits.pop()) elif modifier == "DAGGER": gate.dagger() elif modifier == "FORKED": gate.forked(modifier_qubits.pop(), params[forked_offset:(2 * forked_offset)]) forked_offset *= 2 else: raise ValueError(f"Unsupported gate modifier {modifier}.") return gate
def test_parameters(): parse_equals("RX(123) 0", RX(123, 0)) parse_equals("CPHASE00(0) 0 1", CPHASE00(0, 0, 1)) parse_equals("A(8,9) 0", Gate("A", [8, 9], [Qubit(0)])) parse_equals("A(8, 9) 0", Gate("A", [8, 9], [Qubit(0)]))
def test_simple_gate(): parse_equals("A 0", Gate("A", [], [Qubit(0)])) parse_equals("A 1 10 100", Gate("A", [], [Qubit(1), Qubit(10), Qubit(100)]))