Skip to content
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

Add .apply_layout()method to Pauli class #12066

Merged
merged 6 commits into from
Apr 11, 2024

Conversation

ElePT
Copy link
Contributor

@ElePT ElePT commented Mar 22, 2024

Summary

This PR adds an apply_layout method to the Pauli class, following what was done for SparsePauliOp in #10947. This was the agreed action to partially solve #11824 in the short term until a more permanent/extensible solution is designed.

Details and comments

@ElePT ElePT requested review from ikkoham and a team as code owners March 22, 2024 10:59
@qiskit-bot
Copy link
Collaborator

One or more of the the following people are requested to review this:

  • @Qiskit/terra-core
  • @ikkoham

@ElePT ElePT requested a review from chriseclectic March 22, 2024 10:59
@coveralls
Copy link

coveralls commented Mar 22, 2024

Pull Request Test Coverage Report for Build 8644607674

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 18 of 19 (94.74%) changed or added relevant lines in 1 file are covered.
  • 1086 unchanged lines in 88 files lost coverage.
  • Overall coverage increased (+0.07%) to 89.388%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/quantum_info/operators/symplectic/pauli.py 18 19 94.74%
Files with Coverage Reduction New Missed Lines %
qiskit/synthesis/evolution/qdrift.py 1 93.55%
qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py 1 96.3%
crates/qasm2/src/expr.rs 1 94.03%
qiskit/transpiler/preset_passmanagers/plugin.py 1 98.41%
qiskit/circuit/store.py 1 94.29%
qiskit/circuit/parameter.py 1 98.39%
qiskit/circuit/library/standard_gates/p.py 1 98.17%
crates/accelerate/src/optimize_1q_gates.rs 1 98.41%
qiskit/circuit/library/blueprintcircuit.py 2 95.16%
qiskit/primitives/backend_estimator_v2.py 2 97.84%
Totals Coverage Status
Change from base Build 8376619819: 0.07%
Covered Lines: 60322
Relevant Lines: 67483

💛 - Coveralls

@ElePT ElePT added this to the 1.1.0 milestone Mar 22, 2024
@ElePT ElePT added Changelog: New Feature Include in the "Added" section of the changelog mod: quantum info Related to the Quantum Info module (States & Operators) labels Mar 22, 2024
Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM, just a whitespace nit inline and a small question. But otherwise this is straightforward as it's just the same method as SparsePauliOp.

raise QiskitError("Provided layout contains indices outside the number of qubits.")
if layout is None:
layout = list(range(self.num_qubits))
new_op = type(self)("I" * n_qubits)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize I did the same thing in #10947 but I'm wondering if there is a more efficient constructor here that doesn't require creating a giant string like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, as far as I know, there is no good way to "sparsely" define long operators with only a few non-identity terms, in fact, I think that this is exactly what this issue describes (the word "layout" has a different meaning here: #11891).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, you can directly generate the symplectic Boolean matrices, but fundamentally, Pauli and SparsePauliOp aren't sparse over qubit number - the latter is "sparse" over the full Pauli vector.

Max's issue is about that sort of thing, yeah, although practically I don't think it's something we'll be able to put directly into Pauli and SparsePauliOp - I think it's something we'd do as new QI classes, probably directly in Rust space. This it the kind of thing that Paul's been interested in before as well, and similar to how OpenFermion and friends represent operators on huge spaces. The primitives want that as well.

Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests look right to me (and definitely something we should have), thanks for doing it!

Comment on lines +504 to +518
def test_apply_layout_with_transpile(self):
"""Test the apply_layout method with a transpiler layout."""
psi = EfficientSU2(4, reps=4, entanglement="circular")
op = Pauli("IZZZ")
backend = GenericBackendV2(num_qubits=7)
transpiled_psi = transpile(psi, backend, optimization_level=3, seed_transpiler=12345)
permuted_op = op.apply_layout(transpiled_psi.layout)
identity_op = Pauli("I" * 7)
initial_layout = transpiled_psi.layout.initial_index_layout(filter_ancillas=True)
final_layout = transpiled_psi.layout.routing_permutation()
qargs = [final_layout[x] for x in initial_layout]
expected_op = identity_op.compose(op, qargs=qargs)
self.assertNotEqual(op, permuted_op)
self.assertEqual(permuted_op, expected_op)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for completeness' sake, could you add a test that SparsePauliOp(Pauli(p).apply_layout(layout)) produces the same result as SparsePauliop(Pauli(p)).apply_layout(layout)? Just a consistency test, to enforce that we don't forget one or the other while updating.

Copy link
Contributor Author

@ElePT ElePT Apr 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that you were meaning to say SparsePauliOp(Pauli(p).apply_layout(layout)) produces the same result as Pauli(p).apply_layout(layout), right? This is what I added in 434a21c.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's fine too - you've ended up reducing the SparsePauliOp to a PauliList to check, whereas I was suggesting raising the Pauli to a SparsePauliOp to compare, but both test the same thing that I wanted to test.

Copy link
Contributor Author

@ElePT ElePT Apr 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahaa, I didn't notice the brackets. I can also do it the way you originally suggested (looks cleaner to compare the exact same type).

Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the extra test!

@jakelishman jakelishman added this pull request to the merge queue Apr 11, 2024
Merged via the queue into Qiskit:main with commit 4ff0fa2 Apr 11, 2024
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog mod: quantum info Related to the Quantum Info module (States & Operators) priority: high
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants