예제 #1
0
    def __init__(self):
        """
        Initializes the gate to  its base class, BasicMathGate, with the 
        corresponding function, so it can be emulated efficiently.
        """
        def subtract(a, b):
            return (a, b - a)

        BasicMathGate.__init__(self, subtract)
예제 #2
0
def test_limited_capability_engine_arithmetic():
    default_eng = LimitedCapabilityEngine()
    eng = LimitedCapabilityEngine(allow_arithmetic=True)
    m = MainEngine(backend=DummyEngine(), engine_list=[eng])
    q = m.allocate_qureg(5)

    inc = BasicMathGate(lambda x: x + 1)
    assert not default_eng.is_available(inc.generate_command(q))
    assert eng.is_available(inc.generate_command(q))
예제 #3
0
    def __init__(self, a):
        """
        Initializes the gate to the base of which the inverse needs to be found
        Args:
            base (int): base of which the inverse needs to be found for modular 
                        multiplication
        It also initializes its base class, BasicMathGate, with the
        corresponding function, so it can be emulated efficiently.
        """
        def extended_gcd(a, b):
            # calculates the gcd and the coefficients of Bezout's identity
            lastremainder, remainder = abs(a), abs(b)
            x, lastx, y, lasty = 0, 1, 1, 0
            while remainder != 0:
                lastremainder, (quotient, remainder) = remainder, divmod(
                    lastremainder, remainder)
                x, lastx = lastx - quotient * x, x
                y, lasty = lasty - quotient * y, y
            return lastremainder, lastx, lasty

        def find_inverse(value, mod):
            # if the gcd is not equal to one, the value does not have an inverse.
            # if it is, the inverse is the first Bezout coefficient modulus mod
            (gcd, x, y) = extended_gcd(value, mod)
            if gcd != 1:
                return 'undefined'
            return x % mod

        def mod(exponent, modulus, val):
            # does not change the val if it is bigger than the modulus (this
            # would be irreversible) or if the modulus = 0 (division by 0 not
            # possible)
            base = a
            if exponent == 0 or modulus == 0 or val >= modulus:
                return (exponent, modulus, val)
            else:
                base = base
                inverse = find_inverse(base, modulus)

                if inverse == 'undefined':
                    return (exponent, modulus, val)
                exp = exponent

                while (exp > 0):
                    # if exp is odd, multiply inverse with val
                    if ((exp & 1) != 0):
                        val = (val * inverse) % modulus
                    # square the inverse (base)
                    inverse = (inverse * inverse) % modulus
                    # binary shift
                    exp >>= 1
                return (exponent, modulus, val)

        BasicMathGate.__init__(self, mod)
        self.a = a
예제 #4
0
    def __init__(self, a):
        """
        Initializes the gate to the number to add.

        Args:
            a (int): Number to add to a quantum register.

        It also initializes its base class, BasicMathGate, with the
        corresponding function, so it can be emulated efficiently.
        """
        BasicMathGate.__init__(self, lambda x: ((x + a), ))
        self.a = a
예제 #5
0
    def __init__(self):
        """
        Initializes the gate to  its base class, BasicMathGate, with the
        corresponding function, so it can be emulated efficiently.
        """
        def compare(a, b, c):
            if b < a:
                if c == 0:
                    c = 1
                else:
                    c = 0
            return (a, b, c)

        BasicMathGate.__init__(self, compare)
예제 #6
0
    def __init__(self):
        """
        Initializes the gate to  its base class, BasicMathGate, with the
        corresponding function, so it can be emulated efficiently. 
        """
        def mod(modulus, val):
            if modulus == 0 or val >= modulus:
                return (modulus, val)
            if val == 0:
                return (modulus, modulus - 1)
            else:
                return (modulus, val - 1)

        BasicMathGate.__init__(self, mod)
예제 #7
0
    def __init__(self, a, N):
        """
        Initializes the gate to the number to add modulo N.

        Args:
            a (int): Number to add to a quantum register (0 <= a < N).
            N (int): Number modulo which the addition is carried out.

        It also initializes its base class, BasicMathGate, with the
        corresponding function, so it can be emulated efficiently.
        """
        BasicMathGate.__init__(self, lambda x: ((x + a) % N, ))
        self.a = a
        self.N = N
