Beispiel #1
0
def test_hash_function_implemented():
    assert hash(AddConstant(3)) == hash(str(AddConstant(3)))
    assert hash(SubConstant(-3)) == hash(str(AddConstant(3)))
    assert hash(AddConstantModN(7, 4)) == hash(str(AddConstantModN(7, 4)))
    assert hash(SubConstantModN(7, 4)) == hash(str(AddConstantModN(-3, 4)))
    assert hash(MultiplyByConstantModN(3, 5)) == hash(
        MultiplyByConstantModN(3, 5))
Beispiel #2
0
def test_hash_function_implemented():
    assert hash(AddConstant(3)) == hash(str(AddConstant(3)))
    assert hash(SubConstant(-3)) == hash(str(AddConstant(3)))
    assert hash(AddConstantModN(7, 4)) == hash(str(AddConstantModN(7, 4)))
    assert hash(SubConstantModN(7, 4)) == hash(str(AddConstantModN(-3, 4)))
    assert hash(MultiplyByConstantModN(3, 5)) == hash(
        str(MultiplyByConstantModN(3, 5)))
    assert hash(AddQuantum) == hash(str(AddQuantum))
    assert hash(SubtractQuantum) == hash(str(SubtractQuantum))
    assert hash(ComparatorQuantum) == hash(str(ComparatorQuantum))
    assert hash(DivideQuantum) == hash(str(DivideQuantum))
    assert hash(MultiplyQuantum) == hash(str(MultiplyQuantum))
Beispiel #3
0
def test_factoring(sim):
    eng = get_main_engine(sim)

    ctrl_qubit = eng.allocate_qubit()

    N = 15
    a = 2

    x = eng.allocate_qureg(4)
    X | x[0]

    H | ctrl_qubit
    with Control(eng, ctrl_qubit):
        MultiplyByConstantModN(pow(a, 2**7, N), N) | x

    H | ctrl_qubit
    eng.flush()
    cheat_tpl = sim.cheat()
    idx = cheat_tpl[0][ctrl_qubit[0].id]
    vec = cheat_tpl[1]

    for i in range(len(vec)):
        if abs(vec[i]) > 1.e-8:
            assert ((i >> idx) & 1) == 0

    Measure | ctrl_qubit
    assert int(ctrl_qubit) == 0
    del vec, cheat_tpl

    H | ctrl_qubit
    with Control(eng, ctrl_qubit):
        MultiplyByConstantModN(pow(a, 2, N), N) | x

    H | ctrl_qubit
    eng.flush()
    cheat_tpl = sim.cheat()
    idx = cheat_tpl[0][ctrl_qubit[0].id]
    vec = cheat_tpl[1]

    probability = 0.
    for i in range(len(vec)):
        if abs(vec[i]) > 1.e-8:
            if ((i >> idx) & 1) == 0:
                probability += abs(vec[i])**2

    assert probability == pytest.approx(.5)

    Measure | ctrl_qubit
    Measure | x
Beispiel #4
0
def test_modmultiplier(eng):
    qureg = eng.allocate_qureg(4)
    init(eng, qureg, 4)

    MultiplyByConstantModN(3, 7) | qureg

    assert 1.0 == pytest.approx(abs(eng.backend.cheat()[1][5]))

    init(eng, qureg, 5)  # reset
    init(eng, qureg, 7)

    MultiplyByConstantModN(4, 13) | qureg
    assert 1.0 == pytest.approx(abs(eng.backend.cheat()[1][2]))

    All(Measure) | qureg
