Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9d10dec
Drafted new apply ops
christopherkang Aug 28, 2019
2e61df9
Fixed docs
christopherkang Aug 28, 2019
f76cf3e
Fixed minor bugs
christopherkang Aug 28, 2019
4efe0be
Merge branch 'master' into add_repeated_operation
Aug 28, 2019
ba39745
Added Permutation function + helper Arrays + Claim functions
christopherkang Aug 29, 2019
e2282b8
Added Adj + Ctl and set csproj back to generating docs
christopherkang Aug 29, 2019
8580eee
Added tests
christopherkang Aug 29, 2019
09f5435
Fixed test errors
christopherkang Aug 30, 2019
72c76bf
Updated code from comments; moved PermuteQubits to CommonGates
christopherkang Sep 2, 2019
9afaa71
Fixed minor bugs
christopherkang Sep 3, 2019
f305f58
Apply suggestions from code review
christopherkang Sep 3, 2019
781312d
Added some fixes from changes
christopherkang Sep 3, 2019
1e0d4a0
Merge branch 'master' into add_repeated_operation
christopherkang Sep 3, 2019
0172ccb
Added most recommendations from Mathias
christopherkang Sep 3, 2019
d7673ec
Added example to ApplySeriesOfOps
christopherkang Sep 3, 2019
b74e211
Added new examples
christopherkang Sep 3, 2019
58236ba
Added PermuteQubits example
christopherkang Sep 4, 2019
68e0da4
Changed Swap Order to be appending to an array, added test for it
christopherkang Sep 4, 2019
53ac666
Updated ApplyOpRepeatedlyOver Docs
christopherkang Sep 4, 2019
47d8838
Merge branch 'master' into add_repeated_operation
christopherkang Sep 4, 2019
cf53aca
Added Mathias' comments
christopherkang Sep 5, 2019
ec17ec3
Reverted csproj file
christopherkang Sep 22, 2019
4e75b08
Renamed TupleArrayAsNestedArray
christopherkang Sep 28, 2019
e74c4d9
Merge branch 'master' into add_repeated_operation
Nov 20, 2019
0c11100
Merge branch 'master' into add_repeated_operation
Nov 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 107 additions & 1 deletion Standard/src/Arrays/Arrays.qs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// Licensed under the MIT License.

namespace Microsoft.Quantum.Arrays {
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Logical;

/// # Summary
/// Create an array that contains the same elements as an input array but in Reversed
Expand Down Expand Up @@ -280,6 +283,109 @@ namespace Microsoft.Quantum.Arrays {
return output;
}

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

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

/// # Summary
/// Returns the order elements in an array need to be swapped to produce an ordered array.
/// Assumes swaps occur in place.
///
/// # Input
/// ## newOrder
/// Array with the permutation of the indices of the new array. There should be $n$ elements,
/// each being a unique integer from $0$ to $n-1$.
///
/// # Output
/// The tuple represents the two indices to be swapped. The swaps begin at the lowest index.
///
/// # Remarks
/// ## Example
/// ```qsharp
/// // The following returns [(0, 5),(0, 4),(0, 1),(0, 3)];
/// let swapOrder = _SwapOrderToPermuteArray([5, 3, 2, 0, 1, 4]);
/// ```
///
/// ## Psuedocode
/// for (index in 0..Length(newOrder) - 1)
/// {
/// while newOrder[index] != index
/// {
/// Switch newOrder[index] with newOrder[newOrder[index]]
/// }
/// }
function _SwapOrderToPermuteArray(newOrder : Int[]) : (Int, Int)[] {
// Check to verify the new ordering actually is a permutation of the indices
Fact(_IsPermutation(newOrder), $"The new ordering is not a permutation");

mutable swaps = new (Int, Int)[0];
mutable order = newOrder;

// for each value, whenever the index and value don't match, swap until it does
for (index in IndexRange(order)) {
while (not EqualI(order[index], index))
{
set swaps += [(index, order[index])];
set order = Swapped(order[index], index, order);
}
}

return swaps;
}

/// # Summary
/// Applies a swap of two elements in an array.
///
/// # Input
/// ## firstIndex
/// Index of the first element to be swapped.
///
/// ## secondIndex
/// Index of the second element to be swapped.
///
/// ## arr
/// Array with elements to be swapped.
///
/// # Output
/// The array with the in place swapp applied.
///
/// ## Example
/// ```qsharp
/// // The following returns [0, 3, 2, 1, 4]
/// Swapped(1, 3, [0, 1, 2, 3, 4]);
function Swapped<'T>(firstIndex: Int, secondIndex: Int, arr: 'T[]) : 'T[] {
return arr
w/ firstIndex <- arr[secondIndex]
w/ secondIndex <- arr[firstIndex];
}

