Esempio n. 1
0
def compile_swap(gate) -> QCircuit:
    """
    Compile swap gates into CNOT.
    Parameters
    ----------
    gate:
        the gate.

    Returns
    -------
    QCircuit, the result of compilation.
    """
    if gate.name.lower() == "swap":
        if len(gate.target) != 2:
            raise TequilaCompilerException("SWAP gates needs two targets")
        power = 1
        if hasattr(gate, "power"):
            if power is None or power in [1, 1.0]:
                pass
            else:
                raise TequilaCompilerException(
                    "Parametrized SWAPs should be decomposed on top level! Something went wrong"
                )

        c = []
        if gate.control is not None:
            c = gate.control
        return X(target=gate.target[0], control=[gate.target[1]]) \
               + X(target=gate.target[1], control=[gate.target[0]] + list(c), power=power) \
               + X(target=gate.target[0], control=[gate.target[1]])

    else:
        return QCircuit.wrap_gate(gate)
Esempio n. 2
0
def compile_swap(gate) -> QCircuit:
    """
    Compile swap gates into CNOT.
    Parameters
    ----------
    gate:
        the gate.

    Returns
    -------
    QCircuit, the result of compilation.
    """
    if gate.name.lower() == "swap":
        if len(gate.target) != 2:
            raise TequilaCompilerException("SWAP gates needs two targets")
        if hasattr(gate, "power") and gate.parameter != 1:
            raise TequilaCompilerException(
                "SWAP gate with power can not be compiled into CNOTS")

        c = []
        if gate.control is not None:
            c = gate.control
        return X(target=gate.target[0], control=gate.target[1] + c) \
               + X(target=gate.target[1], control=gate.target[0] + c) \
               + X(target=gate.target[0], control=gate.target[1] + c)

    else:
        return QCircuit.wrap_gate(gate)
Esempio n. 3
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]))
Esempio n. 4
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)
Esempio n. 5
0
def test_unitary_gate_u1(gate, angle):
    """
    Test some equivalences for u1 gate
    """
    c_u1 = u1(lambd=angle,
              target=gate.gates[0].target,
              control=None
              if len(gate.gates[0].control) == 0 else gate.gates[0].control)

    if len(gate.gates[0].control) > 0:
        c_u1 = X(target=gate.gates[0].control) + c_u1
        gate = X(target=gate.gates[0].control) + gate

    wfn1 = simulate(c_u1, backend="symbolic")
    wfn2 = simulate(gate, backend="symbolic")

    assert (numpy.isclose(wfn1.inner(wfn2), 1.0))
Esempio n. 6
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))
Esempio n. 7
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))
Esempio n. 8
0
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)

    if len(gate.gates[0].control) > 0:
        c_u3 = X(target=gate.gates[0].control) + c_u3
        gate = X(target=gate.gates[0].control) + gate

    wfn1 = simulate(c_u3, backend="symbolic")
    wfn2 = simulate(gate, backend="symbolic")

    assert (numpy.isclose(wfn1.inner(wfn2), 1.0))
    def create_sub_circ(self, gate, control_bit, target_bit):
        sub_circ = None

        if gate == "CNOT":
            sub_circ = CNOT(control=control_bit, target=target_bit)

        elif gate == "aCNOT":
            sub_circ = X(control_bit)
            sub_circ += CNOT(control=control_bit, target=target_bit)
            sub_circ += X(control_bit)

        elif gate == "CROT":
            a_angle = self.coefficients[self.c_i]
            sa = sympy.Symbol(a_angle)
            self.c_i += 1
            sub_circ = Ry(control=control_bit,
                          target=target_bit,
                          angle=SympyVariable(sa))

        elif gate == "aCROT":
            a_angle = self.coefficients[self.c_i]
            sa = sympy.Symbol(a_angle)
            self.c_i += 1
            sub_circ = X(control_bit)
            sub_circ += Ry(control=control_bit,
                           target=target_bit,
                           angle=SympyVariable(sa))
            sub_circ += X(control_bit)

        elif gate == "X":
            sub_circ = X(target_bit)

        elif gate == "ROT":
            a_angle = self.coefficients[self.c_i]
            self.c_i += 1
            sub_circ = Ry(control=None,
                          target=target_bit,
                          angle=SympyVariable(sympy.Symbol(a_angle)))

        return sub_circ
Esempio n. 10
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)
Esempio n. 11
0
def test_swap():
    U = X(0)
    U += SWAP(0, 2)
    wfn = simulate(U)
    wfnx = simulate(X(2))
    assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, 1.0)

    U = X(2)
    U += SWAP(0, 2, power=2.0)
    wfn = simulate(U)
    wfnx = simulate(X(0))
    assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, 1.0)

    U = X(0) + X(3)
    U += SWAP(0, 2, control=3)
    wfn = simulate(U)
    wfnx = simulate(X(2) + X(3))
    assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, 1.0)

    U = X(2) + X(3)
    U += SWAP(0, 2, control=3, power=2.0)
    wfn = simulate(U)
    wfnx = simulate(X(2) + X(3))
    assert numpy.isclose(numpy.abs(wfn.inner(wfnx))**2, 1.0)
Esempio n. 12
0
 def hcb_to_me(self, *args, **kwargs):
     U = QCircuit()
     for i in range(self.n_orbitals):
         U += X(target=self.down(i), control=self.up(i))
     return U