Beispiel #1
0
def grover_invert(f, y, n):
    """Grover's algorithm for inverting a general function f that maps a
    sequence of n bits (represented as an int whose binary representation is the
    bit sequence) to another sequence of bits.

    Args:
      f: Function to invert
      y: Value of the function at which to evaluate the inverse.

    Returns:
      The input x such that f(x) = y. If more than one input suffices, it
        returns one at random. If no input suffices, returns -1.
    """
    if n <= 0:
        raise ValueError('n must be positive')

    Hn = hadamard_gate(n)
    Ui = _function_oracle(f, y, n)
    Ud = grover_diffusion_operator(n)

    MAX_ITER = 50
    count = 0
    x = None
    # Repeat until a solution is found or the iteration limit is reached
    while count < MAX_ITER and (x is None or f(x) != y):
        q = QubitSystem(n) # system of n bits in state |0>
        # apply Hadamard gate to create uniform superposition of basis states
        Hn * q

        for _ in range(_r(2**n)):
            Ui * q # apply operator that flips the sign of the matching index
            Ud * q # apply Grover's diffusion operator
        x = q.measure()
        count += 1
    return x if f(x) == y else -1
Beispiel #2
0
def shor_factor(n):
    """Shor's factorization algorithm.

    Args:
      n: Integer >=2 to factor.

    Returns:
      If n is composite, a non-trivial factor of n. If n is prime, returns 1.

    Raises:
      ValueError if n is <= 1.
    """
    if n <= 1:
        raise ValueError('n must be at least 2')
    if is_prime(n):
        return 1
    if n % 2 == 0:
        return 2 # even numbers > 2 are trivial

    # Need to check that n is not a power of an integer for algorithm to work
    root = int_root(n)
    if root != -1:
        return root

    # choose m s.t. n^2 <= 2^m < 2*n^2
    # log2(n^2) <= m <= log2(2 * n^2) = 1 + log2(n^2)
    m = ceil(log(n**2, 2))

    ny = ceil(log(n - 1, 2)) # number of qubits in output of function f
    I = QuantumGate(eye(2**ny))
    H = kron(hadamard_gate(m), I)

    MAX_ITER = 10
    niter = 0
    while True:
        a = n - 1 # arbitrary integer coprime to n

        # Initialize a system of qubits long enough to represent the integers 0
        # to 2^m - 1 alongside an integer up to n - 1, then apply Hadamard gate
        # to the first m qubits to create a uniform superposition.
        q = QubitSystem(m + ny)
        H * q

        # Apply the function f(x) = a^x (mod n) to the system
        f = lambda x: pow(a, x, n)
        Uf = function_gate(f, m, ny)
        Uf * q

        # Find the period of f via quantum Fourier transform
        qft(q)
        r = 1. / q.measure() # period = 1 / frequency

        niter += 1
        if niter >= MAX_ITER or (r % 2 == 0 and (a**(r / 2)) % n != -1):
            break
    return gcd(a**(r / 2) + 1, n)
    def test_controlled_gate(self):
        # gate that permutes the coefficients on a two-qubit system
        P = QuantumGate(array([[0., 0., 0., 1.],
                                [1., 0., 0., 0.],
                                [0., 1., 0., 0.],
                                [0., 0., 1., 0.]]))
        q1 = QubitSystem(3, 0b011)
        q2 = QubitSystem(3, 0b101)
        q3 = QubitSystem(3, 0b101)

        # controlled gate permutes the second two bits iff the first bit is one
        CG = controlled_gate(P)
        CG * q1
        self.assertEqual(q1.measure(), 0b011)
        CG * q2
        self.assertEqual(q2.measure(), 0b110)

        # test Toffoli gate, a.k.a. controlled-controlled-not gate
        T = toffoli_gate()
        T * q1
        self.assertEqual(q1.measure(), 0b011)
        T * q2
        self.assertEqual(q2.measure(), 0b111)

        # Test Fredkin gate, a.k.a. controlled swap gate
        F = fredkin_gate()
        F * q1
        self.assertEqual(q1.measure(), 0b011)
        F * q3
        self.assertEqual(q3.measure(), 0b110)
    def test_function_gate(self):
        f = lambda x: x >> 2
        m, k = 4, 2
        Uf = function_gate(f, m, k)

        # Initial state - M-bit binary string for 6 plus random K-bit register
        q = QubitSystem(m + k, 0b011010)
        # Expected output state: first M bits unchanged, followed by initial
        # string added to f(x) mod 2 (where x = first M bits)
        Uf * q
        self.assertEqual(q.measure(), 0b011011)
    def test_x_gate(self):
        X = x_gate()
        self.assertTrue((X.matrix() == array([[0., 1.], [1., 0.]])).all())

        # Test that applying the X-gate to a qubit in state |0> converts it to
        # state |1>, and vice versa
        q = QubitSystem()
        X * q
        self.assertEqual(q.measure(), 1)
        X * q
        self.assertEqual(q.measure(), 0)
    def test_tensor_product(self):
        # Test that |1> (x) |0> = |10>
        q0 = QubitSystem(1, 0)
        q1 = QubitSystem(1, 1)
        q1 * q0
        self.assertEqual(q1.measure(), 0b10)

        # Test that |0100> (x) |101> = |0100101>
        q4 = QubitSystem(4, 0b0100)
        q5 = QubitSystem(3, 0b101)
        q4 * q5
        self.assertEqual(q4.measure(), 0b0100101)
    def test_measure(self):
        # First, test measurement of a system in a pure state
        STATE = '01010'
        N = len(STATE)
        q = QubitSystem(N, int('0b' + STATE, 2))
        self.assertEqual(q.measure(), int('0b' + STATE, 2))
        self.assertEqual(q.smeasure(), STATE)
        for i in range(N):
            self.assertEqual(q.measure(i + 1), int(STATE[i]))

        # Test probabilistic measurement: repeatedly measure superpositions of
        # basis states and test that the outcome varies randomly.
        N = 2
        NTRIALS = 100
        # number of 1's in the first and second bit, respectively
        nsuccess1 = 0
        nsuccess2 = 0
        for i in range(NTRIALS):
            q = QubitSystem(N) # set the qubits to |00>
            hadamard_gate(N) * q # equal superposition of four basis states
            nsuccess1 += q.measure(1)
            nsuccess2 += q.measure(2)
        # Test that repeated measurement gives the same result
        state = q.measure()
        self.assertEqual(q.measure(), state)
        self.assertEqual(q.measure(), state)
        # Test that the number of 1's that appeared in the first and second
        # qubits is approximately half the total (within approx. 99% confidence
        # interval)
        CUTOFF = NTRIALS * 0.15
        self.assertTrue(abs(nsuccess1 - NTRIALS / 2.) < CUTOFF)
        self.assertTrue(abs(nsuccess2 - NTRIALS / 2.) < CUTOFF)
