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

Conversation

@christopherkang
Copy link
Contributor

@christopherkang christopherkang commented Aug 28, 2019

Draft! Adding the following ops:

  • ApplySeriesOfOps (and C/A/CA functor versions) - apply a list of ops and their targets
  • ApplyOpRepeatedlyOver (and C/A/CA functor versions) - apply a single op multiple times with different targets
  • PermuteQubits - uses ApplyOpRepeatedlyOver to SWAP over qubit array and permute their order.

Would like some input on a few things:

  • Do the operation signatures make sense? Are there operations that could be instead written as functions?
  • Is the Q# file in the appropriate place?
  • Anything I'm missing? :)

To-do:

  • Add unit tests
  • Finish docs
  • Finish C/A/CA functor versions of ApplySeriesOfOps

@msoeken msoeken self-assigned this Aug 28, 2019
@msoeken
Copy link
Member

msoeken commented Aug 28, 2019

Hi @christopherkang, thanks for opening this PR. I would expect a different signature from PermuteQubits, which takes as first input a permutation (Array with entries 0 to n-1, where n is the number of qubits) in the register array.

@christopherkang
Copy link
Contributor Author

@msoeken - good suggestion! What's the optimal sorting algorithm to be used?

@msoeken
Copy link
Member

msoeken commented Aug 28, 2019

@christopherkang It may be too time consuming to find the optimal decomposition into transpositions. But one simple technique is to apply transpositions to always move the largest element that is not yet in its position, until the identity is reached. Then you need at most n-1 transpositions, therefore n-1 SWAP gates.

@christopherkang
Copy link
Contributor Author

@msoeken is this achievable without mutating an array? It would be preferable to have this op as Adj+Ctl.

@cgranade
Copy link
Contributor

@christopherkang: One trick is to isolate mutability within a function, then call to that function from within an operation with is Adj + Ctl. There's a number of existing functions in Microsoft.Quantum.Arrays for just this reason, for instance.

@christopherkang
Copy link
Contributor Author

@cgranade I used that trick to implement the function. @msoeken I'll start working on the unit tests - do you have any suggestions on particular scenarios to use to test the functions? I'd appreciate input from you both on the additions made.

@msoeken
Copy link
Member

msoeken commented Aug 30, 2019

Hi @christopherkang, thanks for the additions. I have worked on a code for permutation synthesis some weeks ago, but it hasn't made it yet to the libraries. There is no need to have two functions that do the same thing, so I'd like to share my code with you as it may be helpful for your implementation.

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Microsoft.Quantum.Canon {
    open Microsoft.Quantum.Arrays;
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Diagnostics;
    open Microsoft.Quantum.Intrinsic;

    function _Equals(a : Int, b : Int) : Bool {
        return a == b;
    }

    function _NotEquals(a : Int, b : Int) : Bool {
        return a != b;
    }

    function _IsPermutationPred(permutation : Int[], value : Int) : Bool {
        let index = IndexOf(_Equals(value, _), permutation);
        return index != -1;
    }

    function _IsPermutation(permutation : Int[]) : Bool {
        return All(_IsPermutationPred(permutation, _), RangeAsIntArray(IndexRange(permutation)));
    }

    function _PermutationToTransposition(permutation : Int[]) : (Int, Int)[] {
        Fact(_IsPermutation(permutation), $"`permutation` is not a permutation");

        mutable preTrans = new (Int, Int)[Length(permutation) - 1];
        mutable p = permutation;

        for (i in Length(p) - 1..-1..1) {
            let j = IndexOf(_Equals(i, _), p);
            if (i != j) {
                set p w/= j <- p[i];
                set p w/= i <- i;
                set preTrans w/= Length(preTrans) - i <- (i, j);
            } else {
                set preTrans w/= Length(preTrans) - i <- (i, i);
            }
        }

        return Filtered(_NotEquals, preTrans);
    }

    /// # Summary
    /// Explicitly permutes qubits using SWAP gates subject to given
    /// permutation.
    ///
    /// # Input
    /// ## qs
    /// Array of qubits to permute.
    ///
    /// ## permutation
    /// Permutation of array `[0, 1, ..., n - 1]`, where `n - 1` is the length
    /// of array `qs`.
    ///
    /// # Remarks
    /// The lengths of `qs` and `permutation` must be equal.  Also `permutation`
    /// must be a correct permutation, i.e., it contains all elements from `0`
    /// to `n - 1` exactly once.
    operation PermuteQubits(qs : Qubit[], permutation : Int[]) : Unit is Adj + Ctl {
        // check that sizes match
        EqualityFactI(Length(qs), Length(permutation), $"Lengths of `qs` and `permutation` must be equal");

        for ((i, j) in _PermutationToTransposition(permutation)) {
            SWAP(qs[i], qs[j]);
        }
    }
}

@msoeken
Copy link
Member

msoeken commented Aug 30, 2019

