Open jiannanWang opened 5 months ago
doesn't looklike an issue in the optimize_for_target_gateset
but in the cirq.decompose
protocol which optimize_for_target_gateset
uses
specifically decomposing the third operation doesn't yield a correct result
>> op = XXPowGate(exponent=2.3059912502413593, global_shift=5.787646153894631).on(qr[3], qr[4]).controlled_by(qr[1])
>> c = cirq.Circuit(cirq.decompose(op))
>> print(cirq.equal_up_to_global_phase(cirq.unitary(c), cirq.unitary(op)))
False
diving deeper the decomposition reaches a controlled CZPowGate
but the decomposition of it wrong. so this issue isn't in the cirq.decompose
but the in _decompose_
method of the ControlledGate
class
>> op = cirq.CZPowGate(exponent=-4.611982500482719, global_shift=-2.8938230769473154).on(cirq.LineQubit(3), cirq.LineQubit(4)).controlled_by(cirq.LineQubit(1))
>> c = cirq.Circuit(op._decompose_())
>> print(cirq.equal_up_to_global_phase(cirq.unitary(c), cirq.unitary(op)))
False
the root cause is the hardcoded decomposition for controlled gate when the subgate is CZPowGate, which turns a CZPowGate into a Controlled - ZPowGate. this transformation misses at least a phase which becomes problematic for the controlled version
Suggested fix: Add a correction operation on line https://github.com/quantumlib/Cirq/blob/decf16ddf5b14b0fe46c5dbbb299c53c89d49945/cirq-core/cirq/ops/controlled_gate.py#L200-L202
We should change the if isinstance(self.sub_gate, common_gates.CZPowGate):
check to also check that self.sub_gate.global_shift == 0
and only then delegate to cirq.Z.controlled()
In hindsight, we probably shouldn't have added so many special cases to the decomposition of Controlled
.
Description of the issue
The document says
optimize_for_target_gateset
returns "An equivalent circuit containing gates accepted by gateset." However, applyingoptimize_for_target_gateset
to the below circuit generates a new circuit with a different final state vector.Note that the final state vectors have a large difference (atol >= 1e-3).
How to reproduce the issue
Cirq version You can get the cirq version by printing
cirq.__version__
. From the command line: