Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 42 additions & 2 deletions cirq-core/cirq/circuits/qasm_output_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,19 +270,39 @@ def __repr__(self):
return 'DummyCompositeOperation()'

return (
cirq.I(q0),
cirq.Z(q0),
cirq.Z(q0) ** 0.625,
cirq.Z(q0) ** 0,
cirq.Y(q0),
cirq.Y(q0) ** 0.375,
cirq.Y(q0) ** 0,
cirq.X(q0),
cirq.X(q0) ** 0.875,
cirq.H(q1),
cirq.X(q0) ** 0,
cirq.H(q0),
cirq.H(q0) ** 0,
cirq.X(q0) ** 0.5,
cirq.X(q0) ** -0.5,
cirq.S(q0),
cirq.Z(q0) ** -0.5,
cirq.T(q0),
cirq.Z(q0) ** -0.25,
cirq.Rx(rads=np.pi)(q0),
cirq.Rx(rads=np.pi / 2)(q0),
cirq.Rx(rads=np.pi / 4)(q0),
cirq.Ry(rads=np.pi)(q0),
cirq.Ry(rads=np.pi / 2)(q0),
cirq.Ry(rads=np.pi / 4)(q0),
cirq.Rz(rads=np.pi)(q0),
cirq.Rz(rads=np.pi / 2)(q0),
cirq.Rz(rads=np.pi / 4)(q0),
cirq.CZ(q0, q1),
cirq.CZ(q0, q1) ** 0.25, # Requires 2-qubit decomposition
cirq.CNOT(q0, q1),
cirq.CNOT(q0, q1) ** 0.5, # Requires 2-qubit decomposition
cirq.ControlledGate(cirq.Y)(q0, q1),
cirq.ControlledGate(cirq.H)(q0, q1),
cirq.SWAP(q0, q1),
cirq.SWAP(q0, q1) ** 0.75, # Requires 2-qubit decomposition
cirq.CCZ(q0, q1, q2),
Expand Down Expand Up @@ -356,15 +376,33 @@ def filter_unpredictable_numbers(text):
creg m_multi[3];


id q[0];
z q[0];
rz(pi*0.625) q[0];
rz(0) q[0];
y q[0];
ry(pi*0.375) q[0];
ry(0) q[0];
x q[0];
rx(pi*0.875) q[0];
h q[1];
rx(0) q[0];
h q[0];
id q[0];
sx q[0];
sxdg q[0];
s q[0];
sdg q[0];
t q[0];
tdg q[0];
rx(pi*1.0) q[0];
rx(pi*0.5) q[0];
rx(pi*0.25) q[0];
ry(pi*1.0) q[0];
ry(pi*0.5) q[0];
ry(pi*0.25) q[0];
rz(pi*1.0) q[0];
rz(pi*0.5) q[0];
rz(pi*0.25) q[0];
cz q[0],q[1];

// Gate: CZ**0.25
Expand Down Expand Up @@ -399,6 +437,8 @@ def filter_unpredictable_numbers(text):
u3(pi*0.5,pi*0.5,pi*1.0) q[1];
ry(pi*0.5) q[1];

cy q[0],q[1];
ch q[0],q[1];
swap q[0],q[1];

// Gate: SWAP**0.75
Expand Down
46 changes: 33 additions & 13 deletions cirq-core/cirq/ops/common_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,13 @@ def _circuit_diagram_info_(

def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
args.validate_version('2.0')
if self._exponent == 1 and self._global_shift != -0.5:
return args.format('x {0};\n', qubits[0])
elif self._exponent == 0.5:
return args.format('sx {0};\n', qubits[0])
elif self._exponent == -0.5:
return args.format('sxdg {0};\n', qubits[0])
if self._global_shift == 0:
if self._exponent == 1:
return args.format('x {0};\n', qubits[0])
elif self._exponent == 0.5:
return args.format('sx {0};\n', qubits[0])
elif self._exponent == -0.5:
return args.format('sxdg {0};\n', qubits[0])
return args.format('rx({0:half_turns}) {1};\n', self._exponent, qubits[0])

def _quil_(
Expand Down Expand Up @@ -308,6 +309,10 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return f'cirq.Rx(rads={proper_repr(self._rads)})'

def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
args.validate_version('2.0')
return args.format('rx({0:half_turns}) {1};\n', self._exponent, qubits[0])

def _json_dict_(self) -> Dict[str, Any]:
return {'rads': self._rads}

Expand Down Expand Up @@ -480,6 +485,10 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return f'cirq.Ry(rads={proper_repr(self._rads)})'

def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
args.validate_version('2.0')
return args.format('ry({0:half_turns}) {1};\n', self._exponent, qubits[0])

def _json_dict_(self) -> Dict[str, Any]:
return {'rads': self._rads}

Expand Down Expand Up @@ -654,13 +663,18 @@ def _circuit_diagram_info_(

def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
args.validate_version('2.0')
if self._exponent == 1 and self.global_shift != -0.5:
return args.format('z {0};\n', qubits[0])
elif self._exponent == 0.5:
return args.format('s {0};\n', qubits[0])
elif self._exponent == -0.5:
return args.format('sdg {0};\n', qubits[0])

if self.global_shift == 0:
if self._exponent == 1:
return args.format('z {0};\n', qubits[0])
elif self._exponent == 0.5:
return args.format('s {0};\n', qubits[0])
elif self._exponent == -0.5:
return args.format('sdg {0};\n', qubits[0])
elif self._exponent == 0.25:
return args.format('t {0};\n', qubits[0])
elif self._exponent == -0.25:
return args.format('tdg {0};\n', qubits[0])
return args.format('rz({0:half_turns}) {1};\n', self._exponent, qubits[0])

def _quil_(
Expand Down Expand Up @@ -756,6 +770,10 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return f'cirq.Rz(rads={proper_repr(self._rads)})'

def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
args.validate_version('2.0')
return args.format('rz({0:half_turns}) {1};\n', self._exponent, qubits[0])

def _json_dict_(self) -> Dict[str, Any]:
return {'rads': self._rads}

Expand Down Expand Up @@ -860,7 +878,9 @@ def _circuit_diagram_info_(

def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
args.validate_version('2.0')
if self._exponent == 1:
if self._exponent == 0:
return args.format('id {0};\n', qubits[0])
elif self._exponent == 1 and self._global_shift == 0:
return args.format('h {0};\n', qubits[0])

return args.format(
Expand Down
35 changes: 34 additions & 1 deletion cirq-core/cirq/ops/controlled_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,14 @@
import numpy as np

from cirq import protocols, qis, value
from cirq.ops import raw_types, gate_operation, controlled_gate, matrix_gates
from cirq.ops import (
controlled_gate,
common_gates,
eigen_gate,
gate_operation,
matrix_gates,
raw_types,
)
from cirq.type_workarounds import NotImplementedType

if TYPE_CHECKING:
Expand Down Expand Up @@ -186,6 +193,32 @@ def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> np.ndarray:
def _has_unitary_(self) -> bool:
return protocols.has_unitary(self.sub_operation)

def _qasm_(self, args: 'cirq.QasmArgs') -> Optional[str]:
if (
hasattr(self._sub_operation, "gate")
and len(self._controls) == 1
and self._control_values == ((1,),)
):
gate = self.sub_operation.gate
if (
isinstance(gate, eigen_gate.EigenGate)
and gate.exponent == 1
and gate.global_shift == 0
):
instr = None
if isinstance(gate, common_gates.XPowGate):
instr = 'cx {0},{1};\n'
elif isinstance(gate, common_gates.YPowGate):
instr = 'cy {0},{1};\n'
elif isinstance(gate, common_gates.ZPowGate):
instr = 'cz {0},{1};\n'
elif isinstance(gate, common_gates.HPowGate):
instr = 'ch {0},{1};\n'
if instr:
return args.format(instr, self._controls[0], self.sub_operation.qubits[0])
# Fallback to decompose.
return None

def _extend_matrix(self, sub_matrix: np.ndarray) -> np.ndarray:
qid_shape = protocols.qid_shape(self)
sub_n = len(qid_shape) - len(self.controls)
Expand Down