Пример #1
0
    def encode_zero(self, prog: Program, block: CodeBlock, ancilla: CodeBlock, scratch: MemoryChunk):
        if len(scratch) < self.error_correct_scratch_size:
            raise ValueError("scratch buffer is too small")

        flag = scratch[0]
        outcome = scratch[1]
        scratch = scratch[2:]

        # To do a somewhat fault tolerant preparation, we will do a noisy preparation of the target
        # block, then perform a Steane error correction using a noisy ancilla. Instead of actually
        # doing an error correction though, we will just do error detection and repeat until no
        # errors are detected. If no errors are detected, then either both the block and ancilla
        # were clean or they both has the exact same errors, which is unlikely. This idea comes from
        # section 4.6 of "An Introduction to Quantum Error Correction and Fault-Tolerant Quantum
        # Computation" by Daniel Gottesman.
        loop_prog = Program()
        loop_prog += gates.MOVE(flag, 0)

        block.reset(loop_prog)
        loop_prog += self.noisy_encode_zero(block.qubits)

        self._error_detect_x(loop_prog, block, ancilla, outcome, scratch, include_operators=True)
        loop_prog += gates.IOR(flag, outcome)

        self._error_detect_z(loop_prog, block, ancilla, outcome, scratch, include_operators=False)
        loop_prog += gates.IOR(flag, outcome)

        prog += gates.MOVE(flag, 1)
        prog.while_do(flag, loop_prog)
Пример #2
0
def test_extract_qubits():
    p = Program(RX(0.5)(0), RY(0.1)(1), RZ(1.4)(2))
    assert p.extract_qubits() == set([0, 1, 2])
    p.if_then(0, X(4), H(5)).measure(6, 2)
    assert p.extract_qubits() == set([0, 1, 2, 4, 5, 6])
    p.while_do(0, Program(X(3)).measure(3, 0))
    assert p.extract_qubits() == set([0, 1, 2, 3, 4, 5, 6])
    new_qubit = p.alloc()
    p.inst(X(new_qubit))
    p.synthesize()
    assert p.extract_qubits() == set([0, 1, 2, 3, 4, 5, 6, new_qubit.index()])
Пример #3
0
def test_control_flows():
    classical_flag_register = 2
    p = Program(X(0), H(0)).measure(0, classical_flag_register)

    # run p in a loop until classical_flag_register is 0
    loop_prog = Program(X(0)).measure(0, classical_flag_register)
    loop_prog.while_do(classical_flag_register, p)
    assert loop_prog.out() == 'X 0\nMEASURE 0 [2]\nLABEL @START1\nJUMP-UNLESS @END2 [2]\nX ' \
                              '0\nH 0\nMEASURE 0 [2]\nJUMP @START1\nLABEL @END2\n'

    # create a program that branches based on the value of a classical register
    x_prog = Program(X(0))
    z_prog = Program()
    branch = Program(H(1)).measure(1, 1).if_then(1, x_prog, z_prog).measure(0, 0)
    assert branch.out() == 'H 1\nMEASURE 1 [1]\nJUMP-WHEN @THEN1 [1]\nJUMP @END2\nLABEL ' \
                           '@THEN1\nX 0\nLABEL @END2\nMEASURE 0 [0]\n'
Пример #4
0
def test_control_flows():
    classical_flag_register = 2
    p = Program(X(0), H(0)).measure(0, classical_flag_register)

    # run p in a loop until classical_flag_register is 0
    loop_prog = Program(X(0)).measure(0, classical_flag_register)
    loop_prog.while_do(classical_flag_register, p)
    assert loop_prog.out() == ('DECLARE ro BIT[3]\n'
                               'X 0\n'
                               'MEASURE 0 ro[2]\n'
                               'LABEL @START1\n'
                               'JUMP-UNLESS @END2 ro[2]\n'
                               'X 0\n'
                               'H 0\n'
                               'MEASURE 0 ro[2]\n'
                               'JUMP @START1\n'
                               'LABEL @END2\n')
Пример #5
0
def test_control_flows():
    outer_loop = Program()
    classical_flag_register = outer_loop.declare('classical_flag_register',
                                                 'BIT')
    outer_loop += MOVE(classical_flag_register, 1)  # initialize

    inner_loop = Program()
    inner_loop += Program(X(0), H(0))
    inner_loop += MEASURE(0, classical_flag_register)

    # run inner_loop in a loop until classical_flag_register is 0
    outer_loop.while_do(classical_flag_register, inner_loop)
    assert outer_loop.out() == '\n'.join([
        "DECLARE classical_flag_register BIT[1]",
        "MOVE classical_flag_register 1", "LABEL @START1",
        "JUMP-UNLESS @END2 classical_flag_register", "X 0", "H 0",
        "MEASURE 0 classical_flag_register", "JUMP @START1", "LABEL @END2", ""
    ])
Пример #6
0
def test_while():
    init_register = Program()
    classical_flag_register = init_register.declare("classical_flag_register", "BIT")
    init_register += MOVE(classical_flag_register, True)

    loop_body = Program(X(0), H(0)).measure(0, classical_flag_register)

    # Put it all together in a loop program:
    loop_prog = init_register.while_do(classical_flag_register, loop_body)

    qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceWavefunctionSimulator)
    qam.execute(loop_prog)
    assert qam.ram[classical_flag_register.name][0] == 0
Пример #7
0
def test_while(qvm):
    # Name our classical registers:
    classical_flag_register = 2

    # Write out the loop initialization and body programs:
    init_register = Program(TRUE([classical_flag_register]))
    loop_body = Program(X(0), H(0)).measure(0, classical_flag_register)

    # Put it all together in a loop program:
    loop_prog = init_register.while_do(classical_flag_register, loop_body)

    _, cregs = qvm.wavefunction(loop_prog, [2])
    assert cregs[0] == False
