microsoft / qsharp-language

Official repository for design of the quantum programming language Q# and its core libraries
MIT License
235 stars 56 forks source link

Make it easier to implement circuits described using mutable arrays #59

Open Strilanc opened 3 years ago

Strilanc commented 3 years ago

I was trying to implement the carry lookahead adder from https://arxiv.org/pdf/2004.01826.pdf . it has a step described like this:

image

As you can see, their description involves storing a reference to an initialized qubit into an array, which will be used during later steps.

Currently, it is difficult to implement this in Q# because:

  1. The syntax for mutating an array-of-arrays is extremely verbose.
  2. set lines prevent the creation of an automatic adjoint.
  3. Qubits need to be allocated outside the nested loop, requiring you to separately calculate the total number you need to allocate instead of just relying on the loop to do it.

I'm not exactly sure how to fix this, but it's something that I've run into more than once.

Here are some ideas:

  1. Have a concept of a "qubit pool", which you can iteratively ask for more qubits from and where all the qubits are deallocated when the pool goes away. Using a pool would prevent the automatic creation of an adjoint:
using (pool = QubitPool()) {
    for (...complicated...) {
        let q = pool.allocate_another();
    }
}
  1. Add support for mutable arrays, and/or multi-dimensional arrays, and/or hash maps. Support syntax like set map[(i, j)] = x.

  2. Allow the use of set statements inside of auto-adjoint operations as long as they invoke no operation that returns a value (except perhaps for some whitelisted special case operations like allocation). Implement these methods by executing them forwards, with all operations replaced by no-ops, recording the historical state of mutable variables. Then rewind while applying the inverses of the operations.

cgranade commented 3 years ago

Thanks for sharing this feedback! With respect to "the syntax for mutating an array-of-arrays is extremely verbose," would the changes proposed at https://github.com/microsoft/qsharp-language/pull/49 address your usecase?

Strilanc commented 3 years ago

Yes, that would help here.

bettinaheim commented 3 years ago

@Strilanc Would you be able to share an example of the code as it needs to be now? If I understand correctly how you use set, then it would be possible to isolate the isolate the population of the arrays into a function such that you can use automatic adjoint. Array comprehension is another idea we've been thinking about. Chris already mentioned multidimensional arrays that should help with this in the future as well. To understand what we can do for the rest, a code example would be really helpful.

Strilanc commented 3 years ago

@bettinaheim I did manage to rewrite the code into a more functional form with everything pre-allocated https://github.com/Strilanc/quantum-block-lookahead-adder/blob/master/anc/src/adder_lookahead.qs#L135 . But I think it's fair to say that the new form is a bit harder to follow the details of, and it certainly took more work than it would have otherwise.