Optimizer failure
Description of the issue
The optimize_for_target_gateset crashes when trying to optimize XXPowGate with larger global shift value. The optimizer crashes with division by zero error.
How to reproduce the issue
import cirq as c
qubits = c.LineQubit.range(4)
circuit = c.Circuit()
circuit.append(c.rz(-0.0171*np.pi)(qubits[0]))
circuit.append(c.CNOT(qubits[3], qubits[1]))
circuit.append(c.MSGate(rads=-0.01*np.pi)(qubits[0], qubits[1]))
circuit.append(c.Y(qubits[0]))
circuit.append(c.CSWAP(qubits[2], qubits[0], qubits[3]))
circuit.append(c.Ry(rads=0.014*np.pi)(qubits[2]))
circuit.append(c.Z(qubits[3]))
circuit.append(c.ISWAP(qubits[0], qubits[2]))
circuit.append(c.XX(qubits[1], qubits[3]))
circuit.append(c.XXPowGate(exponent=0.26, global_shift=100000)(qubits[2], qubits[3]))
circuit.append(c.ISWAP(qubits[0], qubits[2]))
circuit.append(c.Ry(rads=-0.042*np.pi)(qubits[3]))
print(circuit)
optimized = c.optimize_for_target_gateset(circuit, gateset = cg.SycamoreTargetGateset())
print(optimized)
┌───────┐
0: ───Rz(-0.017π)───MS(-0.01π)───Y───×─────────────────iSwap────────────────iSwap─────────
│ │ │ │
1: ───X─────────────MS(-0.01π)───────┼─────────────────┼────XX──────────────┼─────────────
│ │ │ │ │
2: ───┼──────────────────────────────@───Ry(0.014π)────iSwap┼─────XX────────iSwap─────────
│ │ │ │
3: ───@──────────────────────────────×───Z──────────────────XX────XX^0.26───Ry(-0.042π)───
└───────┘
Traceback (most recent call last):
File "/Users/xxx/xxx/cirq_diverging_sycamore.py", line 36, in <module>
optimized = c.optimize_for_target_gateset(circuit, gateset = cg.SycamoreTargetGateset())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/transformer_api.py", line 379, in func_with_logging
return _transform_and_log(
^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/transformer_api.py", line 438, in _transform_and_log
transformed_circuit = _run_transformer_on_circuit(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/transformer_api.py", line 424, in _run_transformer_on_circuit
return func(mutable_circuit if mutable_circuit else circuit, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/optimize_for_target_gateset.py", line 150, in optimize_for_target_gateset
circuit = transformer(circuit, context=context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/target_gatesets/compilation_target_gateset.py", line 71, in transformer_with_kwargs
return transformer(circuit, context=context, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/transformer_api.py", line 379, in func_with_logging
return _transform_and_log(
^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/transformer_api.py", line 438, in _transform_and_log
transformed_circuit = _run_transformer_on_circuit(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/transformer_api.py", line 424, in _run_transformer_on_circuit
return func(mutable_circuit if mutable_circuit else circuit, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq_google/transformers/target_gatesets/sycamore_gateset.py", line 75, in merge_swap_rzz_and_2q_unitaries
circuit = cirq.merge_operations_to_circuit_op(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/transformer_primitives.py", line 566, in merge_operations_to_circuit_op
return merge_operations(circuit, merge_func, tags_to_ignore=tags_to_ignore, deep=deep)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/transformer_primitives.py", line 505, in merge_operations
merged_circuit.add_op_to_moment(moment_idx, op)
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/transformers/transformer_primitives.py", line 345, in add_op_to_moment
self.ops_by_index[moment_index][op] = 0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/_compat.py", line 104, in wrapped_no_args
result = func(self)
^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/value/value_equality_attr.py", line 90, in _value_equality_hash
return hash((self._value_equality_values_cls_(), self._value_equality_values_()))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/_compat.py", line 104, in wrapped_no_args
result = func(self)
^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/value/value_equality_attr.py", line 90, in _value_equality_hash
return hash((self._value_equality_values_cls_(), self._value_equality_values_()))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/_compat.py", line 104, in wrapped_no_args
result = func(self)
^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/_compat.py", line 104, in wrapped_no_args
result = func(self)
^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/ops/eigen_gate.py", line 319, in _value_equality_values_
return self._canonical_exponent, self._global_shift
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/ops/eigen_gate.py", line 311, in _canonical_exponent
period = self._period()
^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/ops/eigen_gate.py", line 300, in _period
return _approximate_common_period(real_periods)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/ops/eigen_gate.py", line 443, in _approximate_common_period
common = float(_common_rational_period(approx_rational_periods))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/ops/eigen_gate.py", line 461, in _common_rational_period
int_common_period = _lcm(int_periods)
^^^^^^^^^^^^^^^^^
File "/Users/xxx/xxx/cirqenv/lib/python3.11/site-packages/cirq/ops/eigen_gate.py", line 402, in _lcm
t = t * r // math.gcd(t, r)
~~~~~~^^~~~~~~~~~~~~~~~
ZeroDivisionError: integer division or modulo by zero
Cirq version: 1.4.1
A global_shift=100000 doesn't make sense. global_shift represents global phase as $e^{i \pi t}$ where $t$ is the global_shift so global_shift should be $\in [0, 2)$. We probably need to add input validation for this.
As for the circuit in question:
import cirq as c
qubits = c.LineQubit.range(4)
circuit = c.Circuit()
circuit.append(c.rz(-0.0171*np.pi)(qubits[0]))
circuit.append(c.CNOT(qubits[3], qubits[1]))
circuit.append(c.MSGate(rads=-0.01*np.pi)(qubits[0], qubits[1]))
circuit.append(c.Y(qubits[0]))
circuit.append(c.CSWAP(qubits[2], qubits[0], qubits[3]))
circuit.append(c.Ry(rads=0.014*np.pi)(qubits[2]))
circuit.append(c.Z(qubits[3]))
circuit.append(c.ISWAP(qubits[0], qubits[2]))
circuit.append(c.XX(qubits[1], qubits[3]))
circuit.append(c.XXPowGate(exponent=0.26, global_shift=100000%2)(qubits[2], qubits[3]))
circuit.append(c.ISWAP(qubits[0], qubits[2]))
circuit.append(c.Ry(rads=-0.042*np.pi)(qubits[3]))
# print(circuit)
optimized = c.optimize_for_target_gateset(circuit, gateset = cg.SycamoreTargetGateset())
print(optimized)
0: ─────────────────────────────────────────────────────────PhXZ(a=0.0217,x=0.198,z=-0.435)─────SYC───────────────────────────────────SYC───PhXZ(a=-0.0502,x=0.398,z=-0.0656)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=-0.491,x=0.373,z=0.672)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=0.883,x=0.435,z=0.779)──────────────────────────────────────────────────────────────────────────────────────────────────────────────────PhXZ(a=0,x=0.586,z=0.0833)────────SYC────────────────SYC───PhXZ(a=-0.0833,x=0.586,z=0.583)────────────────────────────────────────────PhXZ(a=0,x=0.586,z=0.0833)─────SYC────────────────SYC───PhXZ(a=-0.0833,x=0.586,z=0.583)────────────────────────────────────────────PhXZ(a=0.5,x=0.5,z=0.917)───────SYC───Rx(0.477π)───SYC───PhXZ(a=0.75,x=0.5,z=0.75)──────────────────────────────────PhXZ(a=0.568,x=0.586,z=0)──────────SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=-0.815,x=0.891,z=0.0223)───────────────────────────────────────PhXZ(a=-0.273,x=0.289,z=0)──────SYC───PhX(-0.358)────────SYC───PhX(0.968)^0.691───SYC───PhXZ(a=0.1,x=1,z=0)──────────────────────────────────────────────────PhXZ(a=-0.273,x=0.289,z=0)──────SYC───PhX(-0.358)────────SYC───PhX(0.968)^0.691───SYC───PhXZ(a=0.1,x=1,z=0)─────────────
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1: ───PhXZ(a=0.5,x=0.5,z=0.917)────SYC───Rx(0.477π)───SYC───PhXZ(a=0.264,x=4.44e-16,z=-0.514)───SYC───PhXZ(a=-1.11e-16,x=0.979,z=0)───SYC───PhXZ(a=0.0689,x=0.5,z=-0.569)───────┼──────────────────────────────────┼──────────────────────────────────────┼──────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────┼───────────────────────────────────────────────────────────────────────────PhXZ(a=-1,x=1,z=0)──────────────┼────────────────────────┼────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼────────────────────────┼─────────────────────────────────────
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
2: ────────────────────────────────┼──────────────────┼─────────────────────────────────────────────────────────────────────────────────────PhXZ(a=-1,x=0.5,z=0.71)─────────────SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=-0.0745,x=0.5,z=-0.216)───SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=0.993,x=0.586,z=-0.426)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=-0.647,x=0.633,z=0.802)───SYC───────────────────────────SYC───PhXZ(a=-0.401,x=0.319,z=-0.404)───SYC───Rx(0.477π)───SYC───PhXZ(a=-0.0429,x=0.109,z=0.827)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=0.776,x=0.199,z=0.99)───SYC───Rx(0.477π)───SYC───PhXZ(a=-0.0429,x=0.109,z=0.827)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=0.383,x=0.502,z=0.635)───SYC────────────────SYC───PhXZ(a=-0.667,x=0.477,z=-0.667)───SYC────────────────SYC───PhXZ(a=-0.0833,x=0.0863,z=0.293)───SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=-0.161,x=0.5,z=0.744)──────SYC───────────────────────────SYC───PhXZ(a=-0.0833,x=0.6,z=0.583)───SYC───PhX(0.849)^0.975───SYC──────────────────────SYC───PhXZ(a=0.946,x=0.666,z=-0.361)───SYC───────────────────────────SYC───PhXZ(a=0.432,x=0.519,z=0.355)───SYC───PhX(0.849)^0.975───SYC──────────────────────SYC───PhXZ(a=0.916,x=0.148,z=0.845)───
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
3: ───PhXZ(a=0,x=0.586,z=0.0833)───SYC────────────────SYC───PhXZ(a=-0.0833,x=0.586,z=0.583)────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────PhXZ(a=0.355,x=1,z=0)────────────SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=0.926,x=0.5,z=0.991)──────SYC───PhXZ(a=0,x=0.189,z=0)───SYC──────────────────────────────────────────────────────────────PhXZ(a=-0.5,x=0.5,z=-0.29)────────SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=0.426,x=0.5,z=0.824)─────────────────────────────PhXZ(a=0.5,x=0.5,z=-0.29)─────────SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=-0.574,x=0.5,z=0.824)─────────────────────────────PhXZ(a=0.5,x=0.5,z=0.917)─────────SYC───Rx(0.477π)───SYC───PhXZ(a=0.75,x=0.5,z=0.75)───────────────────────────────────────────────────PhXZ(a=-0.5,x=0.5,z=-0.0833)──────SYC───PhXZ(a=0,x=0.477,z=0)───SYC───PhXZ(a=0.375,x=1,z=0)───────────────────────────────────────────────────────────────────PhXZ(a=-0.5,x=0.5,z=0.893)───────SYC───PhXZ(a=0,x=0.202,z=0)───SYC───PhXZ(a=0.226,x=0.458,z=0.274)───────────────────────────────────────────────────────────────────────────────────────────
And even with a non zero global_shift it works. For example when global_shift=0.1 we get
0: ─────────────────────────────────────────────────────────PhXZ(a=0.0217,x=0.198,z=-0.435)─────SYC───────────────────────────────────SYC───PhXZ(a=-0.0502,x=0.398,z=-0.0656)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=-0.491,x=0.373,z=0.672)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=0.883,x=0.435,z=0.779)──────────────────────────────────────────────────────────────────────────────────────────────────────────────────PhXZ(a=0,x=0.586,z=0.0833)────────SYC────────────────SYC───PhXZ(a=-0.0833,x=0.586,z=0.583)────────────────────────────────────────────PhXZ(a=0,x=0.586,z=0.0833)─────SYC────────────────SYC───PhXZ(a=-0.0833,x=0.586,z=0.583)────────────────────────────────────────────PhXZ(a=0.5,x=0.5,z=0.917)───────SYC───Rx(0.477π)───SYC───PhXZ(a=0.75,x=0.5,z=0.75)──────────────────────────────────PhXZ(a=0.568,x=0.586,z=0)──────────SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=-0.815,x=0.891,z=0.0223)───────────────────────────────────────PhXZ(a=-0.273,x=0.289,z=0)──────SYC───PhX(-0.358)────────SYC───PhX(0.968)^0.691───SYC───PhXZ(a=0.1,x=1,z=0)──────────────────────────────────────────────────PhXZ(a=-0.273,x=0.289,z=0)──────SYC───PhX(-0.358)────────SYC───PhX(0.968)^0.691───SYC───PhXZ(a=0.1,x=1,z=0)─────────────
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1: ───PhXZ(a=0.5,x=0.5,z=0.917)────SYC───Rx(0.477π)───SYC───PhXZ(a=0.264,x=4.44e-16,z=-0.514)───SYC───PhXZ(a=-1.11e-16,x=0.979,z=0)───SYC───PhXZ(a=0.0689,x=0.5,z=-0.569)───────┼──────────────────────────────────┼──────────────────────────────────────┼──────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────────────────┼───────────────────────────────────────────────────────────────────────────PhXZ(a=-1,x=1,z=0)──────────────┼────────────────────────┼────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────────┼────────────────────────┼─────────────────────────────────────
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
2: ────────────────────────────────┼──────────────────┼─────────────────────────────────────────────────────────────────────────────────────PhXZ(a=-1,x=0.5,z=0.71)─────────────SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=-0.0745,x=0.5,z=-0.216)───SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=0.993,x=0.586,z=-0.426)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=-0.647,x=0.633,z=0.802)───SYC───────────────────────────SYC───PhXZ(a=-0.401,x=0.319,z=-0.404)───SYC───Rx(0.477π)───SYC───PhXZ(a=-0.0429,x=0.109,z=0.827)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=0.776,x=0.199,z=0.99)───SYC───Rx(0.477π)───SYC───PhXZ(a=-0.0429,x=0.109,z=0.827)───SYC───PhXZ(a=0.0677,x=1,z=0)───────SYC───PhXZ(a=0.383,x=0.502,z=0.635)───SYC────────────────SYC───PhXZ(a=-0.667,x=0.477,z=-0.667)───SYC────────────────SYC───PhXZ(a=-0.0833,x=0.0863,z=0.293)───SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=-0.161,x=0.5,z=0.744)──────SYC───────────────────────────SYC───PhXZ(a=-0.0833,x=0.6,z=0.583)───SYC───PhX(0.849)^0.975───SYC──────────────────────SYC───PhXZ(a=0.946,x=0.666,z=-0.361)───SYC───────────────────────────SYC───PhXZ(a=0.432,x=0.519,z=0.355)───SYC───PhX(0.849)^0.975───SYC──────────────────────SYC───PhXZ(a=0.916,x=0.148,z=0.845)───
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
3: ───PhXZ(a=0,x=0.586,z=0.0833)───SYC────────────────SYC───PhXZ(a=-0.0833,x=0.586,z=0.583)────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────PhXZ(a=0.355,x=1,z=0)────────────SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=0.926,x=0.5,z=0.991)──────SYC───PhXZ(a=0,x=0.189,z=0)───SYC──────────────────────────────────────────────────────────────PhXZ(a=-0.5,x=0.5,z=-0.29)────────SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=0.426,x=0.5,z=0.824)─────────────────────────────PhXZ(a=0.5,x=0.5,z=-0.29)─────────SYC───PhXZ(a=-0.515,x=0.523,z=0)───SYC───PhXZ(a=-0.574,x=0.5,z=0.824)─────────────────────────────PhXZ(a=0.5,x=0.5,z=0.917)─────────SYC───Rx(0.477π)───SYC───PhXZ(a=0.75,x=0.5,z=0.75)───────────────────────────────────────────────────PhXZ(a=-0.5,x=0.5,z=-0.0833)──────SYC───PhXZ(a=0,x=0.477,z=0)───SYC───PhXZ(a=0.375,x=1,z=0)───────────────────────────────────────────────────────────────────PhXZ(a=-0.5,x=0.5,z=0.893)───────SYC───PhXZ(a=0,x=0.202,z=0)───SYC───PhXZ(a=0.226,x=0.458,z=0.274)───────────────────────────────────────────────────────────────────────────────────────────
Even though the value is not practical the gate did accept the value and it failed later at the optimization stage. A human error with such value is still possible and its effects are realized later. Printing the circuit does not show that value so debugging the source of issue could be hard for a developer.
Discussed during bit.ly/cirq-cynq today (2024-10-16): it should do either numeric validation, or or adjust the shift. (Note that the global shift could be symbolic.)
Looks like this gets fixed by #7051, with the underlying issue being #7052.