Exemple #1
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
Exemple #2
0
def hadamard_recursor(gate) -> QCircuit:
    if not isinstance(gate, PowerGateImpl) or gate.name not in [
            'H', 'h', 'hadamard'
    ]:
        return QCircuit.wrap_gate(gate)
    result = QCircuit()
    cl = 0
    if gate.is_controlled():
        cl = len(gate.control)
    if cl == 0:
        return hadamard_base(gate)
    if cl == 1:
        return hadamard_axbxc(gate)

    if cl == 2:
        v = type(gate)(name=gate.name,
                       power=gate.parameter / 2,
                       target=gate.target,
                       control=gate.control[1])
        result += hadamard_axbxc(v)
        result += CNOT(gate.control[0], gate.control[1])
        vdag = type(gate)(name=gate.name,
                          power=gate.parameter / 2,
                          target=gate.target,
                          control=gate.control[1]).dagger()
        result += hadamard_axbxc(vdag)
        result += CNOT(gate.control[0], gate.control[1])
        again = type(gate)(name=gate.name,
                           power=gate.parameter / 2,
                           target=gate.target,
                           control=gate.control[0])
        result += hadamard_axbxc(again)

    else:
        v = type(gate)(name=gate.name,
                       power=gate.parameter / 2,
                       target=gate.target,
                       control=gate.control[-1])
        result += hadamard_axbxc(v)
        result += CNOT(target=gate.control[cl - 1],
                       control=gate.control[0:cl - 1])
        vdag = type(gate)(name=gate.name,
                          power=gate.parameter / 2,
                          target=gate.target,
                          control=gate.control[-1]).dagger()
        result += hadamard_axbxc(vdag)
        result += CNOT(target=gate.control[cl - 1],
                       control=gate.control[0:cl - 1])
        rebuild = type(gate)(name=gate.name,
                             power=gate.parameter / 2,
                             target=gate.target,
                             control=gate.control[:cl - 1])
        result += hadamard_recursor(rebuild)
    return result
Exemple #3
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
Exemple #4
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
Exemple #5
0
def test_moments():
    c = QCircuit()
    c += CNOT(target=0, control=(1, 2, 3))
    c += H(target=[0, 1])
    c += Rx(angle=numpy.pi, target=[0, 3])
    c += Z(target=1)
    c += Phase(phi=numpy.pi, target=4)
    moms = c.moments
    assert len(moms) == 3
    assert (moms[0].gates[1].parameter == assign_variable(numpy.pi))
    assert (moms[0].gates[1].target == (4, ))
    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
Exemple #7
0
def compile_toffoli(gate) -> QCircuit:
    if gate.name.lower != 'x':
        return QCircuit.wrap_gate(gate)
    control = gate.control
    c1 = control[1]
    c0 = control[0]
    target = gate.target
    result = QCircuit()
    result += H(target)
    result += CNOT(c1, target)
    result += T(target).dagger()
    result += CNOT(c0, target)
    result += T(target)
    result += CNOT(c1, target)
    result += T(target).dagger()
    result += CNOT(c0, target)
    result += T(c1)
    result += T(target)
    result += CNOT(c0, c1)
    result += H(target)
    result += T(c0)
    result += T(c1).dagger()
    result += CNOT(c0, c1)

    return (result)
Exemple #8
0
def test_circuit_from_moments():
    c = QCircuit()
    c += CNOT(target=0, control=(1, 2, 3))
    c += Phase(phi=numpy.pi, target=4)
    c += Rx(angle=Variable('a'), target=[0, 3])
    c += H(target=[0, 1])
    c += Rx(angle=Variable('a'), target=[2, 3])
    ## table[1] should equal 1 at this point, len(moments should be 3)
    c += Z(target=1)
    c += Rx(angle=Variable('a'), target=[0, 3])
    moms = c.moments
    c2 = QCircuit.from_moments(moms)
    assert c == c2
Exemple #9
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
Exemple #10
0
def test_canonical_moments():
    c = QCircuit()
    c += CNOT(target=0, control=(1, 2, 3))
    c += Rx(angle=Variable('a'), target=[0, 3])
    c += H(target=[0, 1])
    c += Rx(angle=Variable('a'), target=[2, 3])
    c += Rx(angle=Variable('a'), target=[0, 3])
    c += Z(target=1)
    c += Phase(phi=numpy.pi, target=4)
    moms = c.canonical_moments
    assert len(moms) == 6
    assert (moms[0].gates[1].parameter == assign_variable(numpy.pi))
    assert (moms[0].gates[1].target == (4, ))
    assert hasattr(moms[3].gates[0], 'axis')
    assert len(moms[0].qubits) == 5
