def allocate_qureg(self, n, init=0.0): """ Allocate n qubits and return them as a quantum register, which is a list of qubit objects. Args: n (int): Number of qubits to allocate init (complex): Assign this value to every amplitude Returns: Qureg of length n, a list of n newly allocated qubits. """ cmd = Command(self, AllocateQuregGate(init), ()) if self.backend.is_available(cmd): qubits = Qureg() for i in range(n): new_id = self.main_engine.get_new_qubit_id() qb = Qubit(self, new_id) qubits.append(qb) self.main_engine.active_qubits.add(qb) cmd = Command(self, AllocateQuregGate(init), (qubits, )) self.send([cmd]) return qubits else: return super(MainEngine, self).allocate_qureg(n)
def F8(f=Qureg(), p=Qureg(), x=Qureg()): '''circuit for finding the first one in the bit representation of x. The flag f is toggled to 0 as soon as the first 1 has been found. The position of the first one is store in the p-register, consisting of 3 bits in this example. For more details see https://arxiv.org/pdf/1807.02023.pdf''' X | f #1 CNOT | (x[0], f) #2 C(X, 2) | (f, x[1], p[0]) #3 CNOT | (p[0], f) #4 C(X, 2) | (f, x[2], p[1]) #5 CNOT | (p[1], f) #6 C(X, 2) | (f, x[3], p[0]) #7 C(X, 2) | (f, x[3], p[1]) #8 C(X, 2) | (p[0], p[1], f) #9 C(X, 2) | (f, x[4], p[2]) #10 CNOT | (p[2], f) #11 C(X, 2) | (f, x[5], p[0]) #12 C(X, 2) | (f, x[5], p[2]) #13 C(X, 2) | (p[0], p[2], f) #14 C(X, 2) | (f, x[6], p[1]) #15 C(X, 2) | (f, x[6], p[2]) #16 C(X, 2) | (p[1], p[2], f) #17 C(X, 2) | (f, x[7], p[0]) #18 C(X, 2) | (f, x[7], p[1]) #19 C(X, 2) | (f, x[7], p[2]) #20 C(X, 3) | (p, f) #21
def test_command_comparison(main_engine): qubit = Qureg([Qubit(main_engine, 0)]) ctrl_qubit = Qureg([Qubit(main_engine, 1)]) cmd1 = _command.Command(main_engine, Rx(0.5), (qubit,)) cmd1.tags = ["TestTag"] cmd1.add_control_qubits(ctrl_qubit) # Test equality cmd2 = _command.Command(main_engine, Rx(0.5), (qubit,)) cmd2.tags = ["TestTag"] cmd2.add_control_qubits(ctrl_qubit) assert cmd2 == cmd1 # Test not equal because of tags cmd3 = _command.Command(main_engine, Rx(0.5), (qubit,)) cmd3.tags = ["TestTag", "AdditionalTag"] cmd3.add_control_qubits(ctrl_qubit) assert not cmd3 == cmd1 # Test not equal because of control qubit cmd4 = _command.Command(main_engine, Rx(0.5), (qubit,)) cmd4.tags = ["TestTag"] assert not cmd4 == cmd1 # Test not equal because of qubit qubit2 = Qureg([Qubit(main_engine, 2)]) cmd5 = _command.Command(main_engine, Rx(0.5), (qubit2,)) cmd5.tags = ["TestTag"] cmd5.add_control_qubits(ctrl_qubit) assert cmd5 != cmd1 # Test not equal because of engine cmd6 = _command.Command("FakeEngine", Rx(0.5), (qubit,)) cmd6.tags = ["TestTag"] cmd6.add_control_qubits(ctrl_qubit) assert cmd6 != cmd1
def test_command_init(main_engine): qureg0 = Qureg([Qubit(main_engine, 0)]) qureg1 = Qureg([Qubit(main_engine, 1)]) qureg2 = Qureg([Qubit(main_engine, 2)]) # qureg3 = Qureg([Qubit(main_engine, 3)]) # qureg4 = Qureg([Qubit(main_engine, 4)]) gate = BasicGate() cmd = _command.Command(main_engine, gate, (qureg0, qureg1, qureg2)) assert cmd.gate == gate assert cmd.tags == [] expected_tuple = (qureg0, qureg1, qureg2) for cmd_qureg, expected_qureg in zip(cmd.qubits, expected_tuple): assert cmd_qureg[0].id == expected_qureg[0].id # Testing that Qubits are now WeakQubitRef objects assert type(cmd_qureg[0]) == WeakQubitRef assert cmd._engine == main_engine # Test that quregs are ordered if gate has interchangeable qubits: symmetric_gate = BasicGate() symmetric_gate.interchangeable_qubit_indices = [[0, 1]] symmetric_cmd = _command.Command(main_engine, symmetric_gate, (qureg2, qureg1, qureg0)) assert cmd.gate == gate assert cmd.tags == [] expected_ordered_tuple = (qureg1, qureg2, qureg0) for cmd_qureg, expected_qureg in zip(symmetric_cmd.qubits, expected_ordered_tuple): assert cmd_qureg[0].id == expected_qureg[0].id assert symmetric_cmd._engine == main_engine
def test_command_all_qubits(main_engine): qubit0 = Qureg([Qubit(main_engine, 0)]) qubit1 = Qureg([Qubit(main_engine, 1)]) cmd = _command.Command(main_engine, Rx(0.5), (qubit0,)) cmd.add_control_qubits(qubit1) all_qubits = cmd.all_qubits assert all_qubits[0][0].id == 1 assert all_qubits[1][0].id == 0
def test_commmand_add_control_qubits(main_engine): qubit0 = Qureg([Qubit(main_engine, 0)]) qubit1 = Qureg([Qubit(main_engine, 1)]) qubit2 = Qureg([Qubit(main_engine, 2)]) cmd = _command.Command(main_engine, Rx(0.5), (qubit0, )) cmd.add_control_qubits(qubit2 + qubit1) assert cmd.control_qubits[0].id == 1 assert cmd.control_qubits[1].id == 2
def test_command_str(): qubit = Qureg([Qubit(main_engine, 0)]) ctrl_qubit = Qureg([Qubit(main_engine, 1)]) cmd = _command.Command(main_engine, Rx(0.5), (qubit, )) cmd.tags = ["TestTag"] cmd.add_control_qubits(ctrl_qubit) assert str(cmd) == "CRx(0.5) | ( Qureg[1], Qureg[0] )" cmd2 = _command.Command(main_engine, Rx(0.5), (qubit, )) assert str(cmd2) == "Rx(0.5) | Qureg[0]"
def test_commmand_add_control_qubits_two(main_engine, state): qubit0 = Qureg([Qubit(main_engine, 0)]) qubit1 = Qureg([Qubit(main_engine, 1)]) qubit2 = Qureg([Qubit(main_engine, 2)]) qubit3 = Qureg([Qubit(main_engine, 3)]) cmd = _command.Command(main_engine, Rx(0.5), (qubit0,), qubit1) cmd.add_control_qubits(qubit2 + qubit3, state) assert cmd.control_qubits[0].id == 1 assert cmd.control_state == '1' + canonical_ctrl_state(state, 2)
def RSHIFT(s=Qureg(), x=Qureg()): '''shift x to the right by s bits https://arxiv.org/pdf/1807.02023.pdf''' j = len(s) for k in range(j): i = 0 while i + 2**k <= 2**j - 1: C(Swap, 1) | (s[k], x[-1 * i], x[-1 * (i + (2**k))]) i += 1
def command_str(cmd): gate_str = '{}'.format(cmd.gate).strip() or cmd.gate.__class__.__name__ if len(cmd.control_qubits) > 0: return "Command({} & {} | {})".format( gate_str, Qureg(cmd.control_qubits), tuple(Qureg(e) for e in cmd.qubits)) return "Command({} | {})".format(gate_str, tuple(Qureg(e) for e in cmd.qubits))
def test_command_engine(main_engine): qubit0 = Qureg([Qubit("fake_engine", 0)]) qubit1 = Qureg([Qubit("fake_engine", 1)]) cmd = _command.Command("fake_engine", Rx(0.5), (qubit0, )) cmd.add_control_qubits(qubit1) assert cmd.engine == "fake_engine" cmd.engine = main_engine assert id(cmd.engine) == id(main_engine) assert id(cmd.control_qubits[0].engine) == id(main_engine) assert id(cmd.qubits[0][0].engine) == id(main_engine)
def test_commmand_add_control_qubits_one(main_engine, state): qubit0 = Qureg([Qubit(main_engine, 0)]) qubit1 = Qureg([Qubit(main_engine, 1)]) cmd = _command.Command(main_engine, Rx(0.5), (qubit0,)) cmd.add_control_qubits(qubit1, state=state) assert cmd.control_qubits[0].id == 1 assert cmd.control_state == canonical_ctrl_state(state, 1) with pytest.raises(ValueError): cmd.add_control_qubits(qubit0[0])
def fixed_MUL(b=Qureg(), a=Qureg(), z=Qureg(), eng=MainEngine()): '''see https://arxiv.org/pdf/0910.2530.pdf''' ''' unsigned multiplication is done shifted controlled addition.''' ##input\\ qubit registers a, b, z --- z twice the length of a ## suppose len(a) = n. ##output\\ qubit registers b, a, a*b #### [ b | a | z > --> [ b | a | a*b > n = len(b) for _ in range(n): with Control(eng, b[_]): ADD(a, z[_:n + _], z[n + _]) return 0
def test_command_str(main_engine): qubit = Qureg([Qubit(main_engine, 0)]) ctrl_qubit = Qureg([Qubit(main_engine, 1)]) cmd = _command.Command(main_engine, Rx(0.5 * math.pi), (qubit,)) cmd.tags = ["TestTag"] cmd.add_control_qubits(ctrl_qubit) cmd2 = _command.Command(main_engine, Rx(0.5 * math.pi), (qubit,)) if sys.version_info.major == 3: assert cmd.to_string(symbols=False) == "CRx(1.570796326795) | ( Qureg[1], Qureg[0] )" assert str(cmd2) == "Rx(1.570796326795) | Qureg[0]" else: assert cmd.to_string(symbols=False) == "CRx(1.5707963268) | ( Qureg[1], Qureg[0] )" assert str(cmd2) == "Rx(1.5707963268) | Qureg[0]"
def test_command_engine(main_engine): qubit0 = Qureg([Qubit("fake_engine", 0)]) qubit1 = Qureg([Qubit("fake_engine", 1)]) cmd = _command.Command("fake_engine", Rx(0.5), (qubit0,)) cmd.add_control_qubits(qubit1) assert cmd.engine == "fake_engine" cmd.engine = main_engine assert id(cmd.engine) == id(main_engine) assert id(cmd.control_qubits[0].engine) == id(main_engine) assert id(cmd.qubits[0][0].engine) == id(main_engine) # Avoid raising exception upon Qubit destructions qubit0[0].id = -1 qubit1[0].id = -1
def _2scomplement(x=Qureg(), z=Qureg()): ''' computes x in 2's complement. Does not include the original sign bit. Use control gate with this function outputs x, s (nbit 2s complement of x), z (overflow bit) x original: [0, 0, 0, 1, 0, 1, 0, 0] x: [0, 0, 0, 1, 1, 0, 1, 1]''' "Enter n+1 0s for carry over and storing n bit register for 1 value" X | z[0] All(X) | x ADD(z[:-1], x, z[-1]) #should be able to get rid of zero bit completely #wise to continue to use z[-1] for this part. X | z[0]
def _decompose_parity_measurement(cmd): ancilla = cmd.engine.allocate_qubit() for pos, action in cmd.gate._bases: qureg = Qureg([cmd.qubits[0][pos]]) if action == "X": H | cmd.qubits[0][pos] with Control(cmd.engine, qureg): X | ancilla H | cmd.qubits[0][pos] elif action == "Y": H | cmd.qubits[0][pos] S | cmd.qubits[0][pos] with Control(cmd.engine, qureg): X | ancilla get_inverse(S) | cmd.qubits[0][pos] H | cmd.qubits[0][pos] elif action == "Z": with Control(cmd.engine, qureg): X | ancilla # if there is a minus sign if (cmd.gate._is_inverted): X | ancilla # at last measure the parity: Measure | ancilla
def test_basic_gate_or(): saving_backend = DummyEngine(save_commands=True) main_engine = MainEngine(backend=saving_backend, engine_list=[DummyEngine()]) qubit0 = Qubit(main_engine, 0) qubit1 = Qubit(main_engine, 1) qubit2 = Qubit(main_engine, 2) qubit3 = Qubit(main_engine, 3) qureg = Qureg([qubit2, qubit3]) basic_gate = _basics.BasicGate() command1 = basic_gate.generate_command(qubit0) basic_gate | qubit0 command2 = basic_gate.generate_command([qubit0, qubit1]) basic_gate | [qubit0, qubit1] command3 = basic_gate.generate_command(qureg) basic_gate | qureg command4 = basic_gate.generate_command((qubit0,)) basic_gate | (qubit0,) command5 = basic_gate.generate_command((qureg, qubit0)) basic_gate | (qureg, qubit0) received_commands = [] # Remove Deallocate gates for cmd in saving_backend.received_commands: if not isinstance(cmd.gate, _basics.FastForwardingGate): received_commands.append(cmd) assert received_commands == ([command1, command2, command3, command4, command5])
def deallocate_qubit(self, qubit): """ Deallocate a qubit (and sends the deallocation command down the pipeline). If the qubit was allocated as a dirty qubit, add DirtyQubitTag() to Deallocate command. Args: qubit (BasicQubit): Qubit to deallocate. Raises: ValueError: Qubit already deallocated. Caller likely has a bug. """ if qubit.id == -1: raise ValueError("Already deallocated.") is_dirty = qubit.id in self.dirty_qubits weak_copy = WeakQubitRef(qubit.engine, qubit.id) if not isinstance(qubit, WeakQubitRef): if qubit in self.active_qubits: self.active_qubits.remove(qubit) qubit.id = -1 from projectq.meta import DirtyQubitTag self.send([ Command(self, Deallocate, (Qureg([weak_copy]), ), tags=[DirtyQubitTag()] if is_dirty else []) ])
def allocate_qubit(self, dirty=False): """ Return a new qubit as a list containing 1 qubit object (quantum register of size 1). Allocates a new qubit by getting a (new) qubit id from the MainEngine, creating the qubit object, and then sending an AllocateQubit command down the pipeline. If dirty=True, the fresh qubit can be replaced by a pre-allocated one (in an unknown, dirty, initial state). Dirty qubits must be returned to their initial states before they are deallocated / freed. All allocated qubits are added to the MainEngine's set of active qubits as weak references. This allows proper clean-up at the end of the Python program (using atexit), deallocating all qubits which are still alive. Qubit ids of dirty qubits are registered in MainEngine's dirty_qubits set. Args: dirty (bool): If True, indicates that the allocated qubit may be dirty (i.e., in an arbitrary initial state). Returns: Qureg of length 1, where the first entry is the allocated qubit. """ new_id = self.main_engine.get_new_qubit_id() qb = Qureg([Qubit(self, new_id)]) cmd = Command(self, Allocate, (qb, )) if dirty: from projectq.meta import ( # pylint: disable=import-outside-toplevel DirtyQubitTag, ) if self.is_meta_tag_supported(DirtyQubitTag): cmd.tags += [DirtyQubitTag()] self.main_engine.dirty_qubits.add(qb[0].id) self.main_engine.active_qubits.add(qb[0]) self.send([cmd]) return qb
def Fn(f=Qureg(), p=Qureg(), x=Qureg()): n = len(x) X | f #1 CNOT | (x[0], f) #2 C(X, 2) | (f, x[1], p[0]) #3 CNOT | (p[0], f) #4 for i in range(1, len(p)): if n < 2**(i + 1): max = n else: max = 2**(i + 1) for j in range(2**i, max): a = get_binrep(j, 2**(i)) ones_place = [] for k in range(len(a)): if a[k] == 1: C(X, 2) | (f, x[j], p[k]) ones_place = ones_place + [k] C(X, len(ones_place)) | ([p[k] for k in ones_place], f)
def to_string(self, symbols=False): """Get string representation of this Command object.""" qubits = self.qubits ctrlqubits = self.control_qubits if len(ctrlqubits) > 0: qubits = (self.control_qubits, ) + qubits qstring = "" if len(qubits) == 1: qstring = str(Qureg(qubits[0])) else: qstring = "( " for qreg in qubits: qstring += str(Qureg(qreg)) qstring += ", " qstring = qstring[:-2] + " )" cstring = "C" * len(ctrlqubits) return cstring + self.gate.to_string(symbols) + " | " + qstring
def _decompose_cnot_rotation(cmd): """ Decompose CNOT gates. """ qureg = Qureg(cmd.control_qubits + cmd.qubits[0]) H = QubitOperator("Z0 X1") T = TimeEvolution(-cmath.pi / 4, H) T | qureg Rz(cmath.pi) | qureg[0] Rx(cmath.pi) | qureg[1]
def allocate_qureg(self, n_qubits): """ Allocate n qubits and return them as a quantum register, which is a list of qubit objects. Args: n (int): Number of qubits to allocate Returns: Qureg of length n, a list of n newly allocated qubits. """ return Qureg([self.allocate_qubit()[0] for _ in range(n_qubits)])
def ADD(x=Qureg(), y=Qureg(), z=Qureg()): #### [ x | y | 0 > --> [ x | x+y > n = len(x) for i in range(1, n): CNOT | (x[i], y[i]) #1 for i in range(n - 1, 0, -1): if i + 1 == n: CNOT | (x[i], z) #2 else: CNOT | (x[i], x[i + 1]) for i in range(n): if i == n - 1: Toffoli | (y[i], x[i], z) #3 else: Toffoli | (y[i], x[i], x[i + 1]) for i in range(n - 1, 0, -1): #4 CNOT | (x[i], y[i]) Toffoli | (y[i - 1], x[i - 1], x[i]) for i in range(1, n - 1): CNOT | (x[i], x[i + 1]) #5 for i in range(n): CNOT | (x[i], y[i]) #6 return 0
def __str__(self): """ Get string representation of this Command object. """ qubits = self.qubits ctrlqubits = self.control_qubits if len(ctrlqubits) > 0: qubits = (self.control_qubits,) + qubits qstring = "" if len(qubits) == 1: qstring = str(Qureg(qubits[0])) else: qstring = "( " for qreg in qubits: qstring += str(Qureg(qreg)) qstring += ", " qstring = qstring[:-2] + " )" #qstring = convert_qubits_to_string(qubits) cstring = "C" * len(ctrlqubits) return cstring + str(self.gate) + " | " + qstring
def test_multirotation(): commands = GetCommand() eng = projectq.MainEngine(engine_list=[commands]) qubit1 = eng.allocate_qubit() qubit2 = eng.allocate_qubit() gates.CNOT | (qubit1, qubit2) gates.TimeEvolution(-1, gates.QubitOperator("X0 Z1")) | Qureg(qubit1 + qubit2) cmd2_info = [[(0,"X"), (1,"Z")], "pi4", 1] permute_cnot(commands.commands[0], commands.commands[1], cmd2_info) print(cmd2_info) assert(len(cmd2_info[0])==2) assert(cmd2_info[0][0][1] == "Y" and cmd2_info[0][1][1] == "Y")
def test_command_deepcopy(main_engine): qureg0 = Qureg([Qubit(main_engine, 0)]) qureg1 = Qureg([Qubit(main_engine, 1)]) gate = BasicGate() cmd = _command.Command(main_engine, gate, (qureg0,)) cmd.add_control_qubits(qureg1) cmd.tags.append("MyTestTag") copied_cmd = deepcopy(cmd) # Test that deepcopy gives same cmd assert copied_cmd.gate == gate assert copied_cmd.tags == ["MyTestTag"] assert len(copied_cmd.qubits) == 1 assert copied_cmd.qubits[0][0].id == qureg0[0].id assert len(copied_cmd.control_qubits) == 1 assert copied_cmd.control_qubits[0].id == qureg1[0].id # Engine should not be deepcopied but a reference: assert id(copied_cmd.engine) == id(main_engine) # Test that deepcopy is actually a deepcopy cmd.tags = ["ChangedTag"] assert copied_cmd.tags == ["MyTestTag"] cmd.control_qubits[0].id == 10 assert copied_cmd.control_qubits[0].id == qureg1[0].id cmd.gate = "ChangedGate" assert copied_cmd.gate == gate
def test_basic_gate_make_tuple_of_qureg(main_engine): qubit0 = Qubit(main_engine, 0) qubit1 = Qubit(main_engine, 1) qubit2 = Qubit(main_engine, 2) qubit3 = Qubit(main_engine, 3) qureg = Qureg([qubit2, qubit3]) case1 = _basics.BasicGate.make_tuple_of_qureg(qubit0) assert case1 == ([qubit0],) case2 = _basics.BasicGate.make_tuple_of_qureg([qubit0, qubit1]) assert case2 == ([qubit0, qubit1],) case3 = _basics.BasicGate.make_tuple_of_qureg(qureg) assert case3 == (qureg,) case4 = _basics.BasicGate.make_tuple_of_qureg((qubit0,)) assert case4 == ([qubit0],) case5 = _basics.BasicGate.make_tuple_of_qureg((qureg, qubit0)) assert case5 == (qureg, [qubit0])
def test_basic_gate_generate_command(main_engine): qubit0 = Qubit(main_engine, 0) qubit1 = Qubit(main_engine, 1) qubit2 = Qubit(main_engine, 2) qubit3 = Qubit(main_engine, 3) qureg = Qureg([qubit2, qubit3]) basic_gate = _basics.BasicGate() command1 = basic_gate.generate_command(qubit0) assert command1 == Command(main_engine, basic_gate, ([qubit0], )) command2 = basic_gate.generate_command([qubit0, qubit1]) assert command2 == Command(main_engine, basic_gate, ([qubit0, qubit1], )) command3 = basic_gate.generate_command(qureg) assert command3 == Command(main_engine, basic_gate, (qureg, )) command4 = basic_gate.generate_command((qubit0, )) assert command4 == Command(main_engine, basic_gate, ([qubit0], )) command5 = basic_gate.generate_command((qureg, qubit0)) assert command5 == Command(main_engine, basic_gate, (qureg, [qubit0]))