예제 #8
0
def test_simulator_is_available(sim):
    backend = DummyEngine(save_commands=True)
    eng = MainEngine(backend, [])
    qubit = eng.allocate_qubit()
    Measure | qubit
    BasicMathGate(lambda x: x) | qubit
    del qubit
    assert len(backend.received_commands) == 4

    # Test that allocate, measure, basic math, and deallocate are available.
    for cmd in backend.received_commands:
        assert sim.is_available(cmd)

    new_cmd = backend.received_commands[-1]

    new_cmd.gate = Mock1QubitGate()
    assert sim.is_available(new_cmd)
    assert new_cmd.gate.cnt == 1

    new_cmd.gate = Mock2QubitGate()
    assert not sim.is_available(new_cmd)
    assert new_cmd.gate.cnt == 1

    new_cmd.gate = MockNoMatrixGate()
    assert not sim.is_available(new_cmd)
    assert new_cmd.gate.cnt == 1

    eng = MainEngine(sim, [])
    qubit1 = eng.allocate_qubit()
    qubit2 = eng.allocate_qubit()
    with pytest.raises(Exception):
        Mock2QubitGate() | (qubit1, qubit2)
예제 #9
0
def test_simulator_is_available(sim):
    backend = DummyEngine(save_commands=True)
    eng = MainEngine(backend, [])
    qubit = eng.allocate_qubit()
    Measure | qubit
    BasicMathGate(lambda x: x) | qubit
    qubit[0].__del__()
    assert len(backend.received_commands) == 4

    # Test that allocate, measure, basic math, and deallocate are available.
    for cmd in backend.received_commands:
        assert sim.is_available(cmd)

    new_cmd = backend.received_commands[-1]

    new_cmd.gate = Mock1QubitGate()
    assert sim.is_available(new_cmd)
    assert new_cmd.gate.cnt == 4

    new_cmd.gate = Mock6QubitGate()
    assert not sim.is_available(new_cmd)
    assert new_cmd.gate.cnt == 4

    new_cmd.gate = MockNoMatrixGate()
    assert not sim.is_available(new_cmd)
    assert new_cmd.gate.cnt == 7
예제 #10
0
    def __init__(self, a):
        """
        Initializes the gate to the base to be used for modular 
        exponentiation.
        Args:
            base (int): base for the modular exponentiation.  
        It also initializes its base class, BasicMathGate, with the
        corresponding function, so it can be emulated efficiently.
        
        Example:
            .. code-block:: python
            MultiplyModN(2) | (qureg1, qureg2, qureg3)
        """
        def mod(exponent, modulus, val):
            # does not change the val if it is bigger than the modulus (this
            # would be irreversible) or if the modulus = 0 (division by 0 not
            # possible)
            if modulus == 0 or val >= modulus:
                return (exponent, modulus, val)

            else:
                # repeated squaring algorithm
                base = a
                exp = exponent
                while (exp > 0):
                    # if exp is odd, multiply inverse with val
                    if ((exp & 1) != 0):
                        val = (val * base) % modulus
                    # square the base
                    base = (base * base) % modulus
                    # binary shift
                    exp >>= 1
                return (exponent, modulus, val)

        BasicMathGate.__init__(self, mod)
        self.a = a
예제 #11
0
 def __init__(self):
     BasicMathGate.__init__(self, lambda x, y: (x, y - x))
예제 #12
0
 def __init__(self, amount):
     BasicMathGate.__init__(self, lambda x: (x + amount, ))
    def __init__(self):
        def do_not_call(*_):
            raise AssertionError()

        BasicGateEx.__init__(self)
        BasicMathGate.__init__(self, do_not_call)
예제 #14
0
 def __init__(self):
     BasicMathGate.__init__(self, lambda x: (x + 2, ))
