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

Conversation

@cgranade
Copy link
Contributor

@cgranade cgranade commented Oct 29, 2020

This PR represents an initial version of a proposal for #39.

@cgranade cgranade marked this pull request as ready for review October 29, 2020 23:58
Copy link
Member

@vxfield vxfield left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added some questions

@bamarsha bamarsha linked an issue Nov 11, 2020 that may be closed by this pull request
4 tasks
@cgranade cgranade mentioned this pull request Nov 13, 2020
4 tasks
@bettinaheim
Copy link
Contributor

@cgranade One question: How can the dimensions of a multidimensional array be accessed?

@cgranade
Copy link
Contributor Author

@cgranade One question: How can the dimensions of a multidimensional array be accessed?

My thought was that this is the role of Shape2<'T> : 'T[,] -> (Int, Int), Shape3<'T> : 'T[,,] -> (Int, Int, Int), and so forth functions.

@cgranade
Copy link
Contributor Author

cgranade commented Feb 3, 2021

As per discussions offline, I'll go on and take the action items to:

  • Update this proposal to include five internal intrinsic functions that can allow for implementing functions and operations over multidimensional arrays as pure Q# code.
  • Split new library content included in this proposal to a new API design proposal on QuantumLibraries.

@bettinaheim
Copy link
Contributor

bettinaheim commented Feb 10, 2021

Copy-pasting some notes from exploring a syntax alternative for literals:

What should opening and closing delimiters be for inner levels of nesting?

  • [| and |] allow distinguishing opening and closing delimiters.
  • Can't reuse [| and |], but that's ok since we don't need another basic sequence type. [Edit BH: I wouldn't be so sure about that.]

Are spaces allowed between [ and |?

  • No, treat [| as a two-character token to disambiguate from ?...| and |||.
  • :: is precedent for having two-character tokens be distinct from single-character.

Do we use [|| for higher than 2D or nested [|?

  • No, implied by nesting, so [|| is unneeded.

What should be checked at compile time?

  • Siblings of [| all have same length. E.g.: [ [| 1, 2 |], [| 3, 4, 5 |] ] is bad, since 2 ≠ 3.
  • Cousins at the same depth have all have same length. E.g.: [ [| [| 1, 2 |], [| 3, 4 |] |], [| [| 5, 6, 7 |], [| 8, 9, 10 |] |] ] fails.
  • Both rules are checked going up until the next [] without bars (that is, [ ] break chains, and are self-contained, while [| |] are not independent expressions).

@bettinaheim
Copy link
Contributor

bettinaheim commented Feb 10, 2021

Further discussions on [| and |] vs simply | for inner items:

  • The | alone conflicts with ?|. Consider the example of [ | PauliZ |, | M(q) == One ? PauliI | PauliX | ].
    Counter argument: conditional expressions inside array literals without line breaks make it harder to read the literal in any case.
  • In 3+ dimensions it might be helpful to have a clear distinction of opening vs closing delimiter.
    A counter argument is that for literals for 3+ dimensions should be separated into multiple lines with proper indentation, which makes the open vs close distinction less relevant.
  • The difference between [[1,2], [3,4]] and [|1,2|, |3,4|] is harder to spot.
  • On the other hand [| can feel more clunky opposed to helpful, and makes it harder to spot where the whole array starts and ends, thinking also about what if we have array comprehension as well.

@vxfield
Copy link
Member

vxfield commented Feb 10, 2021

I'm not following this closely, so I'll just drop a raw idea here that you may have already considered (based on many other languages implementations).

  1. Allow arrays of arrays as usual, by nesting [ .. , .. ] constructs. Example:
    [ [1, 2, 3], [3, 4, 5] ]
  2. Have a Matrix<T> type that takes, in its constructor, the dimensions of the matrix. Example:
    let myMatrix = new Matrix<int>(2,3); // creates a 2x3 integer matrix
  3. The constructor of this Matrix type requires at least the size of the first dimension, but allows the user to pass an extra arbitrary number of dimensions. Example:
    public Matrix(int dim1size, int[] extraDimSizes = null)
  4. This Matrix type implements an interface to load data. This method is responsible to check that the input parameter dimensions matches the matrix's dimension. Example:
    myMatrix.Load([ [1, 2, 3], [3, 4, 5] ]); // succeeds
    myMatrix.Load([ [1, 2, 3], [3, 4] ]); // throws exception
  5. Add a syntactic sugar in the compiler to call the Load method together with the constructor:
    let myMatrix = new Matrix<int>(2,3)[ [1,2,3], [4,5,6] ];
    does the same as
    let myMatrix = new Matrix<int>(2,3);
    myMatrix.Load([ [1, 2, 3], [3, 4, 5] ]);
  6. If the compiler can resolve all the symbols at compilation time as constants, the compiler calls the Load method at compile-time, potentially letting the user know that they are trying to do something invalid. Otherwise leave it become a runtime error.

@bamarsha
Copy link
Contributor

bamarsha commented Feb 13, 2021

Can't reuse [| and |], but that's ok since we don't need another basic sequence type. [Edit BH: I wouldn't be so sure about that.]

I think [| |] is probably not practical as a separate sequence delimiter even if we use | | for multidimensional arrays, because of confusion like this:

// 2D array
[ |1, 2, 3| ]

// 2D array or new sequence literal?
[|1, 2, 3|]

So if we expect another type of sequence literal, I think we should plan for that to use delimiters other than [| |], or use neither [| |] nor | | for multidimensional arrays.

@bettinaheim
Copy link
Contributor

bettinaheim commented Feb 27, 2021

Copy-pasting the conclusions from our discussions today here:

  • literals: [|2,3|,|3,4|] as literals
  • types: [|Int|], with keeping both Int[] and [Int] valid for the 1D case
  • allow to omit () in item access; both arr[0, 1] is valid.
  • require () for index expression in copy-and-update as well as update-and-reassign
  • require [|0, size=(2, 3)|] for new array expressions.
  • modify library proposal to use "size" instead of "shape"

Very brief recap of the reasoning:
Having a type Int[,] gets pretty messy in how the type looks compared to how the item access behaves. The consistent notation would be to have Int[,][] in be an array of 2D arrays. Accessing an item in it then requires an indexing first into the outer and then the inner array: arr[0][0,1], switching the order according to the shoes-and-socks principle. E.g. C# deviates from that to align the two such that the type of an array of 2D arrays would be int[][,]. Going with [|Int|] by comparison like e.g. Rust is cleaner and matches the literal syntax. The literal syntax correspondingly should be [|1,2|, |3,4|] to match the [| |] of the type while keeping the type syntax clean (no additional [] as suggested previously for [ [|1,2|], [|3,4|] ]).

Copy link
Contributor

@bettinaheim bettinaheim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked in detail through the subsections under interactions with future modifications yet, and the section on alternatives and the comparison. Let's first close on the comments that I've added.

@bettinaheim bettinaheim changed the title QEP 3: 𝑛-d array proposal QEP 3: multidimensional array proposal Mar 5, 2021
Copy link
Contributor

@bettinaheim bettinaheim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @cgranade, for all the work!

@bettinaheim bettinaheim merged commit c86c7a6 into main Mar 8, 2021
@bettinaheim bettinaheim deleted the cgranade/ndarray branch March 8, 2021 19:01
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multidimensional arrays

6 participants