Beispiel #5
0
def modular_exponentiation(input, output, a, b):
    """
    Calculates the modular exponentiation value |O> = A^|X> mod B. The input register
	should contain the exponent and the output register will contain the result of
	the function. If |X> is in a superposition, it and |O> will be entangled so that
	whatever state |X> is measured to be, |O> will always be the solution to the function.

    Parameters:
        input (Qureg): The register representing X, the exponent of the power term.
            This can be in any superposition you want, so you can calculate the value for
            multiple inputs simultaneously.
        output (Qureg): The register representing O, which will contain the
            solution to the function.
        a (int): The base of the power term
        b (int): The modulus
    """

    X | output[-1]  # Output = |0...01>

    # Essentially, this works by converting modular exponentiation into a bunch of modular
    # multiplications. It will take n multiplications (where n is the length of the input
    # register). If the input is a uniform superposition, then it will contain 2^n possible states,
    # all of which will be calculated at the same time by this function. Thus, this offers an
    # exponential quantum speedup over classical computation.
    #
    # The reason this works is kind of mathy, and it's not hard to explain but it does require a lot
    # of math notation which is really hard to write in code comments. Nevertheless, here goes...
    #
    # Basically you can represent any number in binary, where each digit is a power of 2.
    # Take 13 for example. 13 in big-endian binary is 1101, which = 1*2^3 + 1*2^2 + 0*2^1 + 1*2^0.
    # Since you're a developer reading this code, I'm going to assume you understand how binary works.
    # So the expression A^X mod B can be rewritten by expanding X into its binary form:
    # A^X mod B = ( (A^X_0*2^n-1 mod B) * (A^X_1*2^n-2 mod B) * ... * (A^X_n-1*2^0 mod B) ) mod B.
    # When X_i == 0, the term is ignored. When X_i == 1, the term becomes A^2^(n-i-1) mod B.
    # Essentially that means we can do a modular multiplication for each term, and just use the bits of X
    # as controls for it. A^2^(n-i-1) is easy for a classical computer to calculate, so basically this
    # implements quantum modular exponentiation by turning it into a bunch of quantum modular
    # multiplications and classical modular exponentiations. Since it only does n iterations of either one,
    # but can run on 2^n states simultaneously, this is a big win.
    #
    # This would normally be a fine way to calculate things if you had an input and output register,
    # but the Q# version of modular multiplication runs in-place which means it only has one register for
    # the input and output.
    # (Note: since Cirq doesn't come with one of these functions, I ported Q#'s code over to Cirq so I
    # can actually implement Shor's algorihtm).
    # This means we have to redo the equation a little bit which involves way too many parentheses to write
    # here, but the end result is the same: repeat the calculation |O> = |O> * c mod B for each qubit in
    # the input register, where X_i controls the multiplication and c = A^(2^(n-i-1)) mod B.

    input_size = len(input)
    for i in range(0, input_size):
        power_of_two = input_size - 1 - i  # n-i-1
        power_of_guess = 2**power_of_two  # 2^(n-i-1)
        constant = pow(a, power_of_guess, b)  # c = A^(2^(n-i-1)) mod B

        # Note: ProjectQ is the first Python framework to actually have a math library
        # with it, so I can use their MultiplyByConstantModN implementation instead of
        # porting my own over from the previous libraries. This is quite helpful.
        with Control(input.engine, input[i]):
            MultiplyByConstantModN(constant, b) | output  # |O> = |O> * c mod B
Beispiel #6
0
def find_period(engine, N):
    n = int(np.ceil(np.log2(N)))

    a = shor.find_co_prime_stochastic(N)
    if a < 0:
        print("Factor is", -a)
        exit(0)
    print("a =", a)
    qubits = engine.allocate_qureg(3 * n)

    All(H) | qubits[0:(2 * n)]

    for i in range(2 * n):
        C(MultiplyByConstantModN(pow(a, 2**i, N),
                                 N)) | (qubits[i], qubits[(2 * n):(3 * n)])

    qft.qft_inverse(engine, qubits[0:(2 * n)])

    All(Measure) | qubits

    engine.flush()
    measurements = [int(q) for q in qubits[0:(2 * n)]]
    y = sum([(measurements[2 * n - 1 - i] * 1. / (1 << (i + 1)))
             for i in range(2 * n)])
    period = Fraction(y).limit_denominator(N - 1).denominator
    print("period found =", period)
    if period % 2 != 0:
        period *= 2

    if np.mod(period, 2) == 0:
        print(shor.find_prime_factors(N, pow(a, int(period / 2))))
    print('\nMeasured: {0}'.format([int(q) for q in qubits]))
Beispiel #7
0
def shor(eng, entrada, inicial):
    n = int(ceil(log(entrada, 2)))
    x = eng.allocate_qureg(n)
    X | x[0]
    medidas = [0] * (2 * n)
    ctrl = eng.allocate_qubit()
    for i in range(2 * n):
        a_novo = pow(2**(2 * n - 1 - i),
                     entrada)  #exponenciacao modular em Python
        H | ctrl
        with Control(eng, ctrl):
            MultiplyByConstantModN(
                a_novo, entrada) | x  #exponenciacao modular quantica
        for j in range(i):
            if medidas[j]:
                R(-pi / (2**(i - j))) | ctrl  #transformada de Fourier quantica
        H | ctrl
        Measure | ctrl
        eng.flush()
        if medidas[i]:
            X | ctrl
    Measure | x
    y = sum([(medidas[2 * n - 1 - j] * 1. / (2**(j + 1)))
             for j in range(2 * n)])
    s = Fraction(y).limit_denominator(entrada - 1).denominator
    return s