예제 #15
0
def zoo_profile():
    """Generate and display the zoo of quantum gates."""
    # create a main compiler engine with a drawing backend
    drawing_engine = CircuitDrawer()
    locations = {0: 1, 1: 2, 2: 0, 3: 3}
    drawing_engine.set_qubit_locations(locations)
    main_eng = MainEngine(drawing_engine)
    qureg = main_eng.allocate_qureg(4)

    # define a zoo of gates
    te_gate = TimeEvolution(0.5, 0.1 * QubitOperator('X0 Y2'))

    def add(x, y):
        return x, y + 1

    zoo = [
        (X, 3),
        (Y, 2),
        (Z, 0),
        (Rx(0.5), 2),
        (Ry(0.5), 1),
        (Rz(0.5), 1),
        (Ph(0.5), 0),
        (S, 3),
        (T, 2),
        (H, 1),
        (Toffoli, (0, 1, 2)),
        (Barrier, None),
        (Swap, (0, 3)),
        (SqrtSwap, (0, 1)),
        (get_inverse(SqrtSwap), (2, 3)),
        (SqrtX, 2),
        (C(get_inverse(SqrtX)), (0, 2)),
        (C(Ry(0.5)), (2, 3)),
        (CNOT, (2, 1)),
        (Entangle, None),
        (te_gate, None),
        (QFT, None),
        (Tensor(H), None),
        (BasicMathGate(add), (2, 3)),
        (All(Measure), None),
    ]

    # apply them
    for gate, pos in zoo:
        if pos is None:
            gate | qureg
        elif isinstance(pos, tuple):
            gate | tuple(qureg[i] for i in pos)
        else:
            gate | qureg[pos]

    main_eng.flush()

    # generate latex code to draw the circuit
    s = drawing_engine.get_latex()
    prefix = 'zoo'
    with open('{}.tex'.format(prefix), 'w') as f:
        f.write(s)

    # compile latex source code and open pdf file
    os.system('pdflatex {}.tex'.format(prefix))
    openfile('{}.pdf'.format(prefix))
