예제 #1
0
def compile_phase(gate) -> QCircuit:
    """
    Compile phase gates into Rz gates and cnots, if controlled
    Parameters
    ----------
    gate:
        the gate

    Returns
    -------
    QCircuit, the result of compilation.
    """
    if not isinstance(gate, PhaseGateImpl):
        return QCircuit.wrap_gate(gate)
    phase = gate.parameter
    result = QCircuit()
    if len(gate.control) == 0:
        return Rz(angle=phase, target=gate.target)

    if len(gate.control) == 1:
        result += Rz(angle=phase / 2, target=gate.control, control=None)
        result += Rz(angle=phase, target=gate.target, control=gate.control)
        return result
    else:
        return compile_controlled_phase(gate)
예제 #2
0
def compile_ry(gate: RotationGateImpl,
               controlled_rotation: bool = False) -> QCircuit:
    """
    Compile Ry gates into Rx and Rz.
    Parameters
    ----------
    gate:
        the gate.
    controlled_rotation:
        determines if the decomposition of the controlled-Ry gate will be performed in compile_controlled_rotation,
        if not, decomposition will be performed here

    Returns
    -------
    QCircuit, the result of compilation.
    """
    if gate.name.lower() == "ry":

        if not (gate.is_controlled() and controlled_rotation):

            return Rz(target=gate.target, control=None, angle=-numpy.pi / 2) \
                   + Rx(target=gate.target, control=gate.control, angle=gate.parameter) \
                   + Rz(target=gate.target, control=None, angle=numpy.pi / 2)

    return QCircuit.wrap_gate(gate)
예제 #3
0
def hadamard_base(gate) -> QCircuit:
    """
    base case for hadamard compilation; returns powers of hadamard as sequence of single qubit rotations.
    Parameters
    ----------
    gate:
        the gate.

    Returns
    -------
        A QCircuit; the result of compilation.
    """
    if not isinstance(gate, PowerGateImpl) or gate.name not in [
            'H', 'h', 'hadamard'
    ]:
        return QCircuit.wrap_gate(gate)
    power = gate.parameter
    a = power.wrap(a_calc)
    b = power.wrap(b_calc)
    theta = power.wrap(theta_calc)

    result = QCircuit()

    result += Rz(angle=b, target=gate.target)
    result += Ry(angle=theta, target=gate.target)
    result += Rz(angle=a, target=gate.target)

    return result
예제 #4
0
def hadamard_axbxc(gate) -> QCircuit:
    """
    Decompose 1 control parametrized hadamard into single qubit rotation and CNOT.
    Parameters
    ----------
    gate:
        the gate

    Returns
    -------
    QCircuit, the result of compilation.
    """
    if not isinstance(gate, PowerGateImpl) or gate.name not in [
            'H', 'h', 'hadamard'
    ]:
        return QCircuit.wrap_gate(gate)
    power = gate.parameter
    target = gate.target
    a = power.wrap(a_calc)
    b = power.wrap(b_calc)
    theta = power.wrap(theta_calc)
    phase = power * jnp.pi / 2

    result = QCircuit()

    result += Rz((a - b) / 2, target)
    result += CNOT(gate.control, target)
    result += Rz(-(a + b) / 2, target)
    result += Ry(-theta / 2, target)
    result += CNOT(gate.control, target)
    result += Ry(theta / 2, target)
    result += Rz(a, target)
    result += Phase(numpy.pi * power / 2, gate.control)

    return result
