def augment_program_with_memory_values(quil_program, memory_map): """ This function allocates the classical memory values (gate angles) to a parametric quil program in order to use it on a Numpy-based simulator :param Program quil_program: parametric quil program which would require classical memory allocation :param Dict memory_map: dictionary with as keys the MemoryReference or String descrbing the classical memory, and with items() an array of values for that classical memory :return: quil program with gate angles from memory_map allocated to the (originally parametric) program :rtype: Program """ p = Program() # this function allocates the memory values for a parametric program correctly... if len(memory_map.keys()) == 0: return quil_program elif isinstance(list(memory_map.keys())[0], MemoryReference): for k, v in memory_map.items(): p += MOVE(k, v) elif isinstance(list(memory_map.keys())[0], str): for name, arr in memory_map.items(): for index, value in enumerate(arr): p += MOVE(MemoryReference(name, offset=index), value) else: raise TypeError( "Bad memory_map type; expected Dict[str, List[Union[int, float]]]." ) p += quil_program return percolate_declares(p)
def augment_program_with_memory_values(quil_program, memory_map): p = Program() # we stupidly allowed memory_map to be of type Dict[MemoryReference, Any], whereas qc.run # takes a memory initialization argument of type Dict[str, List[Union[int, float]]. until # we are in a position to remove this, we support both styles of input. if len(memory_map.keys()) == 0: return quil_program elif isinstance(list(memory_map.keys())[0], MemoryReference): warn( "Use of memory_map values of type Dict[MemoryReference, Any] have been " "deprecated. Please use Dict[str, List[Union[int, float]]], as with " "QuantumComputer.run .") for k, v in memory_map.items(): p += MOVE(k, v) elif isinstance(list(memory_map.keys())[0], str): for name, arr in memory_map.items(): for index, value in enumerate(arr): p += MOVE(MemoryReference(name, offset=index), value) else: raise TypeError( "Bad memory_map type; expected Dict[str, List[Union[int, float]]]." ) p += quil_program return percolate_declares(p)
def test_unary_classicals(): p = Program() p.inst( MOVE(MemoryReference("ro", 0), 1), MOVE(MemoryReference("ro", 1), 0), NOT(MemoryReference("ro", 2)), NEG(MemoryReference("ro", 3)), ) assert p.out() == "MOVE ro[0] 1\nMOVE ro[1] 0\nNOT ro[2]\nNEG ro[3]\n"
def test_classical(): parse_equals("MOVE ro[0] 1", MOVE(MemoryReference("ro", 0), 1)) parse_equals("MOVE ro[0] 0", MOVE(MemoryReference("ro", 0), 0)) parse_equals("NOT ro[0]", NOT(MemoryReference("ro", 0))) parse_equals("AND ro[0] 1", AND(MemoryReference("ro", 0), 1)) parse_equals("IOR ro[0] 1", IOR(MemoryReference("ro", 0), 1)) parse_equals("MOVE ro[0] 1", MOVE(MemoryReference("ro", 0), 1)) parse_equals("XOR ro[0] 1", XOR(MemoryReference("ro", 0), 1)) parse_equals("ADD mem[0] 1.2", ADD(MemoryReference("mem", 0), 1.2)) parse_equals("SUB mem[0] 1.2", SUB(MemoryReference("mem", 0), 1.2)) parse_equals("MUL mem[0] 1.2", MUL(MemoryReference("mem", 0), 1.2)) parse_equals("DIV mem[0] 1.2", DIV(MemoryReference("mem", 0), 1.2)) parse_equals("ADD mem[0] -1.2", ADD(MemoryReference("mem", 0), -1.2)) parse_equals("SUB mem[0] -1.2", SUB(MemoryReference("mem", 0), -1.2)) parse_equals("MUL mem[0] -1.2", MUL(MemoryReference("mem", 0), -1.2)) parse_equals("DIV mem[0] -1.2", DIV(MemoryReference("mem", 0), -1.2)) parse_equals( "EQ comp[1] ro[3] ro[2]", EQ(MemoryReference("comp", 1), MemoryReference("ro", 3), MemoryReference("ro", 2)), ) parse_equals( "LT comp[1] ro[3] ro[2]", LT(MemoryReference("comp", 1), MemoryReference("ro", 3), MemoryReference("ro", 2)), ) parse_equals( "LE comp[1] ro[3] ro[2]", LE(MemoryReference("comp", 1), MemoryReference("ro", 3), MemoryReference("ro", 2)), ) parse_equals( "GT comp[1] ro[3] ro[2]", GT(MemoryReference("comp", 1), MemoryReference("ro", 3), MemoryReference("ro", 2)), ) parse_equals( "GE comp[1] ro[3] ro[2]", GE(MemoryReference("comp", 1), MemoryReference("ro", 3), MemoryReference("ro", 2)), ) parse_equals("EQ comp[1] ro[3] 0", EQ(MemoryReference("comp", 1), MemoryReference("ro", 3), 0)) parse_equals("LT comp[1] ro[3] 1", LT(MemoryReference("comp", 1), MemoryReference("ro", 3), 1)) parse_equals("LE comp[1] ro[3] 2", LE(MemoryReference("comp", 1), MemoryReference("ro", 3), 2)) parse_equals("GT comp[1] ro[3] 3", GT(MemoryReference("comp", 1), MemoryReference("ro", 3), 3)) parse_equals("GE comp[1] ro[3] 4", GE(MemoryReference("comp", 1), MemoryReference("ro", 3), 4)) parse_equals( "EQ comp[1] ro[3] 0.0", EQ(MemoryReference("comp", 1), MemoryReference("ro", 3), 0.0) ) parse_equals( "LT comp[1] ro[3] 1.1", LT(MemoryReference("comp", 1), MemoryReference("ro", 3), 1.1) ) parse_equals( "LE comp[1] ro[3] 2.2", LE(MemoryReference("comp", 1), MemoryReference("ro", 3), 2.2) ) parse_equals( "GT comp[1] ro[3] 3.3", GT(MemoryReference("comp", 1), MemoryReference("ro", 3), 3.3) ) parse_equals( "GE comp[1] ro[3] 4.4", GE(MemoryReference("comp", 1), MemoryReference("ro", 3), 4.4) )
def test_memory_commands(): parse_equals( "DECLARE mem OCTET[32] SHARING mem2 OFFSET 16 REAL OFFSET 32 REAL", Declare("mem", "OCTET", 32, shared_region="mem2", offsets=[(16, "REAL"), (32, "REAL")]), ) parse_equals("STORE mem ro[2] ro[0]", STORE("mem", MemoryReference("ro", 2), MemoryReference("ro", 0))) parse_equals("STORE mem ro[2] 7", STORE("mem", MemoryReference("ro", 2), 7)) parse_equals("LOAD ro[8] mem mem[4]", LOAD(MemoryReference("ro", 8), "mem", MemoryReference("mem", 4))) parse_equals("CONVERT ro[1] ro[2]", CONVERT(MemoryReference("ro", 1), MemoryReference("ro", 2))) parse_equals("EXCHANGE ro[0] ro[1]", EXCHANGE(MemoryReference("ro", 0), MemoryReference("ro", 1))) parse_equals("MOVE mem[2] 4", MOVE(MemoryReference("mem", 2), 4)) parse_equals("MOVE mem[2] -4", MOVE(MemoryReference("mem", 2), -4)) parse_equals("MOVE mem[2] -4.1", MOVE(MemoryReference("mem", 2), -4.1))
def test_binary_classicals(): p = Program() p.inst(AND(0, 1), OR(Addr(0), Addr(1)), MOVE(0, 1), EXCHANGE(0, Addr(1))) assert p.out() == 'AND [0] [1]\n' \ 'OR [0] [1]\n' \ 'MOVE [0] [1]\n' \ 'EXCHANGE [0] [1]\n'
def test_binary_classicals(): p = Program() # OR is deprecated in favor of IOR with pytest.warns(UserWarning): p.inst(OR(MemoryReference("ro", 1), MemoryReference("ro", 0))) p.inst( AND(MemoryReference("ro", 0), MemoryReference("ro", 1)), MOVE(MemoryReference("ro", 0), MemoryReference("ro", 1)), CONVERT(MemoryReference("ro", 0), MemoryReference("ro", 1)), IOR(MemoryReference("ro", 0), MemoryReference("ro", 1)), XOR(MemoryReference("ro", 0), MemoryReference("ro", 1)), ADD(MemoryReference("ro", 0), MemoryReference("ro", 1)), SUB(MemoryReference("ro", 0), MemoryReference("ro", 1)), MUL(MemoryReference("ro", 0), MemoryReference("ro", 1)), DIV(MemoryReference("ro", 0), MemoryReference("ro", 1)), EXCHANGE(MemoryReference("ro", 0), MemoryReference("ro", 1)), ) assert (p.out() == "IOR ro[0] ro[1]\n" "AND ro[0] ro[1]\n" "MOVE ro[0] ro[1]\n" "CONVERT ro[0] ro[1]\n" "IOR ro[0] ro[1]\n" "XOR ro[0] ro[1]\n" "ADD ro[0] ro[1]\n" "SUB ro[0] ro[1]\n" "MUL ro[0] ro[1]\n" "DIV ro[0] ro[1]\n" "EXCHANGE ro[0] ro[1]\n")
def test_memory_reference_unpacking(): p = Program() p.inst( AND("ro", ("ro", 1)), MOVE("ro", ("ro", 1)), CONVERT("ro", ("ro", 1)), IOR("ro", ("ro", 1)), XOR("ro", ("ro", 1)), ADD("ro", ("ro", 1)), SUB("ro", ("ro", 1)), MUL("ro", ("ro", 1)), DIV("ro", ("ro", 1)), EXCHANGE("ro", ("ro", 1)), ) assert (p.out() == "AND ro[0] ro[1]\n" "MOVE ro[0] ro[1]\n" "CONVERT ro[0] ro[1]\n" "IOR ro[0] ro[1]\n" "XOR ro[0] ro[1]\n" "ADD ro[0] ro[1]\n" "SUB ro[0] ro[1]\n" "MUL ro[0] ro[1]\n" "DIV ro[0] ro[1]\n" "EXCHANGE ro[0] ro[1]\n")
def augment_program_with_memory_values(self, quil_program): p = Program() for k, v in self._variables_shim.items(): p += MOVE(MemoryReference(name=k.name, offset=k.index), v) p += quil_program return percolate_declares(p)
def augment_program_with_memory_values(quil_program, memory_map): p = Program() for k, v in memory_map.items(): p += MOVE(k, v) p += quil_program return percolate_declares(p)
def test_if_then_2(): # if FALSE creg, then measure 0 should give 1 prog = Program() creg = prog.declare("creg", "BIT") prog.inst(MOVE(creg, 0), X(0)) branch_a = Program(X(0)) branch_b = Program() prog.if_then(creg, branch_a, branch_b) prog += MEASURE(0, creg) qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) assert qam.ram["creg"][0] == 1
def test_unsupported_ops(): target = Label("target") base_prog = Program(Declare("reg1", "BIT"), Declare("reg2", "BIT"), H(0), JumpTarget(target), CNOT(0, 1)) bad_ops = [WAIT, Jump(target), MOVE(MemoryReference("reg1"), MemoryReference("reg2"))] assert to_latex(base_prog) for op in bad_ops: prog = base_prog + op with pytest.raises(ValueError): _ = to_latex(prog)
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_if_then(): # if TRUE creg, then measure 0 should give 0 prog = Program() creg = prog.declare('creg', 'BIT') prog.inst(MOVE(creg, 1), X(0)) branch_a = Program(X(0)) branch_b = Program() prog.if_then(creg, branch_a, branch_b) prog += MEASURE(0, creg) qam = PyQVM(n_qubits=1, quantum_simulator_type=ReferenceWavefunctionSimulator) qam.execute(prog) assert qam.ram['creg'][0] == 0
def test_binary_classicals(): p = Program() p.inst(AND(Addr(0), Addr(1)), OR(Addr(1), Addr(0)), MOVE(Addr(0), Addr(1)), CONVERT(Addr(0), Addr(1)), IOR(Addr(0), Addr(1)), XOR(Addr(0), Addr(1)), ADD(Addr(0), Addr(1)), SUB(Addr(0), Addr(1)), MUL(Addr(0), Addr(1)), DIV(Addr(0), Addr(1)), EXCHANGE(Addr(0), Addr(1))) assert p.out() == 'AND ro[0] ro[1]\n' \ 'IOR ro[0] ro[1]\n' \ 'MOVE ro[0] ro[1]\n' \ 'CONVERT ro[0] ro[1]\n' \ 'IOR ro[0] ro[1]\n' \ 'XOR ro[0] ro[1]\n' \ 'ADD ro[0] ro[1]\n' \ 'SUB ro[0] ro[1]\n'\ 'MUL ro[0] ro[1]\n' \ 'DIV ro[0] ro[1]\n' \ 'EXCHANGE ro[0] ro[1]\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_memory_reference_unpacking(): p = Program() p.inst(AND("ro", ("ro", 1)), MOVE("ro", ("ro", 1)), CONVERT("ro", ("ro", 1)), IOR("ro", ("ro", 1)), XOR("ro", ("ro", 1)), ADD("ro", ("ro", 1)), SUB("ro", ("ro", 1)), MUL("ro", ("ro", 1)), DIV("ro", ("ro", 1)), EXCHANGE("ro", ("ro", 1))) assert p.out() == 'AND ro[0] ro[1]\n' \ 'MOVE ro[0] ro[1]\n' \ 'CONVERT ro[0] ro[1]\n' \ 'IOR ro[0] ro[1]\n' \ 'XOR ro[0] ro[1]\n' \ 'ADD ro[0] ro[1]\n' \ 'SUB ro[0] ro[1]\n'\ 'MUL ro[0] ro[1]\n' \ 'DIV ro[0] ro[1]\n' \ 'EXCHANGE ro[0] ro[1]\n'
def test_binary_classicals(): p = Program() p.inst(AND(MemoryReference("ro", 0), MemoryReference("ro", 1)), OR(MemoryReference("ro", 1), MemoryReference("ro", 0)), MOVE(MemoryReference("ro", 0), MemoryReference("ro", 1)), CONVERT(MemoryReference("ro", 0), MemoryReference("ro", 1)), IOR(MemoryReference("ro", 0), MemoryReference("ro", 1)), XOR(MemoryReference("ro", 0), MemoryReference("ro", 1)), ADD(MemoryReference("ro", 0), MemoryReference("ro", 1)), SUB(MemoryReference("ro", 0), MemoryReference("ro", 1)), MUL(MemoryReference("ro", 0), MemoryReference("ro", 1)), DIV(MemoryReference("ro", 0), MemoryReference("ro", 1)), EXCHANGE(MemoryReference("ro", 0), MemoryReference("ro", 1))) assert p.out() == 'AND ro[0] ro[1]\n' \ 'IOR ro[0] ro[1]\n' \ 'MOVE ro[0] ro[1]\n' \ 'CONVERT ro[0] ro[1]\n' \ 'IOR ro[0] ro[1]\n' \ 'XOR ro[0] ro[1]\n' \ 'ADD ro[0] ro[1]\n' \ 'SUB ro[0] ro[1]\n'\ 'MUL ro[0] ro[1]\n' \ 'DIV ro[0] ro[1]\n' \ 'EXCHANGE ro[0] ro[1]\n'