/// # Summary
/// Turns a list of 2-tuples into a nested array.
///
/// # Input
/// ## tupleList
/// List of 2-tuples to be turned into a nested array.
///
/// # Output
/// A nested array with length matching the tupleList.
///
/// ## Example
/// ```qsharp
/// // The following returns [[2, 3], [4, 5]]
/// TupleArrayAsNestedArray([(2, 3), (4, 5)]);
/// ```
function TupleArrayAsNestedArray<'T>(tupleList : ('T, 'T)[]) : 'T[][] {
mutable newArray = new 'T[][Length(tupleList)];
for (idx in IndexRange(tupleList)) {
let (tupleLeft, tupleRight) = tupleList[idx];
set newArray w/= idx <- [tupleLeft, tupleRight];
}
return newArray;
}

}
256 changes: 256 additions & 0 deletions Standard/src/Canon/Combinators/ApplyRepeatedOver.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

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

///////////////////////////////////////////////////////////////////////////////////////////////
// Helpers to repeatedly apply operations over qubit arrays
///////////////////////////////////////////////////////////////////////////////////////////////

/// # Summary
/// Applies a list of ops and their targets sequentially on an array.
///
/// # Input
/// ## listOfOps
/// List of ops, each taking a 'T array, to be applied. They are applied sequentially, lowest index first.
/// ## targets
/// Nested arrays describing the targets of the op. Each array should contain a list of ints describing
/// the indices to be used.
/// ## register
/// Qubit register to be acted upon.
///
/// ## Example
/// // The following applies Exp([PauliX, PauliY], 0.5) to qubits 0, 1
/// // then X to qubit 2
/// let ops = [Exp([PauliX, PauliY], 0.5, _), ApplyToFirstQubit(X, _)];
/// let indices = [[0, 1], [2]];
/// ApplySeriesOfOps(ops, indices, qubitArray);
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyOpRepeatedlyOver
operation ApplySeriesOfOps<'T>(listOfOps : ('T[] => Unit)[], targets : Int[][], register : 'T[]) : Unit {
if (Length(listOfOps) != Length(targets)) {
fail "The number of ops and number of targets do not match!";
}
for ((op, targetIndices) in Zip(listOfOps, targets)) {
if (Length(targetIndices) > Length(register)) {
fail "There are too many targets!";
}
op(Subarray(targetIndices, register));
}
}

/// # Summary
/// Applies a list of ops and their targets sequentially on an array. (Adjoint)
///
/// # Input
/// ## listOfOps
/// List of ops, each taking a 'T array, to be applied. They are applied sequentially, lowest index first.
/// Each must have an adjoint functor
/// ## targets
/// Nested arrays describing the targets of the op. Each array should contain a list of ints describing
/// the indices to be used.
/// ## register
/// Qubit register to be acted upon.
///
/// ## Example
/// // The following applies Exp([PauliX, PauliY], 0.5) to qubits 0, 1
/// // then X to qubit 2
/// let ops = [Exp([PauliX, PauliY], 0.5, _), ApplyToFirstQubitA(X, _)];
/// let indices = [[0, 1], [2]];
/// ApplySeriesOfOpsA(ops, indices, qubitArray);
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyOpRepeatedlyOver
operation ApplySeriesOfOpsA<'T>(listOfOps : ('T[] => Unit is Adj)[], targets : Int[][], register : 'T[]) : Unit is Adj{
if (Length(listOfOps) != Length(targets)) {
fail "The number of ops and number of targets do not match!";
}
for ((op, targetIndices) in Zip(listOfOps, targets)) {
if (Length(targetIndices) > Length(register)) {
fail "There are too many targets!";
}
op(Subarray(targetIndices, register));
}
}

/// # Summary
/// Applies a list of ops and their targets sequentially on an array. (Controlled)
///
/// # Input
/// ## listOfOps
/// List of ops, each taking a 'T array, to be applied. They are applied sequentially, lowest index first.
/// Each must have a Controlled functor
/// ## targets
/// Nested arrays describing the targets of the op. Each array should contain a list of ints describing
/// the indices to be used.
/// ## register
/// Qubit register to be acted upon.
///
/// ## Example
/// // The following applies Exp([PauliX, PauliY], 0.5) to qubits 0, 1
/// // then X to qubit 2
/// let ops = [Exp([PauliX, PauliY], 0.5, _), ApplyToFirstQubitC(X, _)];
/// let indices = [[0, 1], [2]];
/// ApplySeriesOfOpsC(ops, indices, qubitArray);
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyOpRepeatedlyOver
operation ApplySeriesOfOpsC<'T>(listOfOps : ('T[] => Unit is Ctl)[], targets : Int[][], register : 'T[]) : Unit is Ctl{
if (Length(listOfOps) != Length(targets)) {
fail "The number of ops and number of targets do not match!";
}
for ((op, targetIndices) in Zip(listOfOps, targets)) {
if (Length(targetIndices) > Length(register)) {
fail "There are too many targets!";
}
op(Subarray(targetIndices, register));
}
}

