Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to generate controlled/adjoint variant when it is not requested #1929

Open
tcNickolas opened this issue Sep 24, 2024 · 1 comment
Open
Labels
design needed enhancement New feature or request

Comments

@tcNickolas
Copy link
Member

Describe the bug

I'm trying to pick a random gate from an array, and using DrawRandomInt as the index fails because it doesn't support controlled and thus adjoint cannot be generated.

To Reproduce

operation Test3() : Bool {
    let ind = DrawRandomInt(0, 2);
    let op = [Rx, Ry, Rz][ind](1., _);
    let op1 = [Rx, Ry, Rz][DrawRandomInt(0, 2)](1., _);
    true
}

op and op1 are initialized in the same way (except the variable ind), but the second one yields an error.

Expected behavior

Two initializations of op and op1 should behave the same, since they do the same thing.

Screenshots

image

System information

  • VS Code 1.93.0
  • QDK 1.8.0
@tcNickolas tcNickolas added bug Something isn't working needs triage labels Sep 24, 2024
@swernli
Copy link
Collaborator

swernli commented Sep 30, 2024

This is an interesting one... I think the type system is working against you here in a valid but obscure way. The behavior of partial application is to try and turn the call invocation expression into the body of a function that matches the type of the expression being called, minus partial parameters. In this case, the expression being called is [Rx, Ry, Rz][DrawRandomInt(0, 2)] which correctly has type (Double, Qubit) => Unit is Adj + Ctl. The partial expression for the call is (1., _) which removes the Double and leaves the resolved type as Qubit => Unit is Adj + Ctl. So now the logic that creates the implied lambda does so with that type and the body of the expression, effectively creating:

operation PartialApplication(q : Qubit) : Unit is Adj + Ctl {
    [Rx, Ry, Rz][DrawRandomInt(0, 2)](1., _)
}

And then this fails adjoint and controlled generation later because DrawRandomInt is neither adjointable or controllable. I don't think there is a good way to fix this (short of incorporating it into #504, which is bigger than a bug fix). In the meantime, a workaround that could allow the operation to get chosen at random during each call would be using lambda syntax directly, which infers functors:

let op = q => [Rx, Ry, Rz][DrawRandomInt(0, 2)][1., q];

That will produce an op that gets a new choice from Rx, Ry, or Rz each time, but is not itself adjointable or controllable.

@sezna sezna added enhancement New feature or request design needed and removed bug Something isn't working needs triage labels Oct 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design needed enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants