def _write_operations(self, op_tree: ops.OP_TREE, output: Callable[[str], None], output_line_gap: Callable[[int], None], top=True) -> None: for op in ops.flatten_op_tree(op_tree): out = protocols.qasm(op, args=self.args, default=None) if out is not None: output(out) continue if isinstance(op, ops.GateOperation): comment = 'Gate: {!s}'.format(op.gate) else: comment = 'Operation: {!s}'.format(op) decomp = protocols.decompose_once(op, None) if decomp is not None: if top: output_line_gap(1) output('// {}\n'.format(comment)) self._write_operations(decomp, output, output_line_gap, top=False) if top: output_line_gap(1) continue mat = protocols.unitary(op, None) if len(op.qubits) <= 2 else None if mat is not None and len(op.qubits) == 1: u_op = QasmUGate.from_matrix(mat).on(*op.qubits) if top: output_line_gap(1) output('// {}\n'.format(comment)) output(cast(str, protocols.qasm(u_op, args=self.args))) if top: output_line_gap(1) continue if mat is not None and len(op.qubits) == 2: u_op = QasmTwoQubitGate.from_matrix(mat).on(*op.qubits) if top: output_line_gap(1) output('// {}\n'.format(comment)) self._write_operations((u_op,), output, output_line_gap, top=False) if top: output_line_gap(1) continue raise ValueError('Cannot output operation as QASM: {!r}'.format(op))
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]: from cirq.circuits import qasm_output qasm_gate = qasm_output.QasmUGate(lmda=0.5 - self._axis_phase_exponent, theta=self._x_exponent, phi=self._z_exponent + self._axis_phase_exponent - 0.5) return protocols.qasm(qasm_gate, args=args, qubits=qubits)
def _qasm_(self, args: 'cirq.QasmArgs') -> Optional[str]: args.validate_version('2.0') if len(self._conditions) > 1: raise ValueError('QASM does not support multiple conditions.') subop_qasm = protocols.qasm(self._sub_operation, args=args) if not self._conditions: return subop_qasm return f'if ({self._conditions[0].qasm}) {subop_qasm}'
def _write_operations( self, op_tree: 'cirq.OP_TREE', output: Callable[[str], None], output_line_gap: Callable[[int], None], ) -> None: def keep(op: 'cirq.Operation') -> bool: return protocols.qasm(op, args=self.args, default=None) is not None def fallback(op): if len(op.qubits) not in [1, 2]: return NotImplemented mat = protocols.unitary(op, None) if mat is None: return NotImplemented if len(op.qubits) == 1: return QasmUGate.from_matrix(mat).on(*op.qubits) return QasmTwoQubitGate.from_matrix(mat).on(*op.qubits) def on_stuck(bad_op): return ValueError( 'Cannot output operation as QASM: {!r}'.format(bad_op)) for main_op in ops.flatten_op_tree(op_tree): decomposed = protocols.decompose(main_op, keep=keep, fallback_decomposer=fallback, on_stuck_raise=on_stuck) qasms = [protocols.qasm(op, args=self.args) for op in decomposed] should_annotate = decomposed != [main_op ] or qasms[0].count('\n') > 1 if should_annotate: output_line_gap(1) if isinstance(main_op, ops.GateOperation): x = str(main_op.gate).replace('\n', '\n //') output('// Gate: {!s}\n'.format(x)) else: x = str(main_op).replace('\n', '\n //') output('// Operation: {!s}\n'.format(x)) for qasm in qasms: output(qasm) if should_annotate: output_line_gap(1)
def keep(op: ops.Operation) -> bool: return protocols.qasm(op, args=self.args, default=None) is not None
def _qasm_(self, args: 'protocols.QasmArgs') -> Optional[str]: return protocols.qasm(self.sub_operation, args=args, default=None)
def _qasm_(self, args: 'protocols.QasmArgs') -> Optional[str]: return protocols.qasm(self.gate, args=args, qubits=self.qubits, default=None)
def assert_qasm_is_consistent_with_unitary(val: Any): """Uses `val._unitary_` to check `val._qasm_`'s behavior.""" # Only test if qiskit is installed. try: import qiskit except ImportError: # coverage: ignore warnings.warn("Skipped assert_qasm_is_consistent_with_unitary because " "qiskit isn't installed to verify against.") return unitary = protocols.unitary(val, None) if unitary is None: # Vacuous consistency. return controls = getattr(val, 'control_qubits', None) if controls is None: qubit_count = len(unitary).bit_length() - 1 else: qubit_count = len(unitary).bit_length() - 1 - (len(controls) - controls.count(None)) if isinstance(val, ops.Operation): qubits = val.qubits op = val elif isinstance(val, ops.Gate): qubits = tuple(line.LineQubit.range(qubit_count)) op = val.on(*qubits) else: raise NotImplementedError("Don't know how to test {!r}".format(val)) args = protocols.QasmArgs( qubit_id_map={q: 'q[{}]'.format(i) for i, q in enumerate(qubits)}) qasm = protocols.qasm(op, args=args, default=None) if qasm is None: return header = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[{}]; """.format(len(qubits)) qasm = header + qasm qasm_unitary = None try: result = qiskit.execute( qiskit.load_qasm_string(qasm), backend=qiskit.Aer.get_backend('unitary_simulator')) qasm_unitary = result.result().get_unitary() qasm_unitary = _reorder_indices_of_matrix( qasm_unitary, list(reversed(range(len(qubits))))) lin_alg_utils.assert_allclose_up_to_global_phase(qasm_unitary, unitary, rtol=1e-8, atol=1e-8) except Exception as ex: if qasm_unitary is not None: p_unitary, p_qasm_unitary = linalg.match_global_phase( unitary, qasm_unitary) else: p_unitary = None p_qasm_unitary = None raise AssertionError( 'QASM be consistent with cirq.unitary(op) up to global phase.\n\n' 'op:\n{}\n\n' 'cirq.unitary(op):\n{}\n\n' 'Generated QASM:\n\n{}\n\n' 'Unitary of generated QASM:\n{}\n\n' 'Phased matched cirq.unitary(op):\n{}\n\n' 'Phased matched unitary of generated QASM:\n{}\n\n' 'Underlying error:\n{}'.format(_indent(repr(op)), _indent(repr(unitary)), _indent(qasm), _indent(repr(qasm_unitary)), _indent(repr(p_unitary)), _indent(repr(p_qasm_unitary)), _indent(str(ex))))
def assert_qasm_is_consistent_with_unitary(val: Any): """Uses `val._unitary_` to check `val._qasm_`'s behavior.""" # Only test if qiskit is installed. try: import qiskit except ImportError: # coverage: ignore warnings.warn("Skipped assert_qasm_is_consistent_with_unitary because " "qiskit isn't installed to verify against.") return unitary = protocols.unitary(val, None) if unitary is None: # Vacuous consistency. return if isinstance(val, ops.Operation): qubits: Sequence[ops.Qid] = val.qubits op = val elif isinstance(val, ops.Gate): qid_shape = protocols.qid_shape(val) remaining_shape = list(qid_shape) controls = getattr(val, 'control_qubits', None) if controls is not None: for i, q in zip(reversed(range(len(controls))), reversed(controls)): if q is not None: remaining_shape.pop(i) qubits = devices.LineQid.for_qid_shape(remaining_shape) op = val.on(*qubits) else: raise NotImplementedError(f"Don't know how to test {val!r}") args = protocols.QasmArgs( qubit_id_map={q: f'q[{i}]' for i, q in enumerate(qubits)}) qasm = protocols.qasm(op, args=args, default=None) if qasm is None: return num_qubits = len(qubits) header = f""" OPENQASM 2.0; include "qelib1.inc"; qreg q[{num_qubits}]; """ qasm = header + qasm qasm_unitary = None try: result = qiskit.execute( qiskit.QuantumCircuit.from_qasm_str(qasm), backend=qiskit.Aer.get_backend('unitary_simulator'), ) qasm_unitary = result.result().get_unitary() qasm_unitary = _reorder_indices_of_matrix( qasm_unitary, list(reversed(range(num_qubits)))) lin_alg_utils.assert_allclose_up_to_global_phase(qasm_unitary, unitary, rtol=1e-8, atol=1e-8) except Exception as ex: if qasm_unitary is not None: p_unitary, p_qasm_unitary = linalg.match_global_phase( unitary, qasm_unitary) else: p_unitary = None p_qasm_unitary = None raise AssertionError( 'QASM not consistent with cirq.unitary(op) up to global phase.\n\n' 'op:\n{}\n\n' 'cirq.unitary(op):\n{}\n\n' 'Generated QASM:\n\n{}\n\n' 'Unitary of generated QASM:\n{}\n\n' 'Phased matched cirq.unitary(op):\n{}\n\n' 'Phased matched unitary of generated QASM:\n{}\n\n' 'Underlying error:\n{}'.format( _indent(repr(op)), _indent(repr(unitary)), _indent(qasm), _indent(repr(qasm_unitary)), _indent(repr(p_unitary)), _indent(repr(p_qasm_unitary)), _indent(str(ex)), ))
def _qasm_(self, args: 'cirq.QasmArgs') -> Optional[str]: args.validate_version('2.0') all_keys = " && ".join(c.qasm for c in self._conditions) return args.format('if ({0}) {1}', all_keys, protocols.qasm(self._sub_operation, args=args))