Add SelectionRegisters and multi-indexed versions of SelectedMajoranaFermionGate and ApplyGateToLthQubit#210
Conversation
…FermionGate and ApplyGateToLthQubit
|
|
||
| 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 |
There was a problem hiding this comment.
why is this different now?
There was a problem hiding this comment.
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.
|
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 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 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 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 |
…into multi_select_hubb_gats
|
@mpharrigan I took your suggestion and moved the 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 See Fig 19 and 20 of https://arxiv.org/pdf/1805.03662.pdf for more context. |
…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
* 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>
Part of #108 and step towards #31
This PR introduces a concept of
SelectionRegisters, derived from theRegistersbase class.SelectionRegistersmake 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
Registerclass, and make it similar toFancyRegister. 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
SelectHubbardandPrepareHubbardand thus perform end to end resource estimation for the hubbard model as described in the linear T paper https://arxiv.org/abs/1805.03662cc @mpharrigan