예제 #16
0
def shor(N):
    # Check if number is even
    if N % 2 == 0:
        print('Even number.')
        return 2  
     
    # Step 1: Chose 1 < a < N uniformly at random
    a = np.random.randint(2,N)
    
    # Step 2: Compute b = gcd(a,N). If b > 1, output b and stop
    b = gcd(a,N)
    if b > 1:
        print('Factor found by guessing:', b)
        return b
    
    # Step 3: Find the order r of a modulo N for f(x) = a^x mod N
    # Quantum Part: using approximate periodicity to find r
    
    m = int(np.ceil(np.log2(N**2)))   # Size of first register
    M = 2**m   # M is the smallest power of 2 greater than N^2
    n = int(np.ceil(np.log2(N-1)))   # Size of second register - need to represent 0 to N-1
    
    # Check we can simulate on our local simulator
    if m + n > 28:   # 28 qubits = 4GB of RAM
        print('Number of qubits required =', m+n, 'which is too large to simulate.')
        return 0

    engine = MainEngine()
    # Initialise registers
    reg_1 = engine.allocate_qureg(m)
    reg_2 = engine.allocate_qureg(n)

    # Apply QFT to first register 
    All(H) | reg_1

    # Define the oracle O_f|x>|y> = |x>|y + f(x)> where + is bitwise XOR
    def O_f(x,y) : return (x, y^pow(a,x,N)) 
    # Apply oracle to both registers
    BasicMathGate(O_f) | (reg_1, reg_2)
    
    # Measure the second register 
    All(Measure) | reg_2
    
    # Apply the QFT to the first register
    #QFT | reg_1
    for i in reversed(range(m)):
        H | reg_1[i]
        for d in range(1,i+1):
            C(R(np.pi/(2**d))) | (reg_1[i-d], reg_1[i])
    for i in range(int(m/2)):
        Swap | (reg_1[i], reg_1[m-i-1])
    
    # Measure the first register
    All(Measure) | reg_1
    
    # Run the approximate peridicity algorithm
    engine.flush()
    
    # Determine output y of algorithm 
    y = 0
    for i in range(m):
        y = y + 2**i*int(reg_1[i])
    
    # Use continued fraction expansion of z = y/M to find r
    r = Fraction(y,M).limit_denominator(N).denominator

    # If r is odd the algorithm fails
    if r % 2 == 1:
        print('Order r found is odd: algorithm failed')
        return 0
    
    # Step 4: Find factor of N
    s = gcd(a**(r//2)-1, N)
    if s == 1 or s == N:
        print('Factor found is 1 or', N,': algorithm failed')
        return N
    
    print('Factor found by Shor\'s algorithm is', s, 'using', m+n, 'qubits')
    return s
def shor(N):
    # Check if number is even
    if N % 2 == 0:
        print('Even number.')
        return 2

    # Step 1: Chose 1 < a < N uniformly at random
    a = np.random.randint(2, N)
    #a = 11
    # Step 2: Compute b = gcd(a,N). If b > 1, output b and stop
    b = gcd(a, N)
    if b > 1:
        print('Factor found by guessing:', b)
        return b

    # Step 3: Find the order r of a modulo N for f(x) = a^x mod N
    # Quantum Part: using approximate periodicity to find r

    m = int(np.ceil(np.log2(N**2)))  # Size of first register
    M = 2**m  # M is the smallest power of 2 greater than N^2
    n = int(np.ceil(
        np.log2(N -
                1)))  # Size of second register - need to represent 0 to N-1

    # Check we can simulate on our local simulator
    if m + n > 28:  # 28 qubits = 4GB of RAM
        print('Number of qubits required =', m + n,
              'which is too large to simulate.')
        return 0

    engine = MainEngine()
    # Initialise registers
    reg_1 = engine.allocate_qureg(m)
    reg_2 = engine.allocate_qureg(n)

    # Apply QFT to first register
    All(H) | reg_1

    # Define the oracle O_f|x>|y> = |x>|y + f(x)> where + is bitwise XOR
    def O_f(x, y):
        return (x, y ^ pow(a, x, N))

    # Apply oracle to both registers
    BasicMathGate(O_f) | (reg_1, reg_2)

    # Measure the second register
    All(Measure) | reg_2
    engine.flush()
    y = 0
    for i in range(n):
        y = y + 2**i * int(reg_2[i])
        Deallocate | reg_2[i]
        #engine.deallocate_qubit(reg_2[i])
    print(y)
    engine.flush()
    mapping, wavefunction = engine.backend.cheat()
    #print(wavefunction)
    #    plt.plot(abs(np.asarray(wavefunction)), '.')
    #    plt.show()

    fft_wf = fft(wavefunction)
    plt.plot(abs(fft_wf))
    plt.title('FFT')
    plt.show()

    # Apply the QFT to the first register
    QFT | reg_1
    for i in range(int(m / 2)):
        Swap | (reg_1[i], reg_1[m - i - 1])
    #qft(reg_1)

    engine.flush()
    mapping, wavefunction = engine.backend.cheat()
    #print(wavefunction)
    d = np.nonzero(wavefunction)
    print(d)
    plt.plot(abs(np.asarray(wavefunction)))
    plt.title('QFT')
    plt.show()

    #    wavefunction_reg2 = np.zeros(16)
    #    for k in range(16) :
    #        #wavefunction_reg2[k] = np.sum(wavefunction[256*k: 256*k+255])
    #        for i in range(256) : wavefunction_reg2[k] += wavefunction[256*k + i]
    #
    #    wavefunction_reg1 = np.zeros(256)
    #    for k in range(256) :
    #        for i in range(i) : wavefunction_reg1[k] += wavefunction[k + 16*i]
    #
    #    plt.plot(wavefunction_reg2, '.')
    #    plt.show()
    # Measure the first register
    All(Measure) | reg_1

    # Run the approximate peridicity algorithm
    engine.flush()

    # Determine output y of algorithm
    y = 0
    for i in range(m):
        y = y + 2**i * int(reg_1[i])

    # Use continued fraction expansion of z = y/M to find r
    r = Fraction(y, M).limit_denominator(N).denominator
    print(y, r)

    # If r is odd the algorithm fails
    if r % 2 == 1:
        print('Order r found is odd: algorithm failed')
        return 0

    # Step 4: Find factor of N
    s = gcd(a**(r // 2) - 1, N)
    if s == 1 or s == N:
        print('Factor found is 1 or', N, ': algorithm failed')
        return N

    print('Factor found by Shor\'s algorithm is', s, 'using', m + n, 'qubits')
    return s
예제 #18
0
 def __init__(self):
     """
     Initializes the gate to  its base class, BasicMathGate, with the 
     corresponding function, so it can be emulated efficiently.
     """
     BasicMathGate.__init__(self, AddQuantum.get_math_function)
예제 #19
0
 def __init__(self):
     BasicMathGate.__init__(self, subtract)
예제 #20
0
 def __init__(self):
     BasicMathGate.__init__(self, add)