-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fixed commutation checking between two Pauli product measurements #16023
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
19ab6ba
2b4b48e
6323efa
8ef7b5b
027aeb4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| --- | ||
| fixes: | ||
| - | | ||
| Fixed commutativity check between two :class:`.PauliProductMeasurement` instructions | ||
| in the case that both instructions measure to the same classical bit. In this case, | ||
| the later measurement overwrites the result of the earlier measurement, and consequently, | ||
| interchanging the two measurement instructions inside the quantum circuit is generally | ||
| invalid. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -525,10 +525,11 @@ def test_pauli_based_gates(self, gate_type): | |
| for p1, q1, p2, q2, expected in cases: | ||
| if p1 == "I" and gate_type == "measure": | ||
| continue # PPM doesn't support all-identity gates | ||
| c1, c2 = ([0], [1]) if gate_type == "measure" else ([], []) | ||
|
|
||
| gate1 = build_pauli_gate(p1, gate_type) | ||
| gate2 = build_pauli_gate(p2, gate_type) | ||
| self.assertEqual(expected, scc.commute(gate1, q1, [], gate2, q2, [])) | ||
| self.assertEqual(expected, scc.commute(gate1, q1, c1, gate2, q2, c2)) | ||
|
|
||
| @data( | ||
| ("pauli", "measure"), | ||
|
|
@@ -544,10 +545,61 @@ def test_mix_pauli_gates(self, gate_type1, gate_type2): | |
| ] | ||
|
|
||
| for p1, q1, p2, q2, expected in cases: | ||
| c1 = [0] if gate_type1 == "measure" else [] | ||
| c2 = [1] if gate_type2 == "measure" else [] | ||
|
|
||
| gate1 = build_pauli_gate(p1, gate_type1) | ||
| gate2 = build_pauli_gate(p2, gate_type2) | ||
|
|
||
| with self.subTest(p1=p1, p2=p2): | ||
| self.assertEqual(expected, scc.commute(gate1, q1, [], gate2, q2, [])) | ||
| self.assertEqual(expected, scc.commute(gate1, q1, c1, gate2, q2, c2)) | ||
|
|
||
| def test_ppms_with_same_clbit(self): | ||
| """Test commutativity of two Pauli product measurements with the same clbit.""" | ||
|
|
||
| # Each case represents (pauli1, qubits1, pauli2, qubits2, expected result). | ||
| # Recall that the convention is that pauli strings are read right-to-left, i.e. | ||
| # pauli strings and qubits are in reverse order relative to each other. | ||
| cases = [ | ||
| ("XXII", [1, 0, 2, 3], "IIZZ", [1, 0, 2, 3], False), # different Paulis | ||
| ("XYIZ", [1, 0, 2, 3], "XYIZ", [1, 0, 4, 3], False), # different qubits | ||
| ( | ||
| "ZXII", | ||
| [1, 0, 2, 3], | ||
| "-ZXII", | ||
| [1, 0, 2, 3], | ||
| False, | ||
| ), # different Paulis (including sign) | ||
| ("XYIZ", [1, 0, 2, 3], "XYIZ", [1, 0, 2, 3], True), # same Paulis and qubits | ||
| ("-XYIZ", [1, 0, 2, 3], "-XYIZ", [1, 0, 2, 3], True), # same Paulis and qubits | ||
| ( | ||
| "XXIY", | ||
| [0, 1, 2, 3], | ||
| "YIXX", | ||
| [3, 2, 1, 0], | ||
| True, | ||
| ), # same Paulis and qubits up to reordering | ||
| ( | ||
| "XXIY", | ||
| [0, 1, 2, 3], | ||
| "XXIY", | ||
| [0, 1, 3, 2], | ||
| True, | ||
| ), # same Paulis and qubits up to reordering | ||
|
||
| ( | ||
| "-XXIY", | ||
| [0, 1, 2, 3], | ||
| "-YIXX", | ||
| [2, 3, 1, 0], | ||
| True, | ||
| ), # same Paulis and qubits up to reordering | ||
| ] | ||
|
|
||
| for pauli1, qubits1, pauli2, qubits2, expected in cases: | ||
| with self.subTest(pauli1=pauli1, qubits1=qubits1, pauli2=pauli2, qubits2=qubits2): | ||
| ppm1 = build_pauli_gate(pauli1, "measure") | ||
| ppm2 = build_pauli_gate(pauli2, "measure") | ||
| self.assertEqual(scc.commute(ppm1, qubits1, [0], ppm2, qubits2, [0]), expected) | ||
|
|
||
| def test_pauli_evolution_sums(self): | ||
| """Test PauliEvolutionGate commutations for operators that are sums of Paulis.""" | ||
|
|
@@ -585,7 +637,8 @@ def test_pauli_and_standard_gate(self, pauli_type): | |
| """Test Pauli-based gates and standard gate commutations are efficiently supported.""" | ||
| # 40-qubit Pauli gate with following terms: X: 0-9, Y: 10-19, Z: 20-29, I: 30-39 | ||
| pauli = 10 * "I" + 10 * "Z" + 10 * "Y" + 10 * "X" | ||
| pauli_indices = list(range(len(pauli))) | ||
| pauli_qubits = list(range(len(pauli))) | ||
| pauli_clbits = [0] if pauli_type == "measure" else [] | ||
alexanderivrii marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| pauli_gate = build_pauli_gate(pauli, pauli_type) | ||
|
|
||
| # Test cases in the format: (gate, indices, commutes) | ||
|
|
@@ -607,7 +660,9 @@ def test_pauli_and_standard_gate(self, pauli_type): | |
|
|
||
| for std_gate, indices, expected in cases: | ||
| with self.subTest(std_gate=std_gate, indices=indices): | ||
| commutes = scc.commute(pauli_gate, pauli_indices, [], std_gate, indices, []) | ||
| commutes = scc.commute( | ||
| pauli_gate, pauli_qubits, pauli_clbits, std_gate, indices, [] | ||
| ) | ||
| self.assertEqual(expected, commutes) | ||
|
|
||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.