예제 #5
0
def compile_power_base(gate):
    """
    Base case of compile_power_gate: convert a 1-qubit parametrized power gate into rotation gates.
    Parameters
    ----------
    gate:
        the gate.

    Returns
    -------
        A QCircuit; the result of compilation.
    """
    if not isinstance(gate, PowerGateImpl):
        return QCircuit.wrap_gate(gate)

    if gate.is_controlled():
        return QCircuit.wrap_gate(gate)

    power = gate.power
    if gate.name.lower() in ['h', 'hadamard']:
        ### off by global phase of Exp[ pi power /2]
        theta = power * numpy.pi

        result = QCircuit()
        result += Ry(angle=-numpy.pi / 4, target=gate.target)
        result += Rz(angle=theta, target=gate.target)
        result += Ry(angle=numpy.pi / 4, target=gate.target)
    elif gate.name == 'X':
        ### off by global phase of Exp[ pi power /2]
        '''
        if we wanted to do it formally we would use the following
        a=-numpy.pi/2
        b=numpy.pi/2
        theta = power*numpy.pi

        result = QCircuit()
        result+= Rz(angle=b,target=gate.target)
        result+= Ry(angle=theta,target=gate.target)
        result+= Rz(angle=a,target=gate.target)
        '''
        result = Rx(angle=power * numpy.pi, target=gate.target)
    elif gate.name == 'Y':
        ### off by global phase of Exp[ pi power /2]
        theta = power * numpy.pi

        result = QCircuit()
        result += Ry(angle=theta, target=gate.target)
    elif gate.name == 'Z':
        ### off by global phase of Exp[ pi power /2]
        a = 0
        b = power * numpy.pi
        theta = 0
        result = QCircuit()
        result += Rz(angle=b, target=gate.target)
    else:
        raise TequilaException('passed a gate with name ' + gate.name +
                               ', which cannot be handled!')
    return result
예제 #6
0
def compile_phase(gate) -> QCircuit:
    if not isinstance(gate, PhaseGateImpl):
        return QCircuit.wrap_gate(gate)
    phase = gate.parameter
    result = QCircuit()
    if len(gate.control) == 0:
        return Rz(angle=phase, target=gate.target)

    if len(gate.control) == 1:
        result += Rz(angle=phase / 2, target=gate.control, control=None)
        result += Rz(angle=phase, target=gate.target, control=gate.control)
        return result
    else:
        return compile_controlled_phase(gate)
예제 #7
0
def test_basic_gates():
    I = sympy.I
    cos = sympy.cos
    sin = sympy.sin
    exp = sympy.exp
    BS = QubitWaveFunction.from_int
    angle = sympy.pi
    gates = [
        X(0),
        Y(0),
        Z(0),
        Rx(target=0, angle=angle),
        Ry(target=0, angle=angle),
        Rz(target=0, angle=angle),
        H(0)
    ]
    results = [
        BS(1), I * BS(1),
        BS(0),
        cos(-angle / 2) * BS(0) + I * sin(-angle / 2) * BS(1),
        cos(-angle / 2) * BS(0) + I * sin(-angle / 2) * I * BS(1),
        exp(-I * angle / 2) * BS(0), 1 / sympy.sqrt(2) * (BS(0) + BS(1))
    ]
    for i, g in enumerate(gates):
        wfn = simulate(g, backend="symbolic", variables={angle: sympy.pi})
        assert (wfn == strip_sympy_zeros(results[i]))
예제 #8
0
def compile_controlled_phase(gate) -> QCircuit:
    """
    Compile multi-controlled phase gates to 1q - phase gate and multi-controlled Rz gates.
    Parameters
    ----------
    gate:
        the gate.

    Returns
    -------
    QCircuit, the result of compilation.
    """
    if not isinstance(gate, PhaseGateImpl):
        return QCircuit.wrap_gate(gate)

    if len(gate.control) == 0:
        return QCircuit.wrap_gate(gate)

    phase = gate.parameter

    result = QCircuit()
    result += Phase(target=gate.control[0],
                    control=gate.control[1:],
                    phi=phase / 2)
    result += Rz(target=gate.target, control=gate.control, angle=phase)
    return compile_controlled_phase(result)
예제 #9
0
def compile_controlled_rotation(gate: RotationGateImpl) -> QCircuit:
    """
    Recompilation of a controlled-rotation gate
    Basis change into Rz then recompilation of controled Rz, then change basis back
    :param gate: The rotational gate
    :return: set of gates wrapped in QCircuit class
    """

    if not gate.is_controlled():
        return QCircuit.wrap_gate(gate)

    if not isinstance(gate, RotationGateImpl):
        return QCircuit.wrap_gate(gate)

    if len(gate.target) > 1:
        return compile_controlled_rotation(gate=compile_multitarget(gate=gate))

    target = gate.target
    control = gate.control
    k = len(control)
    cind = _pattern(k) + [k - 1]

    result = QCircuit()
    result += change_basis(target=target, axis=gate._axis)
    coeff = -1 / pow(2, k)
    for i, ci in enumerate(cind):
        coeff *= -1

        result += Rz(target=target, angle=coeff * gate.parameter)
        result += CNOT(control[ci], target)
    result += change_basis(target=target, axis=gate._axis, daggered=True)

    result.n_qubits = result.max_qubit() + 1
    return result
예제 #10
0
def compile_controlled_power(gate: PowerGateImpl) -> QCircuit:
    """
    Recompilation of a controlled-power gate
    Basis change into Z then recompilation of controled Z, then change basis back
    :param gate: The power gate
    :return: set of gates wrapped in QCircuit class
    """
    if not gate.is_controlled():
        return QCircuit.wrap_gate(gate)

    if not isinstance(gate, PowerGateImpl):
        return QCircuit.wrap_gate(gate)

    if len(gate.target) > 1:
        return compile_controlled_power(gate=compile_multitarget(gate=gate))

    power = gate.power
    target = gate.target
    control = gate.control

    result = QCircuit()
    result += Phase(target=control[0], control=control[1:], phi=power * pi / 2)
    result += change_basis(target=target, name=gate.name)
    result += Rz(target=target, control=control, angle=power * pi)
    result += change_basis(target=target, name=gate.name, daggered=True)

    result.n_qubits = result.max_qubit() + 1
    return result
예제 #11
0
def compile_exponential_pauli_gate(gate) -> QCircuit:
    """
    Returns the circuit: exp(i*angle*paulistring)
    primitively compiled into X,Y Basis Changes and CNOTs and Z Rotations
    :param paulistring: The paulistring in given as tuple of tuples (openfermion format)
    like e.g  ( (0, 'Y'), (1, 'X'), (5, 'Z') )
    :param angle: The angle which parametrizes the gate -> should be real
    :returns: the above mentioned circuit as abstract structure
    """

    if hasattr(gate, "paulistring"):

        angle = gate.paulistring.coeff * gate.parameter

        circuit = QCircuit()

        # the general circuit will look like:
        # series which changes the basis if necessary
        # series of CNOTS associated with basis changes
        # Rz gate parametrized on the angle
        # series of CNOT (inverted direction compared to before)
        # series which changes the basis back
        ubasis = QCircuit()
        ubasis_t = QCircuit()
        cnot_cascade = QCircuit()

        last_qubit = None
        previous_qubit = None
        for k, v in gate.paulistring.items():
            pauli = v
            qubit = [k]  # wrap in list for targets= ...

            # see if we need to change the basis
            axis = 2
            if pauli.upper() == "X":
                axis = 0
            elif pauli.upper() == "Y":
                axis = 1
            ubasis += change_basis(target=qubit, axis=axis)
            ubasis_t += change_basis(target=qubit, axis=axis, daggered=True)

            if previous_qubit is not None:
                cnot_cascade += X(target=qubit, control=previous_qubit)
            previous_qubit = qubit
            last_qubit = qubit

        reversed_cnot = cnot_cascade.dagger()

        # assemble the circuit
        circuit += ubasis
        circuit += cnot_cascade
        circuit += Rz(target=last_qubit, angle=angle, control=gate.control)
        circuit += reversed_cnot
        circuit += ubasis_t

        return circuit

    else:
        return QCircuit.wrap_gate(gate)
예제 #12
0
def hadamard_base(gate) -> QCircuit:
    if not isinstance(gate, PowerGateImpl) or gate.name not in [
            'H', 'h', 'hadamard'
    ]:
        return QCircuit.wrap_gate(gate)
    power = gate.parameter
    a = power.wrap(a_calc)
    b = power.wrap(b_calc)
    theta = power.wrap(theta_calc)

    result = QCircuit()

    result += Rz(angle=b, target=gate.target)
    result += Ry(angle=theta, target=gate.target)
    result += Rz(angle=a, target=gate.target)

    return result
예제 #13
0
def test_unitary_gate_u2(ctrl, phi, lambd):
    """
    Test some equivalences for u2 gate
    Since u2(\\phi, \\lambda) = Rz(\\phi)Ry(\\pi/2)Rz(\\lambda)
    """
    c_u2 = u2(phi=phi, lambd=lambd, target=0, control=ctrl)
    c_equiv = Rz(target=0, control=ctrl, angle=lambd) + \
              Ry(target=0, control=ctrl, angle=numpy.pi / 2) + \
              Rz(target=0, control=ctrl, angle=phi)

    if ctrl is not None:
        c_u2 = X(target=ctrl) + c_u2
        c_equiv = X(target=ctrl) + c_equiv

    wfn1 = simulate(c_u2, backend="symbolic")
    wfn2 = simulate(c_equiv, backend="symbolic")

    assert (numpy.isclose(wfn1.inner(wfn2), 1.0))