Beispiel #8
0
def run_shor(eng, N, a, verbose=False):
    """
    Runs the quantum subroutine of Shor's algorithm for factoring.

    Args:
        eng (MainEngine): Main compiler engine to use.
        N (int): Number to factor.
        a (int): Relative prime to use as a base for a^x mod N.
        verbose (bool): If True, display intermediate measurement results.

    Returns:
        r (float): Potential period of a.
    """
    n = int(math.ceil(math.log(N, 2)))

    x = eng.allocate_qureg(n)

    X | x[0]

    measurements = [0] * (2 * n)  # will hold the 2n measurement results

    ctrl_qubit = eng.allocate_qubit()

    for k in range(2 * n):
        current_a = pow(a, 1 << (2 * n - 1 - k), N)
        # one iteration of 1-qubit QPE
        H | ctrl_qubit

        with Control(eng, ctrl_qubit):
            MultiplyByConstantModN(current_a, N) | x

        # perform inverse QFT --> Rotations conditioned on previous outcomes
        for i in range(k):
            if measurements[i]:
                R(-math.pi / (1 << (k - i))) | ctrl_qubit
        H | ctrl_qubit

        # and measure
        Measure | ctrl_qubit
        eng.flush()
        measurements[k] = int(ctrl_qubit)
        if measurements[k]:
            X | ctrl_qubit

        if verbose and MPI.COMM_WORLD.Get_rank() == 0:
            print("\033[95m{}\033[0m".format(measurements[k]), end="")
            sys.stdout.flush()

    All(Measure) | x

    # turn the measured values into a number in [0,1)
    y = sum([(measurements[2 * n - 1 - i] * 1. / (1 << (i + 1)))
             for i in range(2 * n)])

    # continued fraction expansion to get denominator (the period?)
    r = Fraction(y).limit_denominator(N - 1).denominator

    # return the (potential) period
    return r
Beispiel #9
0
def test_modmultiplier():
	sim = Simulator()
	eng = MainEngine(sim, [AutoReplacer(),
	                       InstructionFilter(no_math_emulation)])
	
	qureg = eng.allocate_qureg(4)
	init(eng, qureg, 4)
	
	MultiplyByConstantModN(3, 7) | qureg
	
	assert 1. == pytest.approx(abs(sim.cheat()[1][5]))
	
	init(eng, qureg, 5)  # reset
	init(eng, qureg, 7)
	
	MultiplyByConstantModN(4, 13) | qureg
	assert 1. == pytest.approx(abs(sim.cheat()[1][2]))
	
	Measure | qureg
Beispiel #10
0
def test_restriction():
    engine_list = restrictedgateset.get_engine_list(
        one_qubit_gates=(Rz, H),
        two_qubit_gates=(CNOT, AddConstant, Swap),
        other_gates=(Toffoli, AddConstantModN, MultiplyByConstantModN(2, 8)),
    )
    backend = DummyEngine(save_commands=True)
    eng = projectq.MainEngine(backend, engine_list, verbose=True)
    qubit1 = eng.allocate_qubit()
    qubit2 = eng.allocate_qubit()
    qubit3 = eng.allocate_qubit()
    eng.flush()
    CNOT | (qubit1, qubit2)
    H | qubit1
    with Control(eng, qubit2):
        Rz(0.2) | qubit1
    Measure | qubit1
    AddConstant(1) | (qubit1 + qubit2)
    AddConstantModN(1, 9) | (qubit1 + qubit2 + qubit3)
    Toffoli | (qubit1 + qubit2, qubit3)
    Swap | (qubit1, qubit2)
    MultiplyByConstantModN(2, 8) | qubit1 + qubit2 + qubit3
    TimeEvolution(0.5, QubitOperator("X0 Y1 Z2")) | qubit1 + qubit2 + qubit3
    QFT | qubit1 + qubit2 + qubit3
    Rx(0.1) | (qubit1)
    MultiplyByConstantModN(2, 9) | qubit1 + qubit2 + qubit3
    eng.flush()
    assert backend.received_commands[4].gate == X
    assert len(backend.received_commands[4].control_qubits) == 1
    assert backend.received_commands[5].gate == H
    assert backend.received_commands[6].gate == Rz(0.1)
    assert backend.received_commands[10].gate == Measure
    assert backend.received_commands[11].gate == AddConstant(1)
    assert backend.received_commands[12].gate == AddConstantModN(1, 9)
    assert backend.received_commands[13].gate == X
    assert len(backend.received_commands[13].control_qubits) == 2
    assert backend.received_commands[14].gate == Swap
    assert backend.received_commands[15].gate == MultiplyByConstantModN(2, 8)
    for cmd in backend.received_commands[16:]:
        assert cmd.gate != QFT
        assert not isinstance(cmd.gate, Rx)
        assert not isinstance(cmd.gate, MultiplyByConstantModN)
        assert not isinstance(cmd.gate, TimeEvolution)
