def cswap(self, ctl, tgt1, tgt2): """Apply Fredkin to circuit.""" if isinstance(ctl, QuantumRegister): ctl = [(ctl, i) for i in range(len(ctl))] if isinstance(tgt1, QuantumRegister): tgt1 = [(tgt1, i) for i in range(len(tgt1))] if isinstance(tgt2, QuantumRegister): tgt2 = [(tgt2, i) for i in range(len(tgt2))] if ctl and tgt1 and tgt2: if isinstance(ctl, list) and \ isinstance(tgt1, list) and \ isinstance(tgt2, list): if len(ctl) == len(tgt1) and len(ctl) == len(tgt2): instructions = InstructionSet() for ictl, itgt1, itgt2 in zip(ctl, tgt1, tgt2): instructions.add(self.cswap(ictl, itgt1, itgt2)) return instructions else: raise QiskitError('unequal register sizes') self._check_qubit(ctl) self._check_qubit(tgt1) self._check_qubit(tgt2) self._check_dups([ctl, tgt1, tgt2]) return self._attach(FredkinGate(ctl, tgt1, tgt2, self))
def wait(self, t, q): """Apply wait for time t to q.""" if isinstance(q, QuantumRegister): gs = InstructionSet() for j in range(q.size): gs.add(self.wait(t, (q, j))) return gs self._check_qubit(q) return self._attach(WaitGate(t, q, self))
def u0(self, m, q): """Apply u0 with length m to q.""" if isinstance(q, QuantumRegister): instructions = InstructionSet() for j in range(q.size): instructions.add(self.u0(m, (q, j))) return instructions self._check_qubit(q) return self._attach(U0Gate(m, q, self))
def u3(self, theta, phi, lam, q): """Apply u3 to q.""" if isinstance(q, QuantumRegister): instructions = InstructionSet() for j in range(q.size): instructions.add(self.u3(theta, phi, lam, (q, j))) return instructions self._check_qubit(q) return self._attach(U3Gate(theta, phi, lam, q, self))
def u_base(self, theta, phi, lam, q): """Apply U to q.""" if isinstance(q, QuantumRegister): gs = InstructionSet() for j in range(q.size): gs.add(self.u_base(theta, phi, lam, (q, j))) return gs self._check_qubit(q) return self._attach(UBase(theta, phi, lam, q, self))
def ry(self, theta, q): """Apply Ry to q.""" if isinstance(q, QuantumRegister): instructions = InstructionSet() for j in range(q.size): instructions.add(self.ry(theta, (q, j))) return instructions self._check_qubit(q) return self._attach(RYGate(theta, q, self))
def u1(self, theta, q): """Apply u1 with angle theta to q.""" if isinstance(q, QuantumRegister): instructions = InstructionSet() for j in range(q.size): instructions.add(self.u1(theta, (q, j))) return instructions self._check_qubit(q) return self._attach(U1Gate(theta, q, self))
def z(self, q): """Apply Z to q.""" if isinstance(q, QuantumRegister): instructions = InstructionSet() for j in range(q.size): instructions.add(self.z((q, j))) return instructions self._check_qubit(q) return self._attach(ZGate(q, self))
def swap(self, ctl, tgt): """Apply SWAP from ctl to tgt.""" if isinstance(ctl, QuantumRegister) and \ isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt): instructions = InstructionSet() for j in range(ctl.size): instructions.add(self.swap((ctl, j), (tgt, j))) return instructions self._check_qubit(ctl) self._check_qubit(tgt) self._check_dups([ctl, tgt]) return self._attach(SwapGate(ctl, tgt, self))
def rzz(self, theta, ctl, tgt): """Apply RZZ to circuit.""" if isinstance(ctl, QuantumRegister) and \ isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt): instructions = InstructionSet() for i in range(ctl.size): instructions.add(self.rzz(theta, (ctl, i), (tgt, i))) return instructions self._check_qubit(ctl) self._check_qubit(tgt) self._check_dups([ctl, tgt]) return self._attach(RZZGate(theta, ctl, tgt, self))
def majority(self, c, b, a): """Apply a majority function on the given qubits""" if isinstance(c, QuantumRegister) and \ isinstance(a, QuantumRegister) and \ isinstance(b, QuantumRegister) and \ len(c) == len(b) and len(b) == len(a): instructions = InstructionSet() for i in range(c.size): instructions.add(self.majority((c, i), (b, i), (a, i))) return instructions self._check_qubit(c) self._check_qubit(b) self._check_qubit(a) self._check_dups([c, b, a]) return self._attach(MajorityGate(c, b, a, circ=self))
def cswap(self, ctl, tgt1, tgt2): """Apply Fredkin to circuit.""" if isinstance(ctl, QuantumRegister) and \ isinstance(tgt1, QuantumRegister) and \ isinstance(tgt2, QuantumRegister) and \ len(ctl) == len(tgt1) and len(ctl) == len(tgt2): instructions = InstructionSet() for i in range(ctl.size): instructions.add(self.cswap((ctl, i), (tgt1, i), (tgt2, i))) return instructions self._check_qubit(ctl) self._check_qubit(tgt1) self._check_qubit(tgt2) self._check_dups([ctl, tgt1, tgt2]) return self._attach(FredkinGate(ctl, tgt1, tgt2, self))
def ntoffoli(self, tgt, *ctls): """Apply n-controlled Toffoli to tgt with controls.""" if all(isinstance(ctl, QuantumRegister) for ctl in ctls) and \ isinstance(tgt, QuantumRegister) and \ all(len(ctl) == len(tgt) for ctl in ctls): instructions = InstructionSet() for i in range(ctls[0].size): instructions.add( self.ntoffoli((tgt, i), *zip(ctls, itertools.repeat(i)))) return instructions for ctl in ctls: self._check_qubit(ctl) self._check_qubit(tgt) self._check_dups(list(ctls) + [tgt]) return self._attach(NcrxGate(pi, tgt, *ctls, circ=self))
def ccx(self, ctl1, ctl2, tgt): """Apply Toffoli to from ctl1 and ctl2 to tgt.""" if isinstance(ctl1, QuantumRegister) and \ isinstance(ctl2, QuantumRegister) and \ isinstance(tgt, QuantumRegister) and \ len(ctl1) == len(tgt) and len(ctl2) == len(tgt): instructions = InstructionSet() for i in range(ctl1.size): instructions.add(self.ccx((ctl1, i), (ctl2, i), (tgt, i))) return instructions self._check_qubit(ctl1) self._check_qubit(ctl2) self._check_qubit(tgt) self._check_dups([ctl1, ctl2, tgt]) return self._attach(ToffoliGate(ctl1, ctl2, tgt, self))
def ccx(self, ctl1, ctl2, tgt): """Apply Toffoli to from ctl1 and ctl2 to tgt.""" # expand registers to lists of qubits if isinstance(ctl1, QuantumRegister): ctl1 = [(ctl1, i) for i in range(len(ctl1))] if isinstance(ctl2, QuantumRegister): ctl2 = [(ctl2, i) for i in range(len(ctl2))] if isinstance(tgt, QuantumRegister): tgt = [(tgt, i) for i in range(len(tgt))] # expand single qubit target if controls are lists of qubits if isinstance(ctl1, list) and len(ctl1) == len(ctl2): if isinstance(tgt, tuple): tgt = [tgt] if len(tgt) == 1: tgt = tgt * len(ctl1) elif len(tgt) != len(ctl1): raise QiskitError( 'target register size should match controls or be one') if ctl1 and ctl2 and tgt: if isinstance(ctl1, list) and \ isinstance(ctl2, list) and \ isinstance(tgt, list): if len(ctl1) == len(tgt) and len(ctl2) == len(tgt): instructions = InstructionSet() for ictl1, ictl2, itgt in zip(ctl1, ctl2, tgt): instructions.add(self.ccx(ictl1, ictl2, itgt)) return instructions else: raise QiskitError('unequal register sizes') else: raise QiskitError('empty control or target argument') self._check_qubit(ctl1) self._check_qubit(ctl2) self._check_qubit(tgt) self._check_dups([ctl1, ctl2, tgt]) return self._attach(ToffoliGate(ctl1, ctl2, tgt, self))
def test_instructionset_c_if_with_no_requester(self): """Test that using a raw :obj:`.InstructionSet` with no classical-resource resoluer accepts arbitrary :obj:`.Clbit` and `:obj:`.ClassicalRegister` instances, but rejects integers.""" with self.subTest("accepts arbitrary register"): instruction = HGate() instructions = InstructionSet() instructions.add(instruction, [Qubit()], []) register = ClassicalRegister(2) instructions.c_if(register, 0) self.assertIs(instruction.condition[0], register) with self.subTest("accepts arbitrary bit"): instruction = HGate() instructions = InstructionSet() instructions.add(instruction, [Qubit()], []) bit = Clbit() instructions.c_if(bit, 0) self.assertIs(instruction.condition[0], bit) with self.subTest("rejects index"): instruction = HGate() instructions = InstructionSet() instructions.add(instruction, [Qubit()], []) with self.assertRaisesRegex( CircuitError, r"Cannot pass an index as a condition .*"): instructions.c_if(0, 0)
def cz(self, ctl, tgt): """Apply CZ to circuit.""" if isinstance(ctl, QuantumRegister) and \ isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt): instructions = InstructionSet() for i in range(ctl.size): instructions.add(self.cz((ctl, i), (tgt, i))) return instructions if isinstance(ctl, QuantumRegister): instructions = InstructionSet() for j in range(ctl.size): instructions.add(self.cz((ctl, j), tgt)) return instructions if isinstance(tgt, QuantumRegister): instructions = InstructionSet() for j in range(tgt.size): instructions.add(self.cz(ctl, (tgt, j))) return instructions self._check_qubit(ctl) self._check_qubit(tgt) self._check_dups([ctl, tgt]) return self._attach(CzGate(ctl, tgt, self))
def crz(self, theta, ctl, tgt): """Apply crz from ctl to tgt with angle theta.""" if isinstance(ctl, QuantumRegister) and \ isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt): instructions = InstructionSet() for i in range(ctl.size): instructions.add(self.crz(theta, (ctl, i), (tgt, i))) return instructions if isinstance(ctl, QuantumRegister): instructions = InstructionSet() for j in range(ctl.size): instructions.add(self.crz(theta, (ctl, j), tgt)) return instructions if isinstance(tgt, QuantumRegister): instructions = InstructionSet() for j in range(tgt.size): instructions.add(self.crz(theta, ctl, (tgt, j))) return instructions self._check_qubit(ctl) self._check_qubit(tgt) self._check_dups([ctl, tgt]) return self._attach(CrzGate(theta, ctl, tgt, self))
def cx_base(self, ctl, tgt): """Apply CX ctl, tgt.""" if isinstance(ctl, QuantumRegister) and \ isinstance(tgt, QuantumRegister) and len(ctl) == len(tgt): # apply CX to qubits between two registers instructions = InstructionSet() for i in range(ctl.size): instructions.add(self.cx_base((ctl, i), (tgt, i))) return instructions if isinstance(ctl, QuantumRegister): instructions = InstructionSet() for j in range(ctl.size): instructions.add(self.cx_base((ctl, j), tgt)) return instructions if isinstance(tgt, QuantumRegister): instructions = InstructionSet() for j in range(tgt.size): instructions.add(self.cx_base(ctl, (tgt, j))) return instructions self._check_qubit(ctl) self._check_qubit(tgt) self._check_dups([ctl, tgt]) return self._attach(CXBase(ctl, tgt, self))
def test_instructionset_c_if_deprecated_resolution(self): r"""Test that the deprecated path of passing an iterable of :obj:`.ClassicalRegister`\ s to :obj:`.InstructionSet` works, issues a deprecation warning, and resolves indices in the simple cases it was meant to handle.""" # The deprecated path can only cope with non-overlapping classical registers, with no loose # clbits in the mix. registers = [ ClassicalRegister(2), ClassicalRegister(3), ClassicalRegister(1) ] bits = [bit for register in registers for bit in register] deprecated_regex = r"The 'circuit_cregs' argument to 'InstructionSet' is deprecated .*" def dummy_requester(specifier): """A dummy requester that technically fulfills the spec.""" raise CircuitError with self.subTest("cannot pass both registers and requester"): with self.assertRaisesRegex( CircuitError, r"Cannot pass both 'circuit_cregs' and 'resource_requester'\." ): InstructionSet(registers, resource_requester=dummy_requester) with self.subTest("classical register"): instruction = HGate() with self.assertWarnsRegex(DeprecationWarning, deprecated_regex): instructions = InstructionSet(registers) instructions.add(instruction, [Qubit()], []) instructions.c_if(registers[0], 0) self.assertIs(instruction.condition[0], registers[0]) with self.subTest("classical bit"): instruction = HGate() with self.assertWarnsRegex(DeprecationWarning, deprecated_regex): instructions = InstructionSet(registers) instructions.add(instruction, [Qubit()], []) instructions.c_if(registers[0][1], 0) self.assertIs(instruction.condition[0], registers[0][1]) for i, bit in enumerate(bits): with self.subTest("bit index", index=i): instruction = HGate() with self.assertWarnsRegex(DeprecationWarning, deprecated_regex): instructions = InstructionSet(registers) instructions.add(instruction, [Qubit()], []) instructions.c_if(i, 0) self.assertIs(instruction.condition[0], bit) with self.subTest("raises on bad register"): instruction = HGate() with self.assertWarnsRegex(DeprecationWarning, deprecated_regex): instructions = InstructionSet(registers) instructions.add(instruction, [Qubit()], []) with self.assertRaisesRegex( CircuitError, r"Condition register .* is not one of the registers known here: .*" ): instructions.c_if(ClassicalRegister(2), 0) with self.subTest("raises on bad bit"): instruction = HGate() with self.assertWarnsRegex(DeprecationWarning, deprecated_regex): instructions = InstructionSet(registers) instructions.add(instruction, [Qubit()], []) with self.assertRaisesRegex( CircuitError, "Condition bit .* is not in the registers known here: .*"): instructions.c_if(Clbit(), 0) with self.subTest("raises on bad index"): instruction = HGate() with self.assertWarnsRegex(DeprecationWarning, deprecated_regex): instructions = InstructionSet(registers) instructions.add(instruction, [Qubit()], []) with self.assertRaisesRegex(CircuitError, r"Bit index .* is out-of-range\."): instructions.c_if(len(bits), 0) with self.subTest("raises on bad type"): instruction = HGate() with self.assertWarnsRegex(DeprecationWarning, deprecated_regex): instructions = InstructionSet(registers) instructions.add(instruction, [Qubit()], []) with self.assertRaisesRegex(CircuitError, r"Invalid classical condition\. .*"): instructions.c_if([0], 0)
def test_instructionset_c_if_calls_custom_requester(self): """Test that :meth:`.InstructionSet.c_if` calls a custom requester, and uses its output.""" # This isn't expected to be useful to end users, it's more about the principle that you can # control the resolution paths, so future blocking constructs can forbid the method from # accessing certain resources. sentinel_bit = Clbit() sentinel_register = ClassicalRegister(2) def dummy_requester(specifier): """A dummy requester that returns sentinel values.""" if not isinstance(specifier, (int, Clbit, ClassicalRegister)): raise CircuitError return sentinel_bit if isinstance(specifier, (int, Clbit)) else sentinel_register dummy_requester = unittest.mock.MagicMock(wraps=dummy_requester) with self.subTest("calls requester with bit"): dummy_requester.reset_mock() instruction = HGate() instructions = InstructionSet(resource_requester=dummy_requester) instructions.add(instruction, [Qubit()], []) bit = Clbit() instructions.c_if(bit, 0) dummy_requester.assert_called_once_with(bit) self.assertIs(instruction.condition[0], sentinel_bit) with self.subTest("calls requester with index"): dummy_requester.reset_mock() instruction = HGate() instructions = InstructionSet(resource_requester=dummy_requester) instructions.add(instruction, [Qubit()], []) index = 0 instructions.c_if(index, 0) dummy_requester.assert_called_once_with(index) self.assertIs(instruction.condition[0], sentinel_bit) with self.subTest("calls requester with register"): dummy_requester.reset_mock() instruction = HGate() instructions = InstructionSet(resource_requester=dummy_requester) instructions.add(instruction, [Qubit()], []) register = ClassicalRegister(2) instructions.c_if(register, 0) dummy_requester.assert_called_once_with(register) self.assertIs(instruction.condition[0], sentinel_register) with self.subTest("calls requester only once when broadcast"): dummy_requester.reset_mock() instruction_list = [HGate(), HGate(), HGate()] instructions = InstructionSet(resource_requester=dummy_requester) for instruction in instruction_list: instructions.add(instruction, [Qubit()], []) register = ClassicalRegister(2) instructions.c_if(register, 0) dummy_requester.assert_called_once_with(register) for instruction in instruction_list: self.assertIs(instruction.condition[0], sentinel_register)