예제 #14
0
def compile_y(gate) -> QCircuit:
    """
    Compile Y gates into X and Rz.
    Parameters
    ----------
    gate:
        the gate.

    Returns
    -------
    QCircuit, the result of compilation.
    """
    if gate.name.lower() == "y":

        return Rz(target=gate.target, control=None, angle=-numpy.pi / 2) \
               + X(target=gate.target, control=gate.control, power=gate.power if gate.is_parametrized() else None) \
               + Rz(target=gate.target, control=None, angle=numpy.pi / 2)

    else:
        return QCircuit.wrap_gate(gate)
예제 #15
0
def compile_controlled_phase(gate) -> QCircuit:
    if not isinstance(gate, PhaseGateImpl):
        return QCircuit.wrap_gate(gate)
    if len(gate.control) == 0:
        return QCircuit.wrap_gate(gate)
    count = len(gate.control)
    result = QCircuit()
    phase = gate.parameter

    if count == 1:
        result += H(target=gate.target)
        result += CNOT(gate.control, gate.target)
        result += H(target=gate.target)
        result += Phase(gate.parameter + numpy.pi, target=gate.target)
    elif count == 2:
        result += Rz(angle=phase / (2**2), target=gate.control[0])
        result += Rz(angle=phase / (2**(1)),
                     target=gate.control[1],
                     control=gate.control[0])
        result += Rz(angle=phase, target=gate.target, control=gate.control)

    elif count >= 3:
        result += Rz(angle=phase / (2**count), target=gate.control[0])
        for i in range(1, count):
            result += Rz(angle=phase / (2**(count - i)),
                         target=gate.control[i],
                         control=gate.control[0:i])
        result += Rz(angle=phase, target=gate.target, control=gate.control)
    return result
예제 #16
0
def hadamard_axbxc(gate) -> QCircuit:
    if not isinstance(gate, PowerGateImpl) or gate.name not in [
            'H', 'h', 'hadamard'
    ]:
        return QCircuit.wrap_gate(gate)
    power = gate.parameter
    target = gate.target
    a = power.wrap(a_calc)
    b = power.wrap(b_calc)
    theta = power.wrap(theta_calc)
    phase = power * jnp.pi / 2

    result = QCircuit()

    result += Rz((a - b) / 2, target)
    result += CNOT(gate.control, target)
    result += Rz(-(a + b) / 2, target)
    result += Ry(-theta / 2, target)
    result += CNOT(gate.control, target)
    result += Ry(theta / 2, target)
    result += Rz(a, target)
    result += Phase(numpy.pi * power / 2, gate.control)

    return result
예제 #17
0
def compile_power_base(gate):
    if not isinstance(gate, PowerGateImpl):
        return QCircuit.wrap_gate(gate)
    power = gate.parameter
    if gate.name in ['H', 'h', 'Hadamard', 'hadamard']:
        return compile_h_power(gate=gate)
    if gate.name == 'X':
        ### off by global phase of Exp[ pi power /2]
        '''
        if we wanted to do it formally we would use the following
        a=-numpy.pi/2
        b=numpy.pi/2
        theta = power*numpy.pi

        result = QCircuit()
        result+= Rz(angle=b,target=gate.target)
        result+= Ry(angle=theta,target=gate.target)
        result+= Rz(angle=a,target=gate.target)
        '''
        result = Rx(angle=power * numpy.pi, target=gate.target)
    elif gate.name == 'Y':
        ### off by global phase of Exp[ pi power /2]
        theta = power * numpy.pi

        result = QCircuit()
        result += Ry(angle=theta, target=gate.target)
    elif gate.name == 'Z':
        ### off by global phase of Exp[ pi power /2]
        a = 0
        b = power * numpy.pi
        theta = 0
        result = QCircuit()
        result += Rz(angle=b, target=gate.target)
    else:
        raise TequilaException('passed a gate with name ' + gate.name +
                               ', which cannot be handled!')
    return result