Also note that functions such as ClaimEqualInt or _Equals and _NotEquals in your code are currently addressed in #152, so that PR can make the code a bit simpler, once it has been merged.

@christopherkang
Copy link
Contributor Author

@msoeken I updated my code with your suggestions. I've kept claims in for now - after Quantum.Logical gets pushed, I'll update the code with the new methods

Copy link
Contributor

@cgranade cgranade left a comment

Choose a reason for hiding this comment

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

I took a quick look over, and this is looking really good, thanks for the contribution! The main thing I'd like to iterate on would be the names for ApplySeriesOfOps and ApplyOpRepeatedlyOver. For the latter, I think ApplyToEachSubregister would fit well with the established naming conventions around ApplyToEach, ApplyToEachIndex, and ApplyToSubregister. For the former, I'd like to find a similar name that emphasizes the commonality with other ApplyToEach operations; my first inclination is something like ApplyEachToEachSubregister, but that isn't as readable as I'd like yet, sorry.

Anyway, I think this is a great start; once #152 comes in, and you've refactored to use those new functions, I this should be ready for a more detailed review. Thank you so much!

@msoeken msoeken self-requested a review September 3, 2019 16:55
Co-Authored-By: Chris Granade <cgranade@gmail.com>
Copy link
Member

@msoeken msoeken left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution! It's well organised but I have some comments for clarity, since many functions will go into the public API. This is in addition to @cgranade's comments. In particular we should wait for the other PR to reuse some of the helper functions and make this PR more concise.

@christopherkang
Copy link
Contributor Author

christopherkang commented Sep 4, 2019

Thanks, @msoeken and @cgranade - I appreciate the help! I've updated the code with the PR'd functions, added examples to the docs. Here's our remaining action items (alongside code review)

  • Naming convention for ApplySeriesOfOps and ApplyOpRepeatedlyOver (current suggestions from Chris are ApplyEachToEachSubregister and ApplyToEachSubregister)
  • Decide whether to rename or hide SwapOrderToPermuteArray

Let me know if I missed anything!

Copy link
Member

@msoeken msoeken left a comment

Choose a reason for hiding this comment

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

The code is really taking a great shape! There are some more comments to make it more concise.

@christopherkang
Copy link
Contributor Author

Thanks, @msoeken! I appreciate it 😃

I was ideating on potential names - what about ApplyEachToSubarrays (for different ops) and ApplyToSubarrays (for the same op). Open to suggestions!

@msoeken msoeken requested a review from cgranade September 22, 2019 17:20
@msoeken
Copy link
Member

msoeken commented Sep 22, 2019

@christopherkang Thanks for the last changes, all my comments have been addressed. I cannot comment much on the naming of the functions, @cgranade, could you please check whether the names of the new functions are okay.

Copy link
Contributor

@cgranade cgranade left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution, and for your patience! I think this looks really good, other than that I'd suggest renaming your type conversion function, and that I'd suggest either dropping Op or expanding Op to Operation. Marking as approved, as I'm happy to pick that up after merging that in if you'd like. Thank you so much for your contribution, excited to have this in!

@christopherkang
Copy link
Contributor Author

Thank you both! @cgranade I renamed the Array function, but wasn't sure what you meant by type conversion function. You're welcome to merge changes, once checks pass! I can also make those edits, I'll just need some clarification. Whatever's easier for you! 😄

@cgranade
Copy link
Contributor

My apologies for missing the GitHub notification about your comment, @christopherkang! Merging in now, thank you so much for your contribution. 💕

@cgranade cgranade merged commit 8ff7115 into microsoft:master Nov 22, 2019
@christopherkang
Copy link
Contributor Author

No worries @cgranade - are you aware of any areas that could be refactored with these operations? If so, I'll start working on a new PR

@cgranade
Copy link
Contributor

I think your most recent round addressed everything, @christopherkang, great to have your contribution on board for the next release! My apologies again for missing the notification.

cgranade pushed a commit that referenced this pull request Nov 22, 2019
* Drafted new apply ops

* Fixed docs

* Fixed minor bugs

* Added Permutation function + helper Arrays + Claim functions

* Added Adj + Ctl and set csproj back to generating docs

* Added tests

* Fixed test errors

* Updated code from comments; moved PermuteQubits to CommonGates

* Fixed minor bugs

* Apply suggestions from code review

Co-Authored-By: Chris Granade <cgranade@gmail.com>

* Added some fixes from changes

* Added most recommendations from Mathias

* Added example to ApplySeriesOfOps

* Added new examples

* Added PermuteQubits example

* Changed Swap Order to be appending to an array, added test for it

* Updated ApplyOpRepeatedlyOver Docs

* Added Mathias' comments

* Reverted csproj file

* Renamed TupleArrayAsNestedArray
@christopherkang
Copy link
Contributor Author

Awesome! Also, @cgranade, I mean do you know of any code in the wider Q# codebase that could make use of this operation?

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.

3 participants