Skip to content

Comments

Add SelectionRegisters and multi-indexed versions of SelectedMajoranaFermionGate and ApplyGateToLthQubit#210

Merged
tanujkhattar merged 6 commits intomainfrom
multi_select_hubb_gats
May 9, 2023
Merged

Add SelectionRegisters and multi-indexed versions of SelectedMajoranaFermionGate and ApplyGateToLthQubit#210
tanujkhattar merged 6 commits intomainfrom
multi_select_hubb_gats

Conversation

@tanujkhattar
Copy link
Collaborator

Part of #108 and step towards #31

This PR introduces a concept of SelectionRegisters, derived from the Registers base class. SelectionRegisters make it easier to represent multiple named selection registers, used as an input for nested coherent for-loops with different ranges. It is also very convenient to store the iteration ranges for each selection register along with the bitsize.

Another approach could have been to try and extend the Register class, and make it similar to FancyRegister. But as a first attempt, I found this to be more natural. because it provides a way to assign different names to each of the different nested selection registers.

I have a follow up WIP pr that uses this to correctly implement SelectHubbard and PrepareHubbard and thus perform end to end resource estimation for the hubbard model as described in the linear T paper https://arxiv.org/abs/1805.03662

cc @mpharrigan


initial_state = [qubit_vals[x] for x in g.all_qubits]
qubit_vals[g.quregs['target'][-(n + 1)]] = 1
qubit_vals[g.quregs['target'][n]] = 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

why is this different now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Because earlier we were applying the gate on target[-(selection + 1)] and now we are applying it on target[target_idx]
i.e. self._nth_gate(selection).on(target[-(selection + 1)]).controlled_by(control) changed to self.nth_gate(*selection_idx).on(target[target_idx]).controlled_by(control).

Note that this just means earlier we were explicitly treating the target register in a big-endian notation and therefore the 0th bit was stored in the last position.

Now, with multi-dimensional selection registers, it makes more sense to think of target registers as an array of qubits and follow the natural array indexing.

@mpharrigan
Copy link
Collaborator

mpharrigan commented Apr 24, 2023

I think of our "registers" classes as the types we support. They're "dependent types" as we can statically declare their size. In fancy registers, the bitsize argument is an atomic dimension like how uint32 is opaquely 32 bits. We let you choose any number for this (in both legacy registers and 'fancy' registers world). FancyRegister adds explicit support for n-dimensional arrays of a given atomic type.

We don't have to stop here. Instead of restricting the range of values from 0 to 2**bitsize-1 we can add an additional dependent-typing parameter: the iteration length. I think conceptually this belongs on the register (no "s") objects. This prevents the situation where the number of iteration lengths does not match the number of registers. I think it will also be important for extending this concept to ndarray ("wireshape") registers.

edit: since this is just an attribute describing the range of acceptable integers, it might deserve a more generic name. It can be used for things other than indexing.

FancySelRegister('p', wireshape=(8, 8, ), bitsize=2,  iteration_lengths=(200,198, 2))

In fact: I wonder whether -- in bloqs world -- we only support flat indexing for multidimensional registers? It seems like a natural fit.

To get the flat indexing to work, you need an ordered list of iteration lengths and some sort of mapping to what register they came from. In the multidimensional register case: each iteration length corresponds to a dimension. In the current PR, there is a list of (iteration length, register) pairs so each dimension has its own name. It would probably get complicated if we tried to support a collection of multi-dimensional registers(??).

It's nice to be able to choose whether a dimension is a nameless slice of an ndarray or given a name like "p_x".

Normal programming languages have product types (classes, tuples).

MyIndex = QuantumTuple(Register("p_x", 8, iter=200), Register("p_y", 8, iter=198))

This is close to what the Registers (with s) class is representing. In this PR; the selection "tuple" is flattened into the registers property but you can imagine (re-)designing the infrastructure to allow nested Registers (with s). Sounds like a nightmare.


anyways, I'm fine with proceeding with the current PR for expediency but curious to hear what you would do in a conceptually pure world.

I think it would be worth prototyping a version where we subclass Register and have SelectionRegisters constructor assert that they're all instances of that new type.

@tanujkhattar
Copy link
Collaborator Author

@mpharrigan I took your suggestion and moved the iteration_length parameter to a new derived class SelectionRegister and the SelectionRegisters now just accepts an Iterable[SelectionRegister].

I still think that for this use case, having a named access to each dimension of the multi-dimensional selection register is important. Therefore, having the SelectionRegisters derived class which can provide a named access to each individual SelectionRegister is the way to go; instead of using a FancyRegister style multi-dimensional numpy array with the same name. The reason is that we need to apply different operations to registers belonging to each dimension.

See Fig 19 and 20 of https://arxiv.org/pdf/1805.03662.pdf for more context.

@tanujkhattar tanujkhattar merged commit 1ac43bf into main May 9, 2023
fdmalone pushed a commit that referenced this pull request May 10, 2023
…aFermionGate` and `ApplyGateToLthQubit` (#210)

* Fix numerical instability issue in and_gate.ipynb

* Remove prints

* Add SelectionRegisters and multi-indexed versions of SelectedMajoranaFermionGate and ApplyGateToLthQubit

* Add a SelectionRegister base class and use it in SelectionRegisters derived class
mpharrigan added a commit that referenced this pull request Jun 20, 2023
* Addition gate.

* Add basic arithmetic bloqs.

* More basic bloqs.

* Rename arthmetic_bloqs -> arithmetic.

* Tidy + tests.

* More Bloqs.

* Add test.

* Add notebooks + more tests.

* Fix references + notebook.

* Sorting notebook.

* Fix errors.

* Fix lint error.

* Fix import order.

* Fix formatting.

* Remove imports from init.

* Update cirq_qubitization/bloq_algos/arithmetic.py

Co-authored-by: Matthew Harrigan <mpharrigan@google.com>

* Update nbits -> bitsize + typos.

* Add short_name method for sorting bloqs.

* Add issue comments.

* Working on registers.

* Use multidimensional registers.

* Fix test.

* Remove pretty_name.

* Clear outputs.

* Address more review comments.

* Add rotation gate unit tests.

* Add rotation gates to __init__.

* Address review comments.

* Upadate notebook.

* Fix sum of squares unit test.

* Fix formatting.

* Remove unused imports.

* Fix some docstrings.

* Fix unit test.

* Fix notebooks.

* Add SelectionRegisters and multi-indexed versions of `SelectedMajoranaFermionGate` and `ApplyGateToLthQubit` (#210)

* Fix numerical instability issue in and_gate.ipynb

* Remove prints

* Add SelectionRegisters and multi-indexed versions of SelectedMajoranaFermionGate and ApplyGateToLthQubit

* Add a SelectionRegister base class and use it in SelectionRegisters derived class

* Remove debug code.

* Note book tests.

* fixes

* Fix jupyter imports.

---------

Co-authored-by: Matthew Harrigan <mpharrigan@google.com>
Co-authored-by: Tanuj Khattar <tanujkhattar@google.com>
@mpharrigan mpharrigan deleted the multi_select_hubb_gats branch November 20, 2023 20:01
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.

2 participants