-
Notifications
You must be signed in to change notification settings - Fork 54
Allocatable types and generalization of initializers #40
Description
Suggestion
The suggestion is to generalize the mechanism for [qubit allocations] in Q# to cover the following scenarios by introducing a more general notion of initializers for qubit allocations:
- Creating instances of user defined types containing qubits
- Initializing the allocated qubits with a certain operation upon allocation
- Automatic allocation and deallocation of temporary qubits used during initialization
The suggestion applies to both using- and borrowing statements, and allows to instantiate values of a broad range of allocatable types instead of just values of type Qubit, Qubit[], and tuples thereof. The suggestion involves introducing a new keyword init that allows to elevate adjointable operations to initializers for the sake of supporting the second bullet point above.
Considerations
All of the above is possible to express with the current version of Q#, but the syntax for expressing that is somewhat verbose. Extending the concept of initializers and adding the necessary compiler support for automation of these scenarios allows to express them in a much more natural and readable manner. Any quantum transformations executed upon initializations are automatically reverted upon deallocation.
I believe the concept of initializers can be extended to cover a broader range of types in a consistent manner, without sacrificing any of the guarantees that Q# currently gives and in a way that can be executed on quantum hardware; it should always be possible to bound the number of required qubits by imposing a size limit on the call stack, much like it is the case for the current version of Q#.
The suggested generalizations greatly enhance the expressiveness of Q#. At the same time, it should be possible to translate the additional capabilities and syntax into the current version of the Q# language, such that the suggestion merely involves introducing additional syntax and automation capabilities. The examples below illustrate the suggested mechanism in more detail.
Context
Even though Q# does not currently support defining custom constructors for types, this would be a good addition to the language in the future. As part of a proposal for generalizing initializers, it is hence important to consider how the introduced concepts would work if custom constructors are supported. As part of a potential proposal, it also makes sense to discuss the implementation for supporting the nesting of initializers as part of initializer expressions in detail.
Furthermore, the restrictions that need to be imposed on operations to ensure that they can be elevated to initializers need to be clarified. Besides the requirement that such operations need to be adjointable, it may make sense to impose restrictions on whether or not the operations in question may capture (certain) qubits. If it is possible for such operations to capture qubits, then it giving guarantees regarding whether the un-computation of the allocated qubits is successful would be challenging. Alternatively, it may make sense to distinguish when an operation is (only) intended to be applied upon initialization, versus when its adjoint should also be applied before deallocation.
For the sake of consistency in syntax, it is reasonable to make one breaking change at part of this proposal. Concretely, the suggested breaking change is to replace the current syntax Qubit[n] that is used to initialize an array of qubits with Qubits(n). The exact syntax is to be determined as part of the proposal, and it needs to be possible to potentially extend it to the multi-dimensional case in a consistent manner in the future.
Related suggestions/proposals: #14, #39.
Examples
I will adopt the simplifications for qubit allocations that are currently under review in the given examples for the sake of convenience, though the examples remain valid also if only the current syntax is available.
Example 1: Initializing values of various types to various states
The following statements are valid within operations if this suggestion is adopted, where init is a newly introduced keyword used to elevate (certain) adjointable operations to initializers:
use q = Qubit(); // q contains a single qubit in a state |0>
use qs = Qubits(3); // qs contains a 1D array of 3 qubits in a state |000>
use qInt = BigEndian(3); // qInt contains a BigEndian value containing an array of 3 qubits in a state |000>
use xq = init H; // xq contains a single qubit in a state |+>
use xqs = init(3) ApplyToEachA(H, _); // xqs contains a 1D array of 3 qubits in a state |+++>
use register = init(4) ApproximateQFT(4, _); For an operation ApproximateQFT as defined here, register will be bound to a value of type LittleEndian containing an array of 4 qubits initialized to QFT |0000> (i.e. to a uniform superposition). The last line in the example above can be translated into the following upon compilation:
use __var1__ = Qubits(4) {
let register = LittleEndian(__var1__);
within { ApproximateQFT(4, register); }
apply {
// code within the allocation scope
}
}Example 2: Nesting of initializer expressions and potential future syntax enhancements
If we were to allow for elevated operations to capture qubits, then introducing additional syntax sugar for particular operations, such as e.g. a coherent version of a logical AND would allow to express oracles constructed from such operators in the following way, if this suggestion is adopted:
use res = q1 <and> q2 <and> q3; where the right hand side is syntactic sugar init And(init And(q1, q2, _), q3, _), and q1, q2, q3 are existing qubits that are in scope. The statement above could be translated into the following upon compilation:
use res = Qubit() {
within {
use __var1__ = Qubit() {
within { And (q1, q2, __var1__); }
apply { And (__var1__, q3, res); }
}
}
apply {
// code within the allocation scope
}
}Introducing additional syntax for coherent versions of logical operators is outside the scope of this proposal, but should be considered as part of the discussion on interactions with future modifications.
Affidavit (please fill out)
Please add ticks by placing a cross in the box:
- I have searched both open and closed suggestions and proposals on this site and believe this is not a duplicate.
- I believe that the spirit of this suggestion is aligned with the design principles and general vision for Q#.
Please tick all that apply:
- This is not a breaking change to the Q# language design
- I or my organization would be willing to help implement and/or test this