Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Windowed unitary application #602

Closed
adrianleh opened this issue Jul 6, 2022 · 6 comments
Closed

Windowed unitary application #602

adrianleh opened this issue Jul 6, 2022 · 6 comments
Labels
Kind-Enhancement New feature or request Status-NeedsApiReview This PR requires an API review before merging in.

Comments

@adrianleh
Copy link
Contributor

Proposal title

Windowed Unitary application

Conceptual overview

Addition of a function to apply unitary operations windowed. Windowed operations occur in many quantum algorithms and operations. This proposal proposes a wrapper that will allow windowing of operations with dedicated target qubits to make code more semantic and to provide new users easier ways to implement such operations.

Current status

Currently there is support for creating windows on Arrays, i.e., diving them into chunks of a specific size but no support for windowing operations. So to window an operation requires manually splitting an array and applying the operation over it.

User feedback

N/A

Child issues

N/A

Proposal

New and modified functions, operations, and UDTs

In namespace Microsoft.Quantum.Arrays:

/// # Summary
/// Applies an operation windowing over input but with constant target qubits.
///
/// # Input
/// ## windowLen
/// The size of each window
/// ## op
/// An operation with three arguments, one index, controls, and target. When applied it will be supplied with a windowed component of the `qubits` parameter, the `target` qubits (constant) and an index of the window
/// ## qubits
/// The qubits the operation windows over
/// ## target
/// The target provided to each windowed operation
operation ApplyWindowed(windowLen : Int, op : (Int, Qubit[], Qubit[]) => Unit,  qubits : Qubit[], target : Qubit[]) : Unit

Modifications to style guide

N/A

Impact of breaking changes

N/A

Examples

Current status

Currently the most efficient solution is to inline op in the following:

let windows = Windows(windowLen, qubits); // Create windows of non-target qubits
for (i, window) in Enumerated(windows) {    op(argumentTransform(i), window, target);
}

Using proposed changes

Given this function is mainly a convivence wrapper it would merely involve the single function call.

Relationship to Q# language feature proposals

N/A

Alternatives considered

An alternative would be to include an explicit transformation of the index, however this can be encapsulated in op

/// # Summary
/// Applies an operation windowing over input but with constant target qubits.
///
/// # Input
/// ## windowLen
/// The size of each window
/// ## op
/// An operation with three arguments, one arbitrary, controls, and target. When applied it will be supplied with a windowed component of the `qubits` parameter, the `target` qubits (constant) and an arbitary parameter stemming from the `argumentTransform` mapping supplied.
/// ## argumentTransform
/// Transforms an integer into the arbitary argument for op. This function will be provide with the indices of the windows. This means the function need to work correctly for $[0, n[$, where $n$ is the number of windows.
/// ## qubits
/// The qubits the operation windows over
/// ## target
/// The targer provided to each windowed operation
/// # Type Parameters
/// ## 'T
/// Any type that the operation can use as parametrization
operation ApplyWindowed<'T>(windowLen : Int, op : ('T, Qubit[], Qubit[]) => Unit, argumentTransform : Int -> 'T, qubits : Qubit[], target : Qubit[]) : Unit

Open design questions and considerations

N/A

@adrianleh adrianleh added Kind-Enhancement New feature or request Status-NeedsApiReview This PR requires an API review before merging in. labels Jul 6, 2022
@adrianleh adrianleh mentioned this issue Jul 7, 2022
@cgranade
Copy link
Contributor

cgranade commented Jul 7, 2022

This looks like a useful new operation, thank you for the suggestion and your PR! From the standpoint of an API review, I'd make a few different suggestions on how to make it fit better within the standard libraries.

First, the target input isn't needed, since that can always be readily handled using partial application or lambas. In particular, looking at #603, the same value is passed to op each time it's called. I'd therefore suggest dropping target entirely as an input. That also makes it easier to work with types of targets other than Qubit[] (e.g.: singleton qubits, doubly nested arrays, little endian registers, etc.).

Second, you may want to window over something over than individual qubits in an array. Introducing a type parameter for that would be very helpful, since the body of ApplyWindowed never uses that the elements of qubits are of type Qubit.

Taking these together, you might get something like this as an implementation:

    operation ApplyWindowed<'T>(windowLen : Int, op : (Int, 'T[]) => Unit, register : 'T[]) : Unit {
        ApplyToEach(op, Enumerated(Windows(windowLen, register)));
    }

Past that, I'd also suggest introducing A, C, and CA variants to allow using this operation from operations that need to be adjointable and/or controllable.

Thanks!

@adrianleh
Copy link
Contributor Author

@cgranade Thank you for the suggestions, those indeed look more idiomatic - I'll update the PR

adrianleh added a commit to adrianleh/QuantumLibraries that referenced this issue Jul 7, 2022
adrianleh added a commit to adrianleh/QuantumLibraries that referenced this issue Jul 7, 2022
@msoeken msoeken added this to Ready to be reviewed in API Review Scheduling Jul 17, 2022
@msoeken
Copy link
Member

msoeken commented Jul 19, 2022

I'd like to combine @cgranade's suggestion to drop the target and make the array type generic, but I'd also like to include the argumentTransform into the signature, then having two generic arguments.

@cgranade
Copy link
Contributor

...but I'd also like to include the argumentTransform into the signature, then having two generic arguments.

I'm not sure I understand the reasoning there? That feels like it duplicates a lot of the functionality of Mapped and Enumerated; in particular, could always do something like let argumentTransform = ...; ApplyWindowed((idx, window) => ApplyFoo(argumentTransform(idx), window), register);.

What usecase are you looking at for including argumentTransform as an explicit input?

@msoeken
Copy link
Member

msoeken commented Jul 19, 2022

+1 on @cgranade on using lambda's instead of argumentTransform.

@cgranade
Copy link
Contributor

LGTM, I think just one last minor suggestion: ApplyToEachWindow would match ApplyToEach, ApplyToEachIndex, etc. a bit better than ApplyWindowed. Other than that, happy to approve with no further comment. Thanks!

@msoeken msoeken moved this from Ready to be reviewed to Reviewed: approved in API Review Scheduling Jul 19, 2022
msoeken added a commit that referenced this issue Jul 20, 2022
* Add ApplyWindowed operation

Applies an operation windowing over input but with const target qubits

* Simplify ApplyWindowed

* Update ApplyWindowed to be more idiomatic

See comment on #602 by @cgranade

* Fix documentation style issues for ApplyWindowed

* Improve ApplyWindowed documentation and add example

* Change name of ApplyWindowed to ApplyToEachWindow

* Fix example being in code block

Co-authored-by: Mariia Mykhailova <michaylova@gmail.com>

Co-authored-by: Mathias Soeken <mathias.soeken@microsoft.com>
Co-authored-by: Mariia Mykhailova <michaylova@gmail.com>
@msoeken msoeken closed this as completed Dec 13, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Kind-Enhancement New feature or request Status-NeedsApiReview This PR requires an API review before merging in.
Projects
API Review Scheduling
Reviewed: approved
Development

No branches or pull requests

3 participants