Skip to content

feature: MPS Encoding Algorithm#179

Merged
sesmart merged 6 commits intoamazon-braket:feature-mpsfrom
ACE07-Sev:app-1
Feb 27, 2026
Merged

feature: MPS Encoding Algorithm#179
sesmart merged 6 commits intoamazon-braket:feature-mpsfrom
ACE07-Sev:app-1

Conversation

@ACE07-Sev
Copy link
Copy Markdown

@ACE07-Sev ACE07-Sev commented Feb 16, 2026

Issue #, if available:#1193

Description of changes:

  • Added MPS Encoding Algorithm.

Testing done:

  • Added unit tests for product states, general area-law entangled states, and single qubit states.

Merge Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.

General

Tests

  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have checked that my tests are not configured for a specific region or account (if appropriate)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@ACE07-Sev ACE07-Sev requested a review from a team as a code owner February 16, 2026 13:16
@ACE07-Sev
Copy link
Copy Markdown
Author

ACE07-Sev commented Feb 16, 2026

Some context I think is useful. So, MPS Encoding is the task of doing approximate state preparation using Matrix Product State (MPS) representation of a dense tensor (aka our statevector) as an IR. What happens is we approximate the target state with a MPS, and then compile that MPS to a circuit.

The exponential depth reduction comes from how MPS uses $O(N\chi^2)$ parameters as opposed to $O(N)$ where $\chi$ is the bond dimension (think of it like a knob that you can increase to make the MPS approximation better). Ran's approach uses a compressed bond-2 MPS, so $\chi$ is always equal to 2, and thus by stacking multiple layers of bond 2 MPS we are able to perform the state preparation.

Caveats are that vanilla MPS (what's presented here) only does well on area-law entangled states as that's a limitation of MPS itself. To improve that, I can also make a PR for Application 2 issue where I can add a sweeping algorithm that works both as a standalone circuit optimizer as well as a complementary optimization for MPS.

P.S: I finished preparing the sweeping I mentioned as a PR for application 2. If this PR sees interest, I'll open one for that as well.

@sesmart
Copy link
Copy Markdown
Contributor

sesmart commented Feb 17, 2026

Hi @ACE07-Sev, this is really cool! Thanks for the contribution, and would be really cool to see the follow up as well.

Merging from main should fix the readthedocs, though will try and test a PR locally to see what some of the tox issues are.

@ACE07-Sev
Copy link
Copy Markdown
Author

Thanks for the contribution, and would be really cool to see the follow up as well.

I'm glad you like it. Sure thing, I should have a PR for that in a bit.

@ACE07-Sev
Copy link
Copy Markdown
Author

The coverage issue makes sense. I only tested the behavior of the encoding on different target states, not individual lines of code (more like a black box testing approach).

@ACE07-Sev
Copy link
Copy Markdown
Author

ACE07-Sev commented Feb 17, 2026

@sesmart I added the PR for sweeping #183.

If you like that, I can add the unitary version of sweeping as well.


# Single qubit statevector is optimal, and cannot be
# further improved given depth of 1
if num_qubits == 1:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would have this as a new function or include in the main conversion function

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

So a new function for single qubit state prep?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think so yes, just to make the call method a bit cleaner. But it's not a big deal. mps_to_circuit_approx by comparison is >100 LOC - though a lot of that is comments.

U, _, Vh = np.linalg.svd(unitary)
unitary = U @ Vh

circuit.unitary(matrix=unitary, targets=qubits)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there a way to limit the unitary dimension in the layers such that we only have maybe d=4, and then can do a 2q unitary decomposition?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actually, is that achieved by contracting to a bond dimension =2 system? Or not quite? If so I think we can totally do a 2q decomposition.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The unitary dimension here will always be either 1q or 2q. I imagined in your src you'd route to 2q decomposition if the dimension of unitary is 4x4 or 2x2. If not, yes, definitely can use those instead.

Copy link
Copy Markdown
Author

@ACE07-Sev ACE07-Sev Feb 20, 2026

Choose a reason for hiding this comment

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

Actually, is that achieved by contracting to a bond dimension =2 system? Or not quite? If so I think we can totally do a 2q decomposition.

Forgot to answer this. Yes, we have the guarantee that it'll only use 1 and 2 qubit unitaries because the bond dimension is 2. Given bond dimension 2^n, we can encode that into a gate with n+1 qubits.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Please let me know where I can get the 1q and 2q decompositions to substitute (although this would be better if you do it natively so that when unitary is 2x2 or 4x4 to use the 1q and 2q decompositions automatically).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also, the compilation point is a bit more complex, and I am more worried about the topology than the native gate choice. 1 and 2q resynthesis will generally occur, in the Braket compiler or in Qiskit.

To submit on a device simply requires that you don't have Circuit.unitary gates, so expressing it in U3 + CX/CZ is sufficient. To do it really well though you should probably take advantage of device properties in the decomposition, which I think is beyond the current scope, and may change guarantees about depth and compactness. Unless the protocol actually can be laid out in a layer-like structure.

Copy link
Copy Markdown
Author

@ACE07-Sev ACE07-Sev Feb 26, 2026

Choose a reason for hiding this comment

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

For quick - maybe just reference it? It's good to have as a resource but we don't necessarily need the most performant thing.

No no I meant I could just copy paste that code here. Not to reference it, it's a bit embarrassing of a library for that hehe.

Copy link
Copy Markdown
Contributor

@sesmart sesmart Feb 26, 2026

Choose a reason for hiding this comment

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

Actually, we do support global phase, just not on devices. If you are just converting without supplying a device, I think it should preserve the phase, right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I added global_phase to basis gates. Should I remove it? It ran and stopped giving the warnings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nope, that looks good. That's exactly why it would happen. If you didn't specify basis sets it would have defaulted to all gates ,which might have included unitary and thus not actually decomposed.

@ACE07-Sev
Copy link
Copy Markdown
Author

@sesmart Can I get a review please?

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (3c92423) to head (0f4416c).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #179   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           30        32    +2     
  Lines         1220      1318   +98     
  Branches       156       168   +12     
=========================================
+ Hits          1220      1318   +98     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

U, _, Vh = np.linalg.svd(unitary)
unitary = U @ Vh

circuit.unitary(matrix=unitary, targets=qubits)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also, for the 1- and 2q decompositions, we are okay to use the qiskit-braket-provider here. You can then run to_braket(unitary, optional args), which should decompress it.

@ACE07-Sev
Copy link
Copy Markdown
Author

Anything else I need to do on my side?

@sesmart
Copy link
Copy Markdown
Contributor

sesmart commented Feb 26, 2026

Nope, looks good to go! Will follow up shortly.

@sesmart sesmart self-requested a review February 27, 2026 17:43
@sesmart sesmart changed the base branch from main to feature-mps February 27, 2026 17:43
@sesmart
Copy link
Copy Markdown
Contributor

sesmart commented Feb 27, 2026

merging to feature branch for the moment, while we get consensus on how to handle quimb as a dependency - marking #1194 as closed.

@sesmart sesmart merged commit 723c085 into amazon-braket:feature-mps Feb 27, 2026
13 checks passed
@sesmart
Copy link
Copy Markdown
Contributor

sesmart commented Feb 27, 2026

Hi @ACE07-Sev, can you please comment on one of the algorithms issues in the BDK? It needs to be assigned but you have to comment first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants