-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fix TemplateOptimization dropping the global_phase on substitution
#15943
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 all commits
a4c77b9
514c953
bdeeb62
82ebf1e
05c0b67
4da2d77
3b0b469
4b67060
51fcdde
893c47d
12b6284
a925da7
bd1833a
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,7 @@ | ||
| --- | ||
| fixes: | ||
| - | | ||
| Fixed :func:`.circuit_to_dagdependency` failing to copy ``global_phase`` when converting | ||
| a template :class:`.QuantumCircuit` to a :class:`.DAGDependency`. | ||
|
|
||
| Fixes `#14537 <https://github.com/Qiskit/qiskit/issues/14537>`__. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| --- | ||
| fixes: | ||
| - | | ||
| Fixed global phase handling in :class:`.TemplateSubstitution`, which previously | ||
| silently reset to input circuit's global phase to zero and didn't correct for global | ||
| phases of the templates. | ||
|
|
||
| Fixes `#14537 <https://github.com/Qiskit/qiskit/issues/14537>`__. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -737,7 +737,7 @@ def test_consecutive_templates_do_not_apply(self): | |
| qc.swap(0, 1) | ||
| qc.h(0) | ||
| qc_opt = pm.run(qc) | ||
| self.assertTrue(Operator(qc) == Operator(qc_opt)) | ||
| self.assertEqual(Operator(qc), Operator(qc_opt)) | ||
|
|
||
| def test_clifford_templates(self): | ||
| """Tests TemplateOptimization pass on several larger examples.""" | ||
|
|
@@ -758,10 +758,92 @@ def test_clifford_templates(self): | |
| seed=seed, | ||
| ) | ||
| qc_opt = pm.run(qc) | ||
| self.assertTrue(Operator(qc) == Operator(qc_opt)) | ||
| self.assertEqual(Operator(qc), Operator(qc_opt)) | ||
| # All of these gates are in the commutation library, i.e. the cache should not be used | ||
| self.assertEqual(scc.num_cached_entries(), 0) | ||
|
|
||
| def test_circuit_global_phase_preserved_after_single_and_multiple_template_match(self): | ||
| """Test that circuit global_phase survives template optimization (#14537).""" | ||
|
|
||
| circuit_in = QuantumCircuit(2, global_phase=np.pi / 4) | ||
| circuit_in.cx(0, 1) | ||
| circuit_in.cx(0, 1) | ||
|
|
||
| circuit_in_mult = QuantumCircuit(2, global_phase=np.pi / 3) | ||
| # Two independent pairs of CX gates — the template will match twice. | ||
| circuit_in_mult.cx(0, 1) | ||
| circuit_in_mult.cx(0, 1) | ||
| circuit_in_mult.cx(0, 1) | ||
| circuit_in_mult.cx(0, 1) | ||
|
|
||
| template = QuantumCircuit(2) | ||
| template.cx(0, 1) | ||
| template.cx(0, 1) | ||
|
|
||
| result = TemplateOptimization([template])(circuit_in) | ||
|
|
||
| result_mult = TemplateOptimization([template])(circuit_in_mult) | ||
|
|
||
| with self.subTest(msg="single template match"): | ||
| self.assertAlmostEqual(float(result.global_phase), np.pi / 4) | ||
| self.assertEqual(result.count_ops(), {}) | ||
|
|
||
| with self.subTest(msg="multiple template matches"): | ||
| self.assertAlmostEqual(float(result_mult.global_phase), np.pi / 3) | ||
| self.assertEqual(result_mult.count_ops(), {}) | ||
|
|
||
| def test_template_nonzero_global_phase_applied_to_circuit(self): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we use the example from the issue here, to have a proper regression test? The
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed to the 4-gate example in the issue. Changed the comment for that test accordingly, as now there is no substitution happening, so the comment below this is not relevant anymore.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, my bad. Just checked that there is partial substitution happening, of course. |
||
| """Test the template's global phase is respected (#14537).""" | ||
|
|
||
| template = QuantumCircuit(1) | ||
| template.h(0) | ||
| template.s(0) | ||
| template.h(0) | ||
| template.s(0) | ||
| template.h(0) | ||
| template.s(0) | ||
| template.global_phase = -np.pi / 4 | ||
|
|
||
| qr = QuantumRegister(1, "qr") | ||
| circuit_in = QuantumCircuit(qr, global_phase=np.pi / 4) | ||
| circuit_in.h(qr[0]) | ||
| circuit_in.s(qr[0]) | ||
| circuit_in.h(qr[0]) | ||
| circuit_in.s(qr[0]) | ||
|
|
||
| result = TemplateOptimization([template])(circuit_in) | ||
|
|
||
| self.assertEqual(Operator(circuit_in), Operator(result)) | ||
|
|
||
| def test_circuit_and_template_both_have_nonzero_global_phase(self): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This tests the same thing as the previous test, right? Do we need it?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think given that the previous test was changed to 4 gates and therefore |
||
| """Test that circuit and template global phases both contribute to the result (#14537).""" | ||
| template = QuantumCircuit(1) | ||
| template.h(0) | ||
| template.s(0) | ||
| template.h(0) | ||
| template.s(0) | ||
| template.h(0) | ||
| template.s(0) | ||
| template.global_phase = -np.pi / 4 | ||
|
|
||
| qr = QuantumRegister(1, "qr") | ||
| circuit_in = QuantumCircuit(qr) | ||
| circuit_in.h(qr[0]) | ||
| circuit_in.s(qr[0]) | ||
| circuit_in.h(qr[0]) | ||
| circuit_in.s(qr[0]) | ||
| circuit_in.h(qr[0]) | ||
| circuit_in.s(qr[0]) | ||
| circuit_in.global_phase = np.pi / 3 | ||
|
|
||
| result = TemplateOptimization([template])(circuit_in) | ||
|
|
||
| # All gates cancelled; total phase = circuit phase + template compensation | ||
| # = pi/3 + pi/4 = 7*pi/12. | ||
| self.assertAlmostEqual(result.global_phase, 7 * np.pi / 12) | ||
| self.assertEqual(result.count_ops(), {}) | ||
| self.assertEqual(Operator(circuit_in), Operator(result)) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() | ||
Uh oh!
There was an error while loading. Please reload this page.