예제 #18
0
def test_consistency():
    angle = numpy.pi / 2
    cpairs = [(CNOT(target=0, control=1), X(target=0, control=1)),
              (Ry(target=0, angle=numpy.pi),
               Rz(target=0, angle=4 * numpy.pi) + X(target=0)),
              (Rz(target=0,
                  angle=numpy.pi), Rz(target=0, angle=numpy.pi) + Z(target=0)),
              (Rz(target=0, angle=angle),
               Rz(target=0, angle=angle / 2) + Rz(target=0, angle=angle / 2)),
              (Rx(target=0, angle=angle),
               Rx(target=0, angle=angle / 2) + Rx(target=0, angle=angle / 2)),
              (Ry(target=0, angle=angle),
               Ry(target=0, angle=angle / 2) + Ry(target=0, angle=angle / 2))]

    for c in cpairs:
        print("circuit=", c[0], "\n", c[1])
        wfn1 = simulate(c[0], backend="symbolic")
        wfn2 = simulate(c[1], backend="symbolic")
        assert (numpy.isclose(wfn1.inner(wfn2), 1.0))
예제 #19
0
def get_axbxc_decomp(gate):
    """
    Break down single controlled parametrized power gates into CNOT and rotations.
    Parameters
    ----------
    gate:
        the gate.

    Returns
    -------
    QCircuit; the result of compilation.
    """

    if not isinstance(gate, PowerGateImpl) or gate.name not in ['X', 'Y', 'Z']:
        return QCircuit.wrap_gate(gate)
    power = gate.parameter
    target = gate.target
    result = QCircuit()
    if gate.name == 'X':
        a = -numpy.pi / 2
        b = numpy.pi / 2
        theta = power * numpy.pi
        '''
        result+=Phase(numpy.pi*power/2,gate.control)
        result+=Rz(-(a-b)/2,target)
        result+=CNOT(gate.control,target)
        #result+=Rz(-(a+b)/2,target)
        result+=Ry(-theta/2,target)
        result+=CNOT(gate.control,target)
        result+=Ry(theta/2,target)
        result+=Rz(a,target=target)
        '''
        '''
        result+=Rz((a-b)/2,target)
        result+=CNOT(gate.control,target)
        #result+=Rz(-(a+b)/2,target)
        result+=Ry(-theta/2,target)
        result+=CNOT(gate.control,target)
        result+=Ry(theta/2,target)
        result+=Rz(a,target)
        result += Phase(numpy.pi * power / 2, gate.control)
        '''
        result += Rx(angle=theta, target=target, control=gate.control)
        result += Phase(numpy.pi * power / 2, gate.control)

    elif gate.name == 'Y':
        ### off by global phase of Exp[ pi power /2]

        theta = power * numpy.pi
        '''
        result+=Phase(numpy.pi*power/2,gate.control)
        result+=CNOT(gate.control,target)
        result+=Ry(-theta/2,target)
        result+=CNOT(gate.control,target)
        result+=Ry(theta/2,target)
        '''
        a = 0
        b = 0
        # result+=Rz((a-b)/2,target)
        result += CNOT(gate.control, target)
        # result+=Rz(-(a+b)/2,target)
        result += Ry(-theta / 2, target)
        result += CNOT(gate.control, target)
        result += Ry(theta / 2, target)
        # result+=Rz(a,target)
        result += Phase(numpy.pi * power / 2, gate.control)

    elif gate.name == 'Z':
        a = 0
        b = power * numpy.pi
        theta = 0

        result += Rz(b / 2, target)
        result += CNOT(gate.control, target)
        result += Rz(-b / 2, target)
        result += CNOT(gate.control, target)
        # result+=Rz(a,target)
        result += Phase(numpy.pi * power / 2, gate.control)
        '''
        result+=Rz(b/2,target)
        result+=CNOT(gate.control,target)
        result+=Rz(-b/2,target)
        result+=CNOT(gate.control,target)
        '''
    return result
예제 #20
0
def get_axbxc_decomp(gate):
    if not isinstance(gate, PowerGateImpl) or gate.name not in ['X', 'Y', 'Z']:
        return QCircuit.wrap_gate(gate)
    power = gate.parameter
    target = gate.target
    result = QCircuit()
    if gate.name == 'X':
        a = -numpy.pi / 2
        b = numpy.pi / 2
        theta = power * numpy.pi
        '''
        result+=Phase(numpy.pi*power/2,gate.control)
        result+=Rz(-(a-b)/2,target)
        result+=CNOT(gate.control,target)
        #result+=Rz(-(a+b)/2,target)
        result+=Ry(-theta/2,target)
        result+=CNOT(gate.control,target)
        result+=Ry(theta/2,target)
        result+=Rz(a,target=target)
        '''
        '''
        result+=Rz((a-b)/2,target)
        result+=CNOT(gate.control,target)
        #result+=Rz(-(a+b)/2,target)
        result+=Ry(-theta/2,target)
        result+=CNOT(gate.control,target)
        result+=Ry(theta/2,target)
        result+=Rz(a,target)
        result += Phase(numpy.pi * power / 2, gate.control)
        '''
        result += Rx(angle=theta, target=target, control=gate.control)
        result += Phase(numpy.pi * power / 2, gate.control)

    elif gate.name == 'Y':
        ### off by global phase of Exp[ pi power /2]

        theta = power * numpy.pi
        '''
        result+=Phase(numpy.pi*power/2,gate.control)
        result+=CNOT(gate.control,target)
        result+=Ry(-theta/2,target)
        result+=CNOT(gate.control,target)
        result+=Ry(theta/2,target)
        '''
        a = 0
        b = 0
        # result+=Rz((a-b)/2,target)
        result += CNOT(gate.control, target)
        # result+=Rz(-(a+b)/2,target)
        result += Ry(-theta / 2, target)
        result += CNOT(gate.control, target)
        result += Ry(theta / 2, target)
        # result+=Rz(a,target)
        result += Phase(numpy.pi * power / 2, gate.control)

    elif gate.name == 'Z':
        a = 0
        b = power * numpy.pi
        theta = 0

        result += Rz(b / 2, target)
        result += CNOT(gate.control, target)
        result += Rz(-b / 2, target)
        result += CNOT(gate.control, target)
        # result+=Rz(a,target)
        result += Phase(numpy.pi * power / 2, gate.control)
        '''
        result+=Rz(b/2,target)
        result+=CNOT(gate.control,target)
        result+=Rz(-b/2,target)
        result+=CNOT(gate.control,target)
        '''
    return result
예제 #21
0
    "gate, theta, phi, lambd",
    [
        (Rx(target=0, control=None, angle=numpy.pi / 5), numpy.pi / 5,
         -numpy.pi / 2, numpy.pi / 2),  # Rx(angle) = u3(angle, -pi/2, pi/2)
        (Rx(target=0, control=1,
            angle=numpy.pi / 6), numpy.pi / 6, -numpy.pi / 2, numpy.pi / 2),
        (Rx(target=0, control=None,
            angle=numpy.pi / 7), numpy.pi / 7, -numpy.pi / 2, numpy.pi / 2),
        (Rx(target=0, control=1,
            angle=numpy.pi / 8), numpy.pi / 8, -numpy.pi / 2, numpy.pi / 2),
        (Ry(target=0, control=1, angle=numpy.pi / 4), numpy.pi / 4, 0,
         0),  # Ry(angle) = u3(angle, 0, 0)
        (Ry(target=0, control=1, angle=numpy.pi / 5), numpy.pi / 5, 0, 0),
        (Ry(target=0, control=1, angle=numpy.pi / 3), numpy.pi / 3, 0, 0),
        (Ry(target=0, control=1, angle=numpy.pi / 2), numpy.pi / 2, 0, 0),
        (Rz(target=0, control=None,
            angle=numpy.pi), 0, 0, numpy.pi),  # Rz(angle) = U(0, 0, angle)
        (Rz(target=0, control=1, angle=numpy.pi / 6), 0, 0, numpy.pi / 6),
        (Rz(target=0, control=None, angle=numpy.pi / 7), 0, 0, numpy.pi / 7),
        (Rz(target=0, control=1, angle=numpy.pi / 8), 0, 0, numpy.pi / 8)
    ])
def test_unitary_gate_u_u3(gate, theta, phi, lambd):
    """
    Test some equivalences for u3 gate (also U gate, because U = u3)
    """
    c_u3 = u3(theta=theta,
              phi=phi,
              lambd=lambd,
              target=gate.gates[0].target,
              control=None
              if len(gate.gates[0].control) == 0 else gate.gates[0].control)