Beispiel #11
0
    def run_simulation(sim):
        eng = MainEngine(sim, [])
        quint = eng.allocate_qureg(5)
        AddConstant(3) | quint
        All(Measure) | quint
        eng.flush()
        results[0].append([int(qb) for qb in quint])

        AddConstantModN(4, 5) | quint
        All(Measure) | quint
        eng.flush()
        results[1].append([int(qb) for qb in quint])

        MultiplyByConstantModN(15, 16) | quint
        All(Measure) | quint
        eng.flush()
        results[2].append([int(qb) for qb in quint])
Beispiel #12
0
def run_shor(eng, q, x, showMeasure, N):
    n = int(math.ceil(math.log(q - 1, 2)))
    if showMeasure:
        print("\n\tn: ", n)

    a = eng.allocate_qureg(n)
    All(H) | a

    measurements = [0] * (n)

    ctrl_qubit = eng.allocate_qubit()

    for k in range(n):
        print("K: ", k)
        current_x = pow(x, 1 << (n - 1 - k))
        print("PROBLEM1")
        H | ctrl_qubit
        with Control(eng, ctrl_qubit):
            MultiplyByConstantModN(current_x, N) | a  #PROBLEM
            print("PROBLEM2")

        # and measure
        Measure | ctrl_qubit
        eng.flush()
        measurements[k] = int(ctrl_qubit)

        if showMeasure:
            print("\033[95m{}\033[0m".format(measurements[k]), end="")
            sys.stdout.flush()

    All(Measure) | a
    m = 0
    print("\n")
    for i in range(n):
        m += measurements[n - 1 - i] * 1. / (1 << (i + 1)
                                             )  #Value of m/q in Hayward's

    r = Fraction(m).limit_denominator(N - 1).denominator  #PROBLEM
    print("PROBLEM3")

    return r
def ExecuteShorAlgorithm(eng, N, a, verbose=False):
    n = int(math.ceil(math.log(N, 2)))

    x = eng.allocate_qureg(n)

    X | x[0]

    measurements = [0] * (2 * n)
    ctrl_qubit = eng.allocate_qubit()

    for k in range(2 * n):
        current_a = pow(a, 1 << (2 * n - 1 - k), N)
        H | ctrl_qubit
        with Control(eng, ctrl_qubit):
            MultiplyByConstantModN(current_a, N) | x

        for i in range(k):
            if measurements[i]:
                R(-math.pi / (1 << (k - i))) | ctrl_qubit
        H | ctrl_qubit

        Measure | ctrl_qubit
        eng.flush()
        measurements[k] = int(ctrl_qubit)
        if measurements[k]:
            X | ctrl_qubit

        if verbose:
            print("\033[95m{}\033[0m".format(measurements[k]), end="")
            sys.stdout.flush()

    All(Measure) | x
    y = sum([(measurements[2 * n - 1 - i] * 1. / (1 << (i + 1)))
             for i in range(2 * n)])

    r = Fraction(y).limit_denominator(N - 1).denominator

    return r
Beispiel #14
0
def test_multiplybyconstmodn():
    assert MultiplyByConstantModN(3, 4) == MultiplyByConstantModN(3, 4)
    assert not MultiplyByConstantModN(3, 4) == MultiplyByConstantModN(4, 4)
    assert not MultiplyByConstantModN(3, 5) == MultiplyByConstantModN(3, 4)
    assert MultiplyByConstantModN(7, 4) != MultiplyByConstantModN(3, 4)
    assert MultiplyByConstantModN(3, 5) != MultiplyByConstantModN(3, 4)

    assert str(MultiplyByConstantModN(3, 4)) == "MultiplyByConstantModN(3, 4)"
