Skip to content

Conversation

@anurudhp
Copy link
Contributor

@anurudhp anurudhp commented Jun 21, 2024

Decomposition for sorting lists whose size is a power of 2. Partially addresses #219

Described briefly in https://www.nature.com/articles/s41534-018-0071-5, circuit based on wiki.

@anurudhp
Copy link
Contributor Author

@tanujkhattar @fdmalone ptal

with pytest.raises(NotImplementedError):
bloq.decompose_bloq()
bloq = Comparator(2**4)
assert bloq.t_complexity().t == 88 - 4 - 7 * 4
Copy link
Collaborator

Choose a reason for hiding this comment

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

why the -7 * 4?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had some reason to justify this, but can't remember anymore. I think somewhere in the previous t_complexity it assumed CSwap was t=14, but the current impl is t=7

Copy link
Collaborator

Choose a reason for hiding this comment

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

The paper assumes CSWAP is t=4 using 1 ancilla, right? We should probably open an issue to track that though. Textbook CSWAP should be t=7.

CSWAP to 1 Toffoli can be reduced as follows
image

and then the Toffoli can be implemented using 4 T either using a Relative phase toffoli or using an ancilla with AND gate.

Copy link
Collaborator

@fdmalone fdmalone left a comment

Choose a reason for hiding this comment

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

So nice! I'm glad someone finally did this.

Copy link
Collaborator

@tanujkhattar tanujkhattar left a comment

Choose a reason for hiding this comment

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

+1, great to have this implemented!

Comment on lines 106 to 108
"""Given k numbers in [0, L), compare every pair that is `offset` apart.
Args:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please more details to the docstring - do we compare and swap or we just store the result of the comparison somewhere? Are the RIGHT junk registers storing the result of the comparison? Or are they supposed to be completely ignored?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated all docstrings.

Args:
bitsize: Number of bits used to represent each integer.
L: Upper-bound (excluded) on the input integers.
k: Number of integers in each half
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please specify that k must be a power of 2. Also specify the complexity in terms of T / Toffoli costs, ancilla cost and circuit depth.

Also, would it be a lot more work if we want to support merging two lists of different sizes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It isn't too difficult, but the edge cases need to be dealt with care. I wanted to get the power-of-2 case working first, will implement the general case in a follow up.

r"""Sort k numbers in the range {0, ..., L-1}.
Args:
L: Upper-bound (excluded) on the input integers.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please specify that k must be a power of 2. Also specify the complexity in terms of T / Toffoli costs, ancilla cost and circuit depth.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added to docstring

return Signature(
[
Register("xs", BoundedQUInt(self.bitsize, self.L), shape=(self.k,)),
Register("junk", QBit(), shape=(self.num_comparisons,), side=Side.RIGHT),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we have junk RIGHT registers everywhere ? Are we saving on any uncomputation? Can you also expand the docstring to explain 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.

This is the comparator circuit from the reference:
image

I wrote the signature similar to the And bloq where the result bit is RIGHT.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think its worth highlighting this in the docstring -- i.e. the junk stores the result of the comparisons. This would be necessary to make the sorting bloq reversible so you can apply the unitary in reverse and get back to the original sequence of unsorted elements if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated the docstring explaining this.

@tanujkhattar tanujkhattar self-assigned this Jun 24, 2024
Comment on lines 199 to 200
If each half has length $k$, then the merge network uses $k * (\log{k} + 1)$ comparisons
when $k$ is a power of 2.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please also add information / $$..$$ formula to specify what the junk stores since it can be potentially useful depending upon the context.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a brief description (similar to the one in BitonicSort).

Did you also want a description of the order of the ancillas?

Copy link
Collaborator

Choose a reason for hiding this comment

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

The order is not as important, but we should at least specify that the ancilla qubits store the results of intermediate comparisons.

Comment on lines 307 to 309
The bitonic sorting network requires $\frac{k}{2} \frac{\log{k} (\log{k} + 1)}{2}$ total comparisons,
and has depth $\frac{\log{k} (\log{k} + 1)}{2}$, when $k$ is a power of 2. Each comparison generates
one ancilla qubit, so the total size of junk register equals the number of comparisons.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is great!

Copy link
Collaborator

@tanujkhattar tanujkhattar left a comment

Choose a reason for hiding this comment

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

LGTM % some final comments

$$
The above expression is at most $k / 2$.
Each comparison generates one ancilla qubit, which are aggregated into the `junk` register.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
Each comparison generates one ancilla qubit, which are aggregated into the `junk` register.
Each comparison generates one ancilla qubit which stores the result of the comparison. The ancillas
are aggregated into the `junk` register.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

+ \max((k\mod 2\delta) - \delta, 0)
$$
The above expression is at most $k / 2$.
Copy link
Collaborator

Choose a reason for hiding this comment

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

There seems to be a break after "this requires, . The above expression".

We should finish the "this requires," line. Maybe something like

Suggested change
The above expression is at most $k / 2$.
number of comparisons. The above expression is at most $k / 2$.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oops, fixed

If each half has length $k$, then the merge network uses $k (1+\log{k})$ comparisons
when $k$ is a power of 2.
Each comparison generates one ancilla qubit, which are aggregated into the `junk` register.
Copy link
Collaborator

Choose a reason for hiding this comment

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

ditto: Let's specify that the ancilla qubit stores the result of comparisons

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

@tanujkhattar tanujkhattar merged commit cc4e3bc into quantumlib:main Jun 24, 2024
@anurudhp anurudhp deleted the 2024-06-20-bitonic-sort branch June 24, 2024 21:50
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