Exemple #11
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))
Exemple #12
0
def compile_toffoli(gate) -> QCircuit:
    """
    break down a toffoli gate into a sequence of CNOT and single qubit gates.
    Parameters
    ----------
    gate:
        the gate.

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

    if gate.name.lower != 'x':
        return QCircuit.wrap_gate(gate)
    control = gate.control
    c1 = control[1]
    c0 = control[0]
    target = gate.target
    result = QCircuit()
    result += H(target)
    result += CNOT(c1, target)
    result += T(target).dagger()
    result += CNOT(c0, target)
    result += T(target)
    result += CNOT(c1, target)
    result += T(target).dagger()
    result += CNOT(c0, target)
    result += T(c1)
    result += T(target)
    result += CNOT(c0, c1)
    result += H(target)
    result += T(c0)
    result += T(c1).dagger()
    result += CNOT(c0, c1)

    return (result)
Exemple #13
0
def hadamard_recursor(gate) -> QCircuit:
    """
    recursive function for decomposing parametrized hadamard, potentially with controls.
    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)
    result = QCircuit()
    cl = 0
    if gate.is_controlled():
        cl = len(gate.control)
    if cl == 0:
        return hadamard_base(gate)
    if cl == 1:
        return hadamard_axbxc(gate)

    if cl == 2:
        v = type(gate)(name=gate.name,
                       power=gate.parameter / 2,
                       target=gate.target,
                       control=gate.control[1])
        result += hadamard_axbxc(v)
        result += CNOT(gate.control[0], gate.control[1])
        vdag = type(gate)(name=gate.name,
                          power=gate.parameter / 2,
                          target=gate.target,
                          control=gate.control[1]).dagger()
        result += hadamard_axbxc(vdag)
        result += CNOT(gate.control[0], gate.control[1])
        again = type(gate)(name=gate.name,
                           power=gate.parameter / 2,
                           target=gate.target,
                           control=gate.control[0])
        result += hadamard_axbxc(again)

    else:
        v = type(gate)(name=gate.name,
                       power=gate.parameter / 2,
                       target=gate.target,
                       control=gate.control[-1])
        result += hadamard_axbxc(v)
        result += CNOT(target=gate.control[cl - 1],
                       control=gate.control[0:cl - 1])
        vdag = type(gate)(name=gate.name,
                          power=gate.parameter / 2,
                          target=gate.target,
                          control=gate.control[-1]).dagger()
        result += hadamard_axbxc(vdag)
        result += CNOT(target=gate.control[cl - 1],
                       control=gate.control[0:cl - 1])
        rebuild = type(gate)(name=gate.name,
                             power=gate.parameter / 2,
                             target=gate.target,
                             control=gate.control[:cl - 1])
        result += hadamard_recursor(rebuild)
    return result