Пример #8
0
    def encode_plus(self, prog: Program, block: CodeBlock, ancilla: CodeBlock, scratch: MemoryChunk):
        if len(scratch) < self.error_correct_scratch_size:
            raise ValueError("scratch buffer is too small")

        flag = scratch[0]
        outcome = scratch[1]
        scratch = scratch[2:]

        # See encode_zero for more thorough comments.
        loop_prog = Program()
        loop_prog += gates.MOVE(flag, 0)

        block.reset(loop_prog)
        loop_prog += self.noisy_encode_plus(block.qubits)

        self._error_detect_x(loop_prog, block, ancilla, outcome, scratch, include_operators=False)
        loop_prog += gates.IOR(flag, outcome)

        self._error_detect_z(loop_prog, block, ancilla, outcome, scratch, include_operators=True)
        loop_prog += gates.IOR(flag, outcome)

        prog += gates.MOVE(flag, 1)
        prog.while_do(flag, loop_prog)
Пример #9
0
def forward_prop(weights, initialization=None):
    LOGGER.info("Connecting to the QVM...")
    qvm = QVMConnection()
    LOGGER.info("... done")
    LOGGER.info(" ")

    LOGGER.info("Initialising quantum program...")
    p = Program()

    LOGGER.info("... defining custom gates")
    LOGGER.info("... controlled Ry")
    CRY = controlled_Ry(p)
    LOGGER.info("... controlled sY")
    CSY = controlled_sY(p)
    LOGGER.info("... done")
    LOGGER.info(" ")

    a = -1
    rotation = 0.5 * np.pi * (a + 1)
    gamma = 1 / NUM_INPUT

    W1 = weights[:NUM_INPUT * NUM_HIDDEN].reshape((NUM_INPUT, NUM_HIDDEN))
    b1 = weights[NUM_INPUT * NUM_HIDDEN]
    W2 = weights[NUM_INPUT * NUM_HIDDEN + 1:NUM_INPUT * NUM_HIDDEN + 1 +
                 NUM_HIDDEN * NUM_OUTPUT].reshape(NUM_HIDDEN, NUM_OUTPUT)
    b2 = weights[-1]

    # INITIALISE INPUT
    if initialization == None:
        EDI = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0,
                                                                   1]])
        dg = DefGate("EDI", EDI)
        EDI = dg.get_constructor()

        p.inst(dg)
        p.inst(H(0))
        p.inst(H(1))

        p.inst(EDI(0, 1))
    if initialization == "test":
        # p.inst(X(1))  # |01>
        p.inst(X(0))  # |10>
        # pass

    # INTIALISE LABELS
    p.inst(H(NUM_INPUT + NUM_HIDDEN + NUM_OUTPUT))

    classical_flag_register = ANCILLARY_BIT + 1
    # Write out the loop initialization and body programs:
    for n in range(NUM_HIDDEN):
        loop_body = Program()
        for w in range(NUM_INPUT):
            loop_body.inst(CRY(4. * gamma * W1[w, n])(w, ANCILLARY_BIT))
        loop_body.inst(RY(2. * gamma * b1)(ANCILLARY_BIT))

        loop_body.inst(CSY(ANCILLARY_BIT, NUM_INPUT + n))
        loop_body.inst(RZ(-0.5 * np.pi)(ANCILLARY_BIT))
        for w in range(NUM_INPUT):
            loop_body.inst(CRY(-4. * gamma * W1[w, n])(w, ANCILLARY_BIT))
        loop_body.inst(RY(-2. * gamma * b1)(ANCILLARY_BIT))

        loop_body.measure(ANCILLARY_BIT, classical_flag_register)

        then_branch = Program(RY(-0.5 * np.pi)(NUM_INPUT + n))
        then_branch.inst(X(ANCILLARY_BIT))
        else_branch = Program()

        # Add the conditional branching:
        loop_body.if_then(classical_flag_register, then_branch, else_branch)

        init_register = Program(TRUE([classical_flag_register]))
        loop_prog = init_register.while_do(classical_flag_register, loop_body)
        p.inst(loop_prog)

    # Write out the loop initialization and body programs:
    for n in range(NUM_OUTPUT):
        loop_body = Program()
        for w in range(NUM_HIDDEN):
            loop_body.inst(CRY(4. * gamma * W2[w, n])(w, ANCILLARY_BIT))
        loop_body.inst(RY(2. * gamma * b2)(ANCILLARY_BIT))

        loop_body.inst(CSY(ANCILLARY_BIT, NUM_INPUT + NUM_HIDDEN + n))
        loop_body.inst(RZ(-0.5 * np.pi)(ANCILLARY_BIT))
        for w in range(NUM_HIDDEN):
            loop_body.inst(CRY(-4. * gamma * W2[w, n])(w, ANCILLARY_BIT))
        loop_body.inst(RY(-2. * gamma * b1)(ANCILLARY_BIT))

        loop_body.measure(ANCILLARY_BIT, classical_flag_register)

        then_branch = Program(RY(-0.5 * np.pi)(NUM_INPUT + NUM_HIDDEN + n))
        then_branch.inst(X(ANCILLARY_BIT))
        else_branch = Program()

        # Add the conditional branching:
        loop_body.if_then(classical_flag_register, then_branch, else_branch)

        init_register = Program(TRUE([classical_flag_register]))
        loop_prog = init_register.while_do(classical_flag_register, loop_body)
        p.inst(loop_prog)

    p.measure(NUM_INPUT + NUM_HIDDEN, 0)

    LOGGER.info("... executing on the QVM")
    classical_regs = [0]
    output = qvm.run(p, classical_regs)
    LOGGER.info("... %s", output)
    LOGGER.info("")

    return output[0][0]