|
33 | 33 | SwitchCaseOp,
|
34 | 34 | )
|
35 | 35 | from qiskit.circuit.library import HGate, RZGate, CXGate, CCXGate, TwoLocal
|
| 36 | +from qiskit.circuit.classical import expr |
36 | 37 | from qiskit.test import QiskitTestCase
|
37 | 38 |
|
38 | 39 |
|
@@ -789,6 +790,96 @@ def test_compose_noclbits_registerless(self):
|
789 | 790 | self.assertEqual(outer.clbits, inner.clbits)
|
790 | 791 | self.assertEqual(outer.cregs, [])
|
791 | 792 |
|
| 793 | + def test_expr_condition_is_mapped(self): |
| 794 | + """Test that an expression in a condition involving several registers is mapped correctly to |
| 795 | + the destination circuit.""" |
| 796 | + inner = QuantumCircuit(1) |
| 797 | + inner.x(0) |
| 798 | + a_src = ClassicalRegister(2, "a_src") |
| 799 | + b_src = ClassicalRegister(2, "b_src") |
| 800 | + c_src = ClassicalRegister(name="c_src", bits=list(a_src) + list(b_src)) |
| 801 | + source = QuantumCircuit(QuantumRegister(1), a_src, b_src, c_src) |
| 802 | + |
| 803 | + test_1 = lambda: expr.lift(a_src[0]) |
| 804 | + test_2 = lambda: expr.logic_not(b_src[1]) |
| 805 | + test_3 = lambda: expr.logic_and(expr.bit_and(b_src, 2), expr.less(c_src, 7)) |
| 806 | + source.if_test(test_1(), inner.copy(), [0], []) |
| 807 | + source.if_else(test_2(), inner.copy(), inner.copy(), [0], []) |
| 808 | + source.while_loop(test_3(), inner.copy(), [0], []) |
| 809 | + |
| 810 | + a_dest = ClassicalRegister(2, "a_dest") |
| 811 | + b_dest = ClassicalRegister(2, "b_dest") |
| 812 | + dest = QuantumCircuit(QuantumRegister(1), a_dest, b_dest).compose(source) |
| 813 | + |
| 814 | + # Check that the input conditions weren't mutated. |
| 815 | + for in_condition, instruction in zip((test_1, test_2, test_3), source.data): |
| 816 | + self.assertEqual(in_condition(), instruction.operation.condition) |
| 817 | + |
| 818 | + # Should be `a_dest`, `b_dest` and an added one to account for `c_src`. |
| 819 | + self.assertEqual(len(dest.cregs), 3) |
| 820 | + mapped_reg = dest.cregs[-1] |
| 821 | + |
| 822 | + expected = QuantumCircuit(dest.qregs[0], a_dest, b_dest, mapped_reg) |
| 823 | + expected.if_test(expr.lift(a_dest[0]), inner.copy(), [0], []) |
| 824 | + expected.if_else(expr.logic_not(b_dest[1]), inner.copy(), inner.copy(), [0], []) |
| 825 | + expected.while_loop( |
| 826 | + expr.logic_and(expr.bit_and(b_dest, 2), expr.less(mapped_reg, 7)), inner.copy(), [0], [] |
| 827 | + ) |
| 828 | + self.assertEqual(dest, expected) |
| 829 | + |
| 830 | + def test_expr_target_is_mapped(self): |
| 831 | + """Test that an expression in a switch statement's target is mapping correctly to the |
| 832 | + destination circuit.""" |
| 833 | + inner1 = QuantumCircuit(1) |
| 834 | + inner1.x(0) |
| 835 | + inner2 = QuantumCircuit(1) |
| 836 | + inner2.z(0) |
| 837 | + |
| 838 | + a_src = ClassicalRegister(2, "a_src") |
| 839 | + b_src = ClassicalRegister(2, "b_src") |
| 840 | + c_src = ClassicalRegister(name="c_src", bits=list(a_src) + list(b_src)) |
| 841 | + source = QuantumCircuit(QuantumRegister(1), a_src, b_src, c_src) |
| 842 | + |
| 843 | + test_1 = lambda: expr.lift(a_src[0]) |
| 844 | + test_2 = lambda: expr.logic_not(b_src[1]) |
| 845 | + test_3 = lambda: expr.lift(b_src) |
| 846 | + test_4 = lambda: expr.bit_and(c_src, 7) |
| 847 | + source.switch(test_1(), [(False, inner1.copy()), (True, inner2.copy())], [0], []) |
| 848 | + source.switch(test_2(), [(False, inner1.copy()), (True, inner2.copy())], [0], []) |
| 849 | + source.switch(test_3(), [(0, inner1.copy()), (CASE_DEFAULT, inner2.copy())], [0], []) |
| 850 | + source.switch(test_4(), [(0, inner1.copy()), (CASE_DEFAULT, inner2.copy())], [0], []) |
| 851 | + |
| 852 | + a_dest = ClassicalRegister(2, "a_dest") |
| 853 | + b_dest = ClassicalRegister(2, "b_dest") |
| 854 | + dest = QuantumCircuit(QuantumRegister(1), a_dest, b_dest).compose(source) |
| 855 | + |
| 856 | + # Check that the input expressions weren't mutated. |
| 857 | + for in_target, instruction in zip((test_1, test_2, test_3, test_4), source.data): |
| 858 | + self.assertEqual(in_target(), instruction.operation.target) |
| 859 | + |
| 860 | + # Should be `a_dest`, `b_dest` and an added one to account for `c_src`. |
| 861 | + self.assertEqual(len(dest.cregs), 3) |
| 862 | + mapped_reg = dest.cregs[-1] |
| 863 | + |
| 864 | + expected = QuantumCircuit(dest.qregs[0], a_dest, b_dest, mapped_reg) |
| 865 | + expected.switch( |
| 866 | + expr.lift(a_dest[0]), [(False, inner1.copy()), (True, inner2.copy())], [0], [] |
| 867 | + ) |
| 868 | + expected.switch( |
| 869 | + expr.logic_not(b_dest[1]), [(False, inner1.copy()), (True, inner2.copy())], [0], [] |
| 870 | + ) |
| 871 | + expected.switch( |
| 872 | + expr.lift(b_dest), [(0, inner1.copy()), (CASE_DEFAULT, inner2.copy())], [0], [] |
| 873 | + ) |
| 874 | + expected.switch( |
| 875 | + expr.bit_and(mapped_reg, 7), |
| 876 | + [(0, inner1.copy()), (CASE_DEFAULT, inner2.copy())], |
| 877 | + [0], |
| 878 | + [], |
| 879 | + ) |
| 880 | + |
| 881 | + self.assertEqual(dest, expected) |
| 882 | + |
792 | 883 |
|
793 | 884 | if __name__ == "__main__":
|
794 | 885 | unittest.main()
|
0 commit comments