Skip to content

Improve qubit counting logic to minimize qubit counts over multiple allocations #1636

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

Open
tanujkhattar opened this issue Apr 28, 2025 · 2 comments · May be fixed by #1641
Open

Improve qubit counting logic to minimize qubit counts over multiple allocations #1636

tanujkhattar opened this issue Apr 28, 2025 · 2 comments · May be fixed by #1641

Comments

@tanujkhattar
Copy link
Collaborator

import attrs

from qualtran import Bloq, Signature, BloqBuilder, SoquetT
from qualtran.bloqs.basic_gates import CNOT, TGate
from qualtran.drawing import show_bloq
from qualtran.resource_counting import QubitCount, get_cost_value

@attrs.frozen
class TestManyAlloc(Bloq):
    n: int
    alloc_once: bool

    @property
    def signature(self) -> Signature:
        return Signature.build(x=self.n)

    def build_composite_bloq(self, bb: 'BloqBuilder', *, x: 'SoquetT') -> dict[str, 'SoquetT']:
        x = bb.split(x)
        if self.alloc_once:
            anc = bb.allocate(1)
        for i in range(self.n):
            if not self.alloc_once:
                anc = bb.allocate(1)
            x[i], anc = bb.add(CNOT(), ctrl=x[i], target=anc)
            anc = bb.add(TGate(), q=anc)
            x[i], anc = bb.add(CNOT(), ctrl=x[i], target=anc)
            if not self.alloc_once:
                bb.free(anc)
        if self.alloc_once:
            bb.free(anc)
        return {'x': bb.join(x)}


get_cost_value(TestManyAlloc(10, True), QubitCount()), get_cost_value(TestManyAlloc(10, False), QubitCount())

Output:

(11, 20)

Ideally, there should be a way to get 11 qubits in both the cases above.

@mpharrigan
Copy link
Collaborator

If we allocate once, we get

Image

If we allocate and free inside the for loop, we get

Image

and get the inflated qubit count.

The ideal solution in this case is to use subroutines to structure your code

Image

but we can also recover the desired behavior most of the time using our specialized topological sort greedy_topological_sort which postpones allocations.

Image

I'll open a PR

@mpharrigan
Copy link
Collaborator

Note that I had to hack in greedy_topological_sort to get the ultimate diagram, see #1640

@mpharrigan mpharrigan linked a pull request May 5, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants