def test_single_qubit_matrix_to_native_gates_tolerance_z(): z = np.diag([1, np.exp(1j * 0.01)]) optimized_away = decompositions.single_qubit_matrix_to_native_gates( z, tolerance=0.1) assert len(optimized_away) == 0 kept = decompositions.single_qubit_matrix_to_native_gates(z, tolerance=0.0001) assert len(kept) == 1
def test_single_qubit_matrix_to_native_gates_tolerance_xy(): c, s = np.cos(0.01), np.sin(0.01) xy = np.array([[c, -s], [s, c]]) optimized_away = decompositions.single_qubit_matrix_to_native_gates( xy, tolerance=0.1) assert len(optimized_away) == 0 kept = decompositions.single_qubit_matrix_to_native_gates(xy, tolerance=0.0001) assert len(kept) == 1
def test_single_qubit_matrix_to_native_gates_tolerance_half_turn_phasing(): a = np.pi / 2 + 0.01 c, s = np.cos(a), np.sin(a) nearly_x = np.array([[c, -s], [s, c]]) z1 = np.diag([1, np.exp(1j * 1.2)]) z2 = np.diag([1, np.exp(1j * 1.6)]) phased_nearly_x = z1.dot(nearly_x).dot(z2) optimized_away = decompositions.single_qubit_matrix_to_native_gates( phased_nearly_x, tolerance=0.1) assert len(optimized_away) == 1 kept = decompositions.single_qubit_matrix_to_native_gates(phased_nearly_x, tolerance=0.0001) assert len(kept) == 2
def test_single_qubit_matrix_to_native_gates_tolerance_half_turn_phasing(): a = np.pi / 2 + 0.01 c, s = np.cos(a), np.sin(a) nearly_x = np.array([[c, -s], [s, c]]) z1 = np.diag([1, np.exp(1j * 1.2)]) z2 = np.diag([1, np.exp(1j * 1.6)]) phased_nearly_x = z1.dot(nearly_x).dot(z2) optimized_away = decompositions.single_qubit_matrix_to_native_gates( phased_nearly_x, tolerance=0.1) assert len(optimized_away) == 1 kept = decompositions.single_qubit_matrix_to_native_gates( phased_nearly_x, tolerance=0.0001) assert len(kept) == 2
def _convert_one(self, op: ops.Operation) -> ops.OP_TREE: # Already supported? if isinstance(op.gate, XmonGate): return op # Maybe we know how to wrap it? xmon = self.extensions.try_cast(op.gate, XmonGate) if xmon is not None: return xmon.on(*op.qubits) # Known matrix? mat = self.extensions.try_cast(op.gate, ops.KnownMatrixGate) if mat is not None and len(op.qubits) == 1: gates = single_qubit_matrix_to_native_gates(mat.matrix()) return [g.on(op.qubits[0]) for g in gates] if mat is not None and len(op.qubits) == 2: return two_qubit_matrix_to_native_gates(op.qubits[0], op.qubits[1], mat.matrix(), allow_partial_czs=True) # Provides a decomposition? composite = self.extensions.try_cast(op.gate, ops.CompositeGate) if composite is not None: return composite.default_decompose(op.qubits) # Just let it be? if self.ignore_failures: return op raise TypeError("Don't know how to work with {!r}. " "It isn't an XmonGate, " "1-qubit KnownMatrixGate, " "2-qubit KnownMatrixGate, " "or CompositeGate.".format(op))
def _merge_rotations( self, qubit: ops.QubitId, operations: Iterable[ops.Operation]) -> List[ops.Operation]: matrix = linalg.dot( np.eye(2, dtype=np.complex128), *reversed([protocols.unitary(op) for op in operations])) out_gates = single_qubit_matrix_to_native_gates(matrix, self.tolerance) return [gate(qubit) for gate in out_gates]
def _merge_rotations( self, qubit: ops.QubitId, operations: Iterable[ops.KnownMatrix]) -> List[ops.Operation]: matrix = np.eye(2, dtype=np.complex128) for op in operations: matrix = np.dot(op.matrix(), matrix) out_gates = single_qubit_matrix_to_native_gates(matrix, self.tolerance) return [gate(qubit) for gate in out_gates]
def test_single_qubit_matrix_to_native_gates_fuzz_half_turns_always_one_gate( pre_turns, post_turns): intended_effect = cirq.dot( cirq.RotZGate(half_turns=2 * pre_turns).matrix(), cirq.X.matrix(), cirq.RotZGate(half_turns=2 * post_turns).matrix()) gates = decompositions.single_qubit_matrix_to_native_gates( intended_effect, tolerance=0.0001) assert len(gates) == 1 assert_gates_implement_unitary(gates, intended_effect)
def _convert_one(self, op: ops.Operation) -> ops.OP_TREE: # Known matrix? mat = protocols.unitary(op, None) if len(op.qubits) <= 2 else None if mat is not None and len(op.qubits) == 1: gates = single_qubit_matrix_to_native_gates(mat) return [g.on(op.qubits[0]) for g in gates] if mat is not None and len(op.qubits) == 2: return two_qubit_matrix_to_operations(op.qubits[0], op.qubits[1], mat, allow_partial_czs=True) return NotImplemented
def _convert_one(self, op: ops.Operation) -> ops.OP_TREE: # Maybe we know how to wrap it? if isinstance(op, ops.GateOperation): xmon = xmon_gate_ext.try_cast(XmonGate, op.gate) # type: ignore if xmon is not None: return xmon.on(*op.qubits) # Known matrix? mat = protocols.unitary(op, None) if len(op.qubits) <= 2 else None if mat is not None and len(op.qubits) == 1: gates = single_qubit_matrix_to_native_gates(mat) return [g.on(op.qubits[0]) for g in gates] if mat is not None and len(op.qubits) == 2: return two_qubit_matrix_to_operations(op.qubits[0], op.qubits[1], mat, allow_partial_czs=True) return NotImplemented
def _convert_one(self, op: ops.Operation) -> ops.OP_TREE: # Already supported? if isinstance(op, ops.GateOperation) and isinstance(op.gate, XmonGate): return op # Maybe we know how to wrap it? if isinstance(op, ops.GateOperation): xmon = self.extensions.try_cast(XmonGate, op.gate) if xmon is not None: return xmon.on(*op.qubits) # Known matrix? mat = self.extensions.try_cast(ops.KnownMatrix, op) if mat is not None and len(op.qubits) == 1: gates = single_qubit_matrix_to_native_gates(mat.matrix()) return [g.on(op.qubits[0]) for g in gates] if mat is not None and len(op.qubits) == 2: return two_qubit_matrix_to_operations( op.qubits[0], op.qubits[1], mat.matrix(), allow_partial_czs=True) # Provides a decomposition? composite_op = self.extensions.try_cast(ops.CompositeOperation, op) if composite_op is not None: return composite_op.default_decompose() # Just let it be? if self.ignore_failures: return op raise TypeError("Don't know how to work with {!r}. " "It isn't a GateOperation with an XmonGate, " "a 1-qubit KnownMatrix, " "a 2-qubit KnownMatrix, " "or a CompositeOperation.".format(op))
def _convert_one(self, op: ops.Operation) -> ops.OP_TREE: # Already supported? if XmonGate.is_supported_op(op): return op # Maybe we know how to wrap it? if isinstance(op, ops.GateOperation): xmon = xmon_gate_ext.try_cast(XmonGate, op.gate) # type: ignore if xmon is not None: return xmon.on(*op.qubits) # Known matrix? mat = protocols.unitary(op, None) if len(op.qubits) <= 2 else None if mat is not None and len(op.qubits) == 1: gates = single_qubit_matrix_to_native_gates(mat) return [g.on(op.qubits[0]) for g in gates] if mat is not None and len(op.qubits) == 2: return two_qubit_matrix_to_operations(op.qubits[0], op.qubits[1], mat, allow_partial_czs=True) # Provides a decomposition? composite_op = xmon_gate_ext.try_cast( # type: ignore ops.CompositeOperation, op) if composite_op is not None: return composite_op.default_decompose() # Just let it be? if self.ignore_failures: return op raise TypeError("Don't know how to work with {!r}. " "It isn't a GateOperation with an XmonGate, " "a 1 or 2 qubit gate with a known unitary, " "or a CompositeOperation.".format(op))
def test_single_qubit_matrix_to_native_gates_known_y(): actual = decompositions.single_qubit_matrix_to_native_gates( np.array([[0, -1j], [1j, 0]]), tolerance=0.01) assert actual == [cirq.Y]
def test_single_qubit_matrix_to_native_gates_cases(intended_effect): gates = decompositions.single_qubit_matrix_to_native_gates( intended_effect, tolerance=0.0001) assert len(gates) <= 2 assert_gates_implement_unitary(gates, intended_effect)
def test_known_h(): actual = decompositions.single_qubit_matrix_to_native_gates( np.array([[1, 1], [1, -1]]) * np.sqrt(0.5), tolerance=0.001) assert actual == [cirq.Y**-0.5, cirq.Z]
def test_known_s_dag(): actual = decompositions.single_qubit_matrix_to_native_gates(np.array( [[1, 0], [0, -1j]]), tolerance=0.01) assert actual == [cirq.Z**-0.5]
def test_single_qubit_matrix_to_native_gates_known_y(): actual = decompositions.single_qubit_matrix_to_native_gates(np.array( [[0, -1j], [1j, 0]]), tolerance=0.01) assert actual == [cirq.Y]
def test_known_s_dag(): actual = decompositions.single_qubit_matrix_to_native_gates( np.array([[1, 0], [0, -1j]]), tolerance=0.01) assert actual == [cirq.Z**-0.5]
def test_single_qubit_matrix_to_native_gates_known_s(): actual = decompositions.single_qubit_matrix_to_native_gates(np.array( [[1, 0], [0, 1j]]), tolerance=0.01) assert actual == [ops.Z**0.5]