microsoft / QuantumLibraries

Q# libraries for the Quantum Development Kit
https://docs.microsoft.com/quantum
MIT License
543 stars 179 forks source link

Improvements to Microsoft.Quantum.Arrays #313

Closed cgranade closed 4 years ago

cgranade commented 4 years ago

Abstract

There is a close connection between the iteration over classical values, and generalizing "circuit"-like patterns into high-level code. In Q#, we use exploit this connection with the Microsoft.Quantum.Arrays namespace to make it easier express high-level patterns. We have noted from user feedback, however, that some common patterns are difficult to express using existing array functions, or that users may not be able to discover needed functionality.

The improvements proposed here empower users to make better use of high-level quantum development in Q# by making it easier to iterate over collections of values, such as Qubit[], and to use them to write out complex algorithmic patterns efficiently.

Proposed deprecations and renamings

Proposed additions

Future considerations and language feature dependencies

Other comments

msoeken commented 4 years ago

I suggest to add a function Flattened with the following specification:

function Flattened<'T>(arrays : 'T[][]) : 'T[] {
    return Fold(PlusA<'T>, new 'T[0], arrays);
}

This could also be implemented using a special case of FlatMapped:

function Flattened<'T>(arrays : 'T[][]): 'T[] {
  return FlatMapped(PlusA<'T>, arrays);
}
msoeken commented 4 years ago

I suggest to add a function Count with the following specification:

function Count<'T>(value : 'T, array : 'T[]) : Int {
  mutable count = 0;
  for (elem in array) {
    if (elem == value) {
      set count += 1;
    }
  }
  return count;
}

Currently I am implementing such a function using Filtered and type specific functions such as EqualI:

let integerCounts = Length(Filtered(EqualI(value, _), array));
cgranade commented 4 years ago

I suggest to add a function Count with the following specification:

Added to the draft API above, reflecting that not all 'T support equality by taking an explicit predicate.

msoeken commented 4 years ago

Added to the draft API above, reflecting that not all 'T support equality by taking an explicit predicate.

Thanks! That also explains the signature of Filtered, Where, and IndexOf, where I often expect a value instead of a predicate.

guenp commented 4 years ago

Perhaps this is out of scope for this discussion but I disagree with deprecating Zip. It can be a huge blocker to people who are new to Q# (and let's be honest, a large majority of our users are going to be new to Q# in the future :)) and have worked with other languages such as Python and are going to expect to be able to (keep) using Zip.

msoeken commented 4 years ago

I prefer Zipped for the sake of consistency, but agree that we should provide a solution for function names of commonly used functions that differ from the style guide, such as Zip, Fold, or Reduce. I suggest to have a discussion on how to best achieve this (solutions may include aliases, documentation, code hints, replacements in error messages for unknown identifiers, ...).

cgranade commented 4 years ago

Perhaps this is out of scope for this discussion but I disagree with deprecating Zip. It can be a huge blocker to people who are new to Q# (and let's be honest, a large majority of our users are going to be new to Q# in the future :)) and have worked with other languages such as Python and are going to expect to be able to (keep) using Zip.

While I totally agree with reducing confusion, I think it's important to keep in mind that Q# is its own language with its own design, geared towards making it easier to write quantum programs. For example, in order to support automatic adjointability and controllability, Q# has a strong separation between subroutines which are purely deterministic and cannot have side-effects (functions), and those that can have arbitrary side effects (operations). Operations cannot be used in all the same places that functions can, such that using names that reflect that feature helps make it easier understand the implications of functions-vs-operations.

From that perspective, I think it makes sense to identify some of the features that we can develop or expand upon to help users out as they learn Q#. As per your comments, @guenp and @msoeken, collecting some of the initial ideas:

The above notwithstanding, I'm wary of providing two distinct and equally valid functions for doing the same thing, though. That opens up a few more problems:

(On a not entirely serious side note, I think that's a large part of why Python's import this contains the following timeless wisdom: "There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch.")

In any case, given the above, my suggested action items are thus as follows:

msoeken commented 4 years ago

In any case, given the above, my suggested action items are thus as follows: ...

I second this suggestion.