Beispiel #8
0
def grover_search(match_text, lst):
    """Grover's quantum algorithm for searching.

    Args:
      match_text: Text to find in the list lst.
      lst: List of strings to search to find a string matching match_text.

    Returns:
      The index i of the item such that lst[i] is the same string as
        match_text. The lines must match exactly; it is not enough for the text
        to be contained in the line. If two or more lines match, it will only
        return one of the line numbers. Returns -1 if no matching line is found,
        i.e. the algorithm fails to find a solution.
    """
    if len(lst) <= 0:
        raise ValueError('List must be of positive length')

    n = len(lst)
    N = int(ceil(log(n, 2))) # number of qubits needed
    Hn = hadamard_gate(N)
    Ui = _search_oracle(match_text, lst)
    Ud = grover_diffusion_operator(N)

    MAX_ITER = 50
    count = 0
    index = n
    # Repeat until a solution is found or the iteration limit is reached
    while count < MAX_ITER and (index >= n or lst[index] != match_text):
        q = QubitSystem(N) # system of log2(n) bits in state |0>
        # apply Hadamard gate to create uniform superposition of basis states
        Hn * q

        for _ in range(_r(2**N)):
            Ui * q # apply operator that flips the sign of the matching index
            Ud * q # apply Grover's diffusion operator
        index = q.measure()
        count += 1
    return index if index < n and lst[index] == match_text else -1
    def test_act(self):
        q1 = QubitSystem(2)
        q2 = QubitSystem(2, 0b10)
        SWAP = swap_gate()
        CNOT = cnot_gate()

        # SWAP * |00> = |00>
        SWAP * q1
        self.assertEqual(q1.measure(), 0b00)

        # SWAP * |10> = |01>, and vice versa
        SWAP * q2
        self.assertEqual(q2.measure(), 0b01)
        SWAP * q2
        self.assertEqual(q2.measure(), 0b10)

        # CNOT * |00> = |00>
        CNOT * q1
        self.assertEqual(q1.measure(), 0b00)

        # CNOT * |10> = |11> and vice versa
        CNOT * q2
        self.assertEqual(q2.measure(), 0b11)
        CNOT * q2
        self.assertEqual(q2.measure(), 0b10)

        # Test applying a gate to a subset of the qubits in the system
        q = QubitSystem(4)  # state 0000
        X = x_gate()

        X.act(q, 3)
        self.assertEqual(q.measure(), 0b0010)
        X.act(q, 4)
        self.assertEqual(q.measure(), 0b0011)
        SWAP.act(q, 2)
        self.assertEqual(q.measure(), 0b0101)
        SWAP * q
        self.assertEqual(q.measure(), 0b1001)