Exemple #14
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
Exemple #15
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
Exemple #16
0
def power_recursor(gate, cut=False) -> QCircuit:
    """
    recursive function for decomposing parametrized, possibly controlled, power gates.
    Parameters
    ----------
    gate:
        the gate.
    cut: bool:
        whether or not to stop recursion at 2 controls maximum.
        Default: False.
    Returns
    -------
        A QCircuit; the result of compilation.
    """

    result = QCircuit()
    cl = 0
    if gate.is_controlled():
        cl = len(gate.control)
    if cl == 0:
        return compile_power_base(gate=gate)
    elif cl == 1:
        return get_axbxc_decomp(gate=gate)

    elif cl == 2 and not cut:
        v = type(gate)(name=gate.name,
                       power=gate.parameter / 2,
                       target=gate.target,
                       control=gate.control[1])
        result += get_axbxc_decomp(v)
        result += CNOT(gate.control[0], gate.control[1])
        vdag = type(gate)(name=gate.name,
                          power=gate.parameter / 2,
                          target=gate.target,
                          control=gate.control[1]).dagger()
        result += get_axbxc_decomp(vdag)
        result += CNOT(gate.control[0], gate.control[1])
        again = type(gate)(name=gate.name,
                           power=gate.parameter / 2,
                           target=gate.target,
                           control=gate.control[0])
        result += get_axbxc_decomp(again)

    elif cl == 2 and cut:
        if gate.name in ['CCx', 'CCNOT', 'CCX', 'X']:
            return QCircuit.wrap_gate(gate)
        else:
            v = type(gate)(name=gate.name,
                           power=gate.parameter / 2,
                           target=gate.target,
                           control=gate.control[1])
            result += get_axbxc_decomp(v)
            result += CNOT(gate.control[0], gate.control[1])
            vdag = type(gate)(name=gate.name,
                              power=gate.parameter / 2,
                              target=gate.target,
                              control=gate.control[1]).dagger()
            result += get_axbxc_decomp(vdag)
            result += CNOT(gate.control[0], gate.control[1])
            again = type(gate)(name=gate.name,
                               power=gate.parameter / 2,
                               target=gate.target,
                               control=gate.control[0])
            result += get_axbxc_decomp(again)

    else:
        v = type(gate)(name=gate.name,
                       power=gate.parameter / 2,
                       target=gate.target,
                       control=gate.control[-1])
        result += get_axbxc_decomp(v)
        result += CNOT(target=gate.control[cl - 1],
                       control=gate.control[0:cl - 1])
        vdag = type(gate)(name=gate.name,
                          power=gate.parameter / 2,
                          target=gate.target,
                          control=gate.control[-1]).dagger()
        result += get_axbxc_decomp(vdag)
        result += CNOT(target=gate.control[cl - 1],
                       control=gate.control[0:cl - 1])
        rebuild = type(gate)(name=gate.name,
                             power=gate.parameter / 2,
                             target=gate.target,
                             control=gate.control[:cl - 1])
        result += power_recursor(gate=rebuild, cut=cut)

    return result
Exemple #17
0
def power_recursor(gate, cut=False) -> QCircuit:
    '''
    if not hasattr(gate,'power'):
        return QCircuit.wrap_gate(gate)
    '''
    result = QCircuit()
    cl = 0
    if gate.is_controlled():
        cl = len(gate.control)
    if cl == 0:
        return compile_power_base(gate=gate)
    elif cl == 1:
        return get_axbxc_decomp(gate=gate)

    elif cl == 2 and not cut:
        v = type(gate)(name=gate.name,
                       power=gate.parameter / 2,
                       target=gate.target,
                       control=gate.control[1])
        result += get_axbxc_decomp(v)
        result += CNOT(gate.control[0], gate.control[1])
        vdag = type(gate)(name=gate.name,
                          power=gate.parameter / 2,
                          target=gate.target,
                          control=gate.control[1]).dagger()
        result += get_axbxc_decomp(vdag)
        result += CNOT(gate.control[0], gate.control[1])
        again = type(gate)(name=gate.name,
                           power=gate.parameter / 2,
                           target=gate.target,
                           control=gate.control[0])
        result += get_axbxc_decomp(again)

    elif cl == 2 and cut:
        if gate.name in ['CCx', 'CCNOT', 'CCX', 'X']:
            return QCircuit.wrap_gate(gate)
        else:
            v = type(gate)(name=gate.name,
                           power=gate.parameter / 2,
                           target=gate.target,
                           control=gate.control[1])
            result += get_axbxc_decomp(v)
            result += CNOT(gate.control[0], gate.control[1])
            vdag = type(gate)(name=gate.name,
                              power=gate.parameter / 2,
                              target=gate.target,
                              control=gate.control[1]).dagger()
            result += get_axbxc_decomp(vdag)
            result += CNOT(gate.control[0], gate.control[1])
            again = type(gate)(name=gate.name,
                               power=gate.parameter / 2,
                               target=gate.target,
                               control=gate.control[0])
            result += get_axbxc_decomp(again)

    else:
        v = type(gate)(name=gate.name,
                       power=gate.parameter / 2,
                       target=gate.target,
                       control=gate.control[-1])
        result += get_axbxc_decomp(v)
        result += CNOT(target=gate.control[cl - 1],
                       control=gate.control[0:cl - 1])
        vdag = type(gate)(name=gate.name,
                          power=gate.parameter / 2,
                          target=gate.target,
                          control=gate.control[-1]).dagger()
        result += get_axbxc_decomp(vdag)
        result += CNOT(target=gate.control[cl - 1],
                       control=gate.control[0:cl - 1])
        rebuild = type(gate)(name=gate.name,
                             power=gate.parameter / 2,
                             target=gate.target,
                             control=gate.control[:cl - 1])
        result += power_recursor(gate=rebuild, cut=cut)

    return result