Skip to content

ControlledGate equality seems too loose #5110

@daxfohl

Description

@daxfohl

Description of the issue

Equality in controlled gate is implemented as follows, intentionally ignoring the order of the controls.

    def _value_equality_values_(self):
        return (
            self.sub_gate,
            self.num_controls(),
            frozenset(zip(self.control_values, self.control_qid_shape)),
        )

This means gates are considered equal even if their unitaries don't match.

def test_me():
    g0 = cirq.ControlledGate(cirq.Z, control_values=[[1], [0]])
    g1 = cirq.ControlledGate(cirq.Z, control_values=[[0], [1]])
    assert g0 == g1  # passes
    assert np.allclose(cirq.unitary(g0), cirq.unitary(g1))  # fails

In some cases the gate can't even be applied to the same qubits.

def test_me():
    g0 = cirq.ControlledGate(cirq.Z, control_values=[[1], [1, 2]], control_qid_shape=[2, 3])
    g1 = cirq.ControlledGate(cirq.Z, control_values=[[1, 2], [1]], control_qid_shape=[3, 2])
    assert g0 == g1  # passes
    qubits = cirq.LineQid.for_qid_shape((2, 3, 2))
    op0 = g0.on(*qubits)
    op1 = g1.on(*qubits)  # raises "Wrong shape of qids"
    assert op0 == op1

So, while there's a relationship between such gates, calling that relationship "equality" doesn't feel right. Was this intentional?

Cirq version
0.14.0.dev

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/gateskind/bug-reportSomething doesn't seem to work.triage/acceptedA consensus emerged that this bug report, feature request, or other action should be worked on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions