def on(self, params: List[float], args: List[List[ops.Qid]], lineno: int) -> Iterable[ops.Operation]: self._validate_args(args, lineno) self._validate_params(params, lineno) reg_sizes = np.unique([len(reg) for reg in args]) if len(reg_sizes) > 2 or (len(reg_sizes) > 1 and reg_sizes[0] != 1): raise QasmException("Non matching quantum registers of length {} " "at line {}".format(reg_sizes, lineno)) # the actual gate we'll apply the arguments to might be a parameterized # or non-parametrized gate final_gate = (self.cirq_gate if isinstance(self.cirq_gate, ops.Gate) else self.cirq_gate(params)) # type: ops.Gate # OpenQASM gates can be applied on single qubits and qubit registers. # We represent single qubits as registers of size 1. # Based on the OpenQASM spec (https://arxiv.org/abs/1707.03429), # single qubit arguments can be mixed with qubit registers. # Given quantum registers of length reg_size and single qubits are both # used as arguments, we generate reg_size GateOperations via iterating # through each qubit of the registers 0 to n-1 and use the same one # qubit from the "single-qubit registers" for each operation. op_qubits = cast(Sequence[Sequence[ops.Qid]], functools.reduce(np.broadcast, args)) for qubits in op_qubits: if isinstance(qubits, ops.Qid): yield final_gate.on(qubits) elif len(np.unique(qubits)) < len(qubits): raise QasmException("Overlapping qubits in arguments" " at line {}".format(lineno)) else: yield final_gate.on(*qubits)
def p_error(self, p): if p is None: raise QasmException('Unexpected end of file') raise QasmException(f"""Syntax error: '{p.value}' {self.debug_context(p)} at line {p.lineno}, column {self.find_column(p)}""")
def p_error(self, p): if p is None: raise QasmException('Unexpected end of file') raise QasmException("""Syntax error: '{}' {} at line {}, column {}""".format(p.value, self.debug_context(p), p.lineno, self.find_column(p)))
def p_new_reg(self, p): """new_reg : QREG ID '[' NATURAL_NUMBER ']' ';' | CREG ID '[' NATURAL_NUMBER ']' ';'""" name, length = p[2], p[4] if name in self.qregs.keys() or name in self.cregs.keys(): raise QasmException(f"{name} is already defined at line {p.lineno(2)}") if length == 0: raise QasmException(f"Illegal, zero-length register '{name}' at line {p.lineno(4)}") if p[1] == "qreg": self.qregs[name] = length else: self.cregs[name] = length p[0] = (name, length)
def _validate_params(self, params: List[float], lineno: int): if len(params) != self.num_params: raise QasmException( "{} takes {} parameter(s), got: {}, at line {}".format( self.qasm_gate, self.num_params, len(params), lineno ) )
def p_classical_arg_register(self, p): """carg : ID""" reg = p[1] if reg not in self.cregs.keys(): raise QasmException(f'Undefined classical register "{reg}" at line {p.lineno(1)}') p[0] = [self.make_name(idx, reg) for idx in range(self.cregs[reg])]
def p_format(self, p): """format : FORMAT_SPEC""" if p[1] != "2.0": raise QasmException( "Unsupported OpenQASM version: {}, " "only 2.0 is supported currently by Cirq".format(p[1]) )
def p_expr_function_call(self, p): """expr : ID '(' expr ')'""" func = p[1] if func not in self.functions.keys(): raise QasmException( f"Function not recognized: '{func}' at line {p.lineno(1)}") p[0] = self.functions[func](p[3])
def p_classical_arg_bit(self, p): """carg : ID '[' NATURAL_NUMBER ']' """ reg = p[1] idx = p[3] arg_name = self.make_name(idx, reg) if reg not in self.cregs.keys(): raise QasmException('Undefined classical register "{}" ' 'at line {}'.format(reg, p.lineno(1))) size = self.cregs[reg] if idx >= size: raise QasmException('Out of bounds bit index {} ' 'on classical register {} of size {} ' 'at line {}'.format(idx, reg, size, p.lineno(1))) p[0] = [arg_name]
def p_quantum_arg_bit(self, p): """qarg : ID '[' NATURAL_NUMBER ']' """ reg = p[1] idx = p[3] arg_name = self.make_name(idx, reg) if reg not in self.qregs.keys(): raise QasmException('Undefined quantum register "{}" ' 'at line {}'.format(reg, p.lineno(1))) size = self.qregs[reg] if idx >= size: raise QasmException('Out of bounds qubit index {} ' 'on register {} of size {} ' 'at line {}'.format(idx, reg, size, p.lineno(1))) if arg_name not in self.qubits.keys(): self.qubits[arg_name] = NamedQubit(arg_name) p[0] = [self.qubits[arg_name]]
def _resolve_gate_operation(self, args: List[List[ops.Qid]], gate: str, p: Any, params: List[float]): gate_set = (self.basic_gates if not self.qelibinc else self.all_gates) if gate not in gate_set.keys(): msg = 'Unknown gate "{}" at line {}{}'.format( gate, p.lineno(1), ", did you forget to include qelib1.inc?" if not self.qelibinc else "") raise QasmException(msg) p[0] = gate_set[gate].on(args=args, params=params, lineno=p.lineno(1))
def _resolve_gate_operation(self, args: List[List[ops.Qid]], gate: str, p: Any, params: List[float]): if gate not in self.basic_gates.keys(): raise QasmException('Unknown gate "{}" at line {}, ' 'maybe you forgot to include ' 'the standard qelib1.inc?'.format( gate, p.lineno(1))) p[0] = self.basic_gates[gate].on(args=args, params=params, lineno=p.lineno(1))
def p_quantum_arg_register(self, p): """qarg : ID""" reg = p[1] if reg not in self.qregs.keys(): raise QasmException(f'Undefined quantum register "{reg}" at line {p.lineno(1)}') qubits = [] for idx in range(self.qregs[reg]): arg_name = self.make_name(idx, reg) if arg_name not in self.qubits.keys(): self.qubits[arg_name] = NamedQubit(arg_name) qubits.append(self.qubits[arg_name]) p[0] = qubits
def p_new_reg(self, p): """new_reg : QREG ID '[' NATURAL_NUMBER ']' ';' | CREG ID '[' NATURAL_NUMBER ']' ';'""" name, length = p[2], p[4] if name in self.qregs.keys() or name in self.cregs.keys(): raise QasmException("{} is already defined " "at line {}".format(name, p.lineno(2))) if p[1] == "qreg": self.qregs[name] = length else: self.cregs[name] = length p[0] = (name, length)
def p_measurement(self, p): """measurement : MEASURE qarg ARROW carg ';'""" qreg = p[2] creg = p[4] if len(qreg) != len(creg): raise QasmException( 'mismatched register sizes {} -> {} for measurement ' 'at line {}'.format(len(qreg), len(creg), p.lineno(1))) p[0] = [ ops.MeasurementGate(num_qubits=1, key=creg[i]).on(qreg[i]) for i in range(len(qreg)) ]
def t_error(self, t): raise QasmException("Illegal character '{}' at line {}".format( t.value[0], t.lineno))
def t_error(self, t): raise QasmException(f"Illegal character '{t.value[0]}' at line {t.lineno}")
def _validate_args(self, args: List[List[ops.Qid]], lineno: int): if len(args) != self.num_args: raise QasmException( "{} only takes {} arg(s) (qubits and/or registers), " "got: {}, at line {}".format(self.qasm_gate, self.num_args, len(args), lineno))
def p_qasm_no_format_specified_error(self, p): """qasm : QELIBINC | circuit """ if self.supported_format is False: raise QasmException("Missing 'OPENQASM 2.0;' statement")