Beispiel #15
0
    def test_period_6(self):
        """
        Tests QFT by running a single iteration of the period-finding subroutine from
	    Shor's algorithm. This test will use 21 as the number to factor, 11 as the
	    original guess, and ensure that QFT reports that the modular exponential
	    equation has a period of 6.
        """

        # So this test basically just runs a hardcoded iteration of the quantum portion
		# of Shor's algorithm. I don't want to explain the entire thing here; you can
		# look at shor.py for my implementation, which has plenty of documentation
		# attached to it. For this test, I'm trying to factor 21. That means the
		# "output" register needs to be 5 qubits (because 2^4 = 16 and 2^5 = 32, so it
		# needs 5 qubits to be represented in binary). For the input register, I'm going
		# with 9 qubits: 21^2 = 441, 2^8 = 256, and 2^9 = 512, so 21^2 needs 9 qubits to
		# be represented in binary. That will give 512 discrete states. For a guess of
		# 11, the period will be 6:
		# -------------------------
		#  State (i) | 11^i mod 21
		# -------------------------
		#          0 | 1
		#          1 | 11
		#          2 | 16
		#          3 | 8
		#          4 | 4
		#          5 | 2
		#          6 | 1	<== Pattern repeats here, after 6 entries
		#          7 | 11
		#          8 | 16
		#          ...
		#
		# QFT should return some value X which, when divided by 512, should be really
		# close to 0/6, 1/6, 2/6, 3/6, 4/6, or 5/6. The amplitude peaks (the expected
		# values) are 0, 85, 171, 256, 341, and 427.

        input_length = 9
        output_length = 5
        number_to_factor = 21
        guess = 11
        
        engine = MainEngine()
        input = engine.allocate_qureg(input_length)
        output = engine.allocate_qureg(output_length)

        All(H) | input  # Input = |+...+>
        X | output[-1]  # Output = |0...01>

        # Do the arithmetic so the input register is entangled with the output register; after
		# this, if the state X is measured on the input register, the output register will always
		# be measured as 11^X mod 21.
        for i in range(0, input_length):
            power_of_two = input_length - 1 - i
            power_of_guess = 2 ** power_of_two
            constant = pow(guess, power_of_guess, number_to_factor)

            # Note: ProjectQ is the first Python framework to actually have a math library
            # with it, so I can use their MultiplyByConstantModN implementation instead of
            # porting my own over from the previous libraries. This is quite helpful.
            with Control(engine, input[i]):
                MultiplyByConstantModN(constant, number_to_factor) | output

        # Run inverse QFT (the analog of the normal DFT) to find the period
        with Dagger(engine):
            qft.qft(input)

        result_string = ""
        for qubit in input:
            Measure | qubit
            result_string += str(int(qubit))
        result = int(result_string, 2)

        # Measure the resulting period and make sure it's close to a multiple of 1/6,
        # with a tolerance of 0.01.
        scaled_measurement = result / 512 * 6
        nearest_multiple = round(scaled_measurement)
        delta = abs(scaled_measurement - nearest_multiple)

        # Cleanup
        reset(output)
        engine.flush()

        print(f"Measured {result}/512 => {scaled_measurement}, delta = {delta}")
        if delta >= 0.01:
            self.fail(f"QFT failed, delta of {delta} is too high.")
            
        print("Passed!")
Beispiel #16
0
def eng():
    return MainEngine(
        backend=Simulator(),
        engine_list=[
            AutoReplacer(rule_set),
            InstructionFilter(no_math_emulation)
        ],
    )


rule_set = DecompositionRuleSet(
    modules=[projectq.libs.math, qft2crandhadamard, swap2cnot])


@pytest.mark.parametrize('gate',
                         (AddConstantModN(-1, 6), MultiplyByConstantModN(
                             -1, 6), MultiplyByConstantModN(4, 4)),
                         ids=str)
def test_invalid(eng, gate):
    qureg = eng.allocate_qureg(4)
    init(eng, qureg, 4)

    with pytest.raises(ValueError):
        gate | qureg
        eng.flush()


def test_adder(eng):
    qureg = eng.allocate_qureg(4)
    init(eng, qureg, 4)

    AddConstant(3) | qureg