/// # Summary
/// Applies a list of ops and their targets sequentially on an array. (Adjoint + Controlled)
///
/// # Input
/// ## listOfOps
/// List of ops, each taking a 'T array, to be applied. They are applied sequentially, lowest index first.
/// Each must have both an Adjoint and Controlled functor.
/// ## targets
/// Nested arrays describing the targets of the op. Each array should contain a list of ints describing
/// the indices to be used.
/// ## register
/// Qubit register to be acted upon.
///
/// ## Example
/// // The following applies Exp([PauliX, PauliY], 0.5) to qubits 0, 1
/// // then X to qubit 2
/// let ops = [Exp([PauliX, PauliY], 0.5, _), ApplyToFirstQubitCA(X, _)];
/// let indices = [[0, 1], [2]];
/// ApplySeriesOfOpsCA(ops, indices, qubitArray);
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyOpRepeatedlyOver
operation ApplySeriesOfOpsCA<'T>(listOfOps : ('T[] => Unit is Adj + Ctl)[], targets : Int[][], register : 'T[]) : Unit is Adj + Ctl{
if (Length(listOfOps) != Length(targets)) {
fail "The number of ops and number of targets do not match!";
}
for ((op, targetIndices) in Zip(listOfOps, targets)) {
if (Length(targetIndices) > Length(register)) {
fail "There are too many targets!";
}
op(Subarray(targetIndices, register));
}
}

/// # Summary
/// Applies the same op over a qubit register multiple times.
///
/// # Input
/// ## op
/// An operation to be applied multiple times on the qubit register
/// ## targets
/// Nested arrays describing the targets of the op. Each array should contain a list of ints describing
/// the qubits to be used.
/// ## register
/// Qubit register to be acted upon.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplySeriesOfOps
operation ApplyOpRepeatedlyOver(op : (Qubit[] => Unit), targets : Int[][], register : Qubit[]) : Unit
{
for (target in targets)
{
if (Length(target) > Length(register))
{
fail "Too many targets!";
}
let opTargets = Subarray(target, register);
op(opTargets);
}
}

/// # Summary
/// Applies the same op over a qubit register multiple times.
///
/// # Input
/// ## op
/// An operation to be applied multiple times on the qubit register
/// ## targets
/// Nested arrays describing the targets of the op. Each array should contain a list of ints describing
/// the qubits to be used.
/// ## register
/// Qubit register to be acted upon.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplySeriesOfOps
operation ApplyOpRepeatedlyOverA(op : (Qubit[] => Unit is Adj), targets : Int[][], register : Qubit[]) : Unit is Adj
{
for (target in targets)
{
if (Length(target) > Length(register))
{
fail "Too many targets!";
}
let opTargets = Subarray(target, register);
op(opTargets);
}
}

/// # Summary
/// Applies the same op over a qubit register multiple times.
///
/// # Input
/// ## op
/// An operation to be applied multiple times on the qubit register
/// ## targets
/// Nested arrays describing the targets of the op. Each array should contain a list of ints describing
/// the qubits to be used.
/// ## register
/// Qubit register to be acted upon.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplySeriesOfOps
operation ApplyOpRepeatedlyOverC(op : (Qubit[] => Unit is Ctl), targets : Int[][], register : Qubit[]) : Unit is Ctl
{
for (target in targets)
{
if (Length(target) > Length(register))
{
fail "Too many targets!";
}
let opTargets = Subarray(target, register);
op(opTargets);
}
}

/// # Summary
/// Applies the same op over a qubit register multiple times.
///
/// # Input
/// ## op
/// An operation to be applied multiple times on the qubit register
/// ## targets
/// Nested arrays describing the targets of the op. Each array should contain a list of ints describing
/// the qubits to be used.
/// ## register
/// Qubit register to be acted upon.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplySeriesOfOps
operation ApplyOpRepeatedlyOverCA(op : (Qubit[] => Unit is Adj+Ctl), targets : Int[][], register : Qubit[]) : Unit is Adj+Ctl
{
for (target in targets)
{
if (Length(target) > Length(register))
{
fail "Too many targets!";
}
let opTargets = Subarray(target, register);
op(opTargets);
}
}

}
Loading