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)
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()])
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'
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')
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", "" ])
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
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
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)
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]