Various additions and improvements to Microsoft.Quantum.Arrays (#330)

This commit is contained in:
Mathias Soeken 2020-09-24 01:23:18 +02:00 коммит произвёл GitHub
Родитель fdd6b964c1
Коммит c4f69418a5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
45 изменённых файлов: 1937 добавлений и 117 удалений

Просмотреть файл

@ -10,7 +10,7 @@ namespace Microsoft.Quantum.Chemistry.JordanWigner {
open Microsoft.Quantum.Arrays;
/// # Summary
/// Computes Z component of Jordan–Wigner string between
/// Computes Z component of Jordan–Wigner string between
/// fermion indices in a fermionic operator with an even
/// number of creation / annihilation operators.
///
@ -89,7 +89,7 @@ namespace Microsoft.Quantum.Chemistry.JordanWigner {
let ops = [[PauliX, PauliY], [PauliY, PauliX]];
let signs = [+1.0, -1.0];
for ((op, sign) in Zip(ops, signs)) {
for ((op, sign) in Zipped(ops, signs)) {
let pauliString = _ComputeJordanWignerPauliString(Length(qubits), idxFermions, op);
Exp(pauliString, sign * angle, qubits);
}
@ -124,7 +124,7 @@ namespace Microsoft.Quantum.Chemistry.JordanWigner {
let ops = [[y,y,x,y],[x,x,x,y],[x,y,y,y],[y,x,y,y],[x,y,x,x],[y,x,x,x],[y,y,y,x],[x,x,y,x]];
let (sortedIndices, signs, globalSign) = _JordanWignerClusterOperatorPQRSTermSigns([p,q,r,s]);
for ((op, sign) in Zip(ops, signs)) {
for ((op, sign) in Zipped(ops, signs)) {
let pauliString = _ComputeJordanWignerPauliString(Length(qubits), sortedIndices, op);
Exp(pauliString, globalSign * sign * angle, qubits);
}
@ -272,4 +272,3 @@ namespace Microsoft.Quantum.Chemistry.JordanWigner {
}

Просмотреть файл

@ -8,7 +8,7 @@ namespace Microsoft.Quantum.Chemistry.JordanWigner {
open Microsoft.Quantum.Chemistry;
open Microsoft.Quantum.Arrays;
// This evolution set runs off data optimized for a Jordan–Wigner encoding.
// This evolution set runs off data optimized for a Jordan–Wigner encoding.
// This collects terms Z, ZZ, PQandPQQR, hpqrs separately.
// This only apples the needed hpqrs XXXX XXYY terms.
// Operations here are expressed in terms of Exp([...])
@ -134,7 +134,7 @@ namespace Microsoft.Quantum.Chemistry.JordanWigner {
if (idxFermions[0] < qubitQidx and qubitQidx < idxFermions[3]) {
let termPR1 = GeneratorIndex((idxTermType, [1.0]), [idxFermions[0], idxFermions[3] - 1]);
_ApplyJordanWignerPQTerm_(termPR1, angle, new Qubit[0], Exclude([qubitQidx], qubits));
_ApplyJordanWignerPQTerm_(termPR1, angle, new Qubit[0], Excluding([qubitQidx], qubits));
}
else {
let termPR1 = GeneratorIndex((idxTermType, [1.0]), [0, idxFermions[3] - idxFermions[0]]);
@ -280,4 +280,3 @@ namespace Microsoft.Quantum.Chemistry.JordanWigner {
}

Просмотреть файл

@ -39,7 +39,7 @@ namespace Microsoft.Quantum.Chemistry.JordanWigner.VQE {
mutable jwTermEnergy = 0.;
for ((coeff, op) in Zip(coeffs, ops)) {
for ((coeff, op) in Zipped(coeffs, ops)) {
// Only perform computation if the coefficient is significant enough
if (AbsD(coeff) >= 1e-10) {
// Compute expectation value using the fast frequency estimator, add contribution to Jordan-Wigner term energy
@ -95,7 +95,7 @@ namespace Microsoft.Quantum.Chemistry.JordanWigner.VQE {
mutable compactOp = compactOps[iOp];
mutable op = ConstantArray(nQubits, PauliI);
for ((idx, pauli) in Zip(indices, compactOp)) {
for ((idx, pauli) in Zipped(indices, compactOp)) {
set op w/= idx <- pauli;
}
for (i in indices[0]+1..indices[1]-1) {

Просмотреть файл

@ -6,7 +6,7 @@ namespace Microsoft.Quantum.MachineLearning {
open Microsoft.Quantum.Math;
function _AllNearlyEqualD(v1 : Double[], v2 : Double[]) : Bool {
return Length(v1) == Length(v2) and All(NearlyEqualD, Zip(v1, v2));
return Length(v1) == Length(v2) and All(NearlyEqualD, Zipped(v1, v2));
}
function _TailMeasurement(nQubits : Int) : (Qubit[] => Result) {

Просмотреть файл

@ -63,7 +63,7 @@ namespace Microsoft.Quantum.MachineLearning {
}
function _UncontrolledSpanSequence(idxsQubits : Int[]) : (Int, Int[])[] {
return Zip(
return Zipped(
idxsQubits,
ConstantArray(Length(idxsQubits), new Int[0])
);
@ -210,4 +210,4 @@ namespace Microsoft.Quantum.MachineLearning {
return combined;
}
}
}

Просмотреть файл

@ -160,9 +160,9 @@ namespace Microsoft.Quantum.MachineLearning {
// size of the step taken during the move. We can find this size
// as the squared norm of the gradient.
SquaredNorm(batchGradient),
// To actually apply the step, we can use Mapped(PlusD, Zip(...))
// To actually apply the step, we can use Mapped(PlusD, Zipped(...))
// to represent element-wise vector summation.
model w/ Parameters <- Mapped(PlusD, Zip(model::Parameters, batchGradient))
model w/ Parameters <- Mapped(PlusD, Zipped(model::Parameters, batchGradient))
);
}
@ -239,7 +239,7 @@ namespace Microsoft.Quantum.MachineLearning {
features, options::NMeasurements
);
let updatedBias = _UpdatedBias(
Zip(probabilities, actualLabels), model::Bias, options::Tolerance
Zipped(probabilities, actualLabels), model::Bias, options::Tolerance
);
let updatedLabels = InferredLabels(
updatedBias, probabilities
@ -330,7 +330,7 @@ namespace Microsoft.Quantum.MachineLearning {
);
// Find the best bias for the new classification parameters.
let localBias = _UpdatedBias(
Zip(probabilities, Sampled(validationSchedule, labels)),
Zipped(probabilities, Sampled(validationSchedule, labels)),
0.0,
options::Tolerance
);
@ -359,7 +359,7 @@ namespace Microsoft.Quantum.MachineLearning {
);
mutable bestSoFar = model
w/ Bias <- _UpdatedBias(
Zip(probabilities, actualLabels),
Zipped(probabilities, actualLabels),
model::Bias, options::Tolerance
);
let inferredLabels = InferredLabels(

Просмотреть файл

@ -27,7 +27,7 @@ namespace Microsoft.Quantum.MachineLearning {
: Int[] {
return Where(
NotEqualI,
Zip(inferredLabels, actualLabels)
Zipped(inferredLabels, actualLabels)
);
}

Просмотреть файл

@ -53,14 +53,14 @@ namespace Microsoft.Quantum.MachineLearning.Tests {
function EqualCR(x : ML.ControlledRotation, y : ML.ControlledRotation) : Bool {
return x::Axis == y::Axis and
All(EqualI, Zip(x::ControlIndices, y::ControlIndices)) and
All(EqualI, Zipped(x::ControlIndices, y::ControlIndices)) and
x::TargetIndex == y::TargetIndex and
x::ParameterIndex == y::ParameterIndex;
}
@Test("QuantumSimulator")
function LocalRotationsLayerFact() : Unit {
Fact(All(EqualCR, Zip(
Fact(All(EqualCR, Zipped(
ML.LocalRotationsLayer(3, PauliY),
[
Default<ML.ControlledRotation>()
@ -86,7 +86,7 @@ namespace Microsoft.Quantum.MachineLearning.Tests {
@Test("QuantumSimulator")
function PartialRotationsLayerFact() : Unit {
Fact(All(EqualCR, Zip(
Fact(All(EqualCR, Zipped(
ML.PartialRotationsLayer([4, 5, 6], PauliY),
[
Default<ML.ControlledRotation>()
@ -112,7 +112,7 @@ namespace Microsoft.Quantum.MachineLearning.Tests {
@Test("QuantumSimulator")
function CyclicEntanglingLayerFact() : Unit {
Fact(All(EqualCR, Zip(
Fact(All(EqualCR, Zipped(
ML.CyclicEntanglingLayer(3, PauliX, 2),
[
Default<ML.ControlledRotation>()
@ -160,7 +160,7 @@ namespace Microsoft.Quantum.MachineLearning.Tests {
w/ ParameterIndex <- 0
]
]);
Fact(All(EqualCR, Zip(
Fact(All(EqualCR, Zipped(
combined,
[
Default<ML.ControlledRotation>()

Просмотреть файл

@ -43,7 +43,7 @@ namespace Microsoft.Quantum.Arithmetic {
MultiplySI(xsInt, ysInt, tmpResultInt);
(Controlled ApplyToEachCA)(controls,
(CNOT,
Zip(tmpResult[n-px..2*n-px-1], zs)));
Zipped(tmpResult[n-px..2*n-px-1], zs)));
(Adjoint MultiplySI)(xsInt, ysInt, tmpResultInt);
}
}
@ -77,7 +77,7 @@ namespace Microsoft.Quantum.Arithmetic {
SquareSI(xsInt, tmpResultInt);
(Controlled ApplyToEachCA)(controls,
(CNOT,
Zip(tmpResult[n-px..2*n-px-1], ys)));
Zipped(tmpResult[n-px..2*n-px-1], ys)));
(Adjoint SquareSI)(xsInt, tmpResultInt);
}
}

Просмотреть файл

@ -32,7 +32,7 @@ namespace Microsoft.Quantum.Arithmetic {
([sign], SignedLittleEndian(LittleEndian(xs)));
ComputeReciprocalI(LittleEndian(xs), LittleEndian(tmpRes));
(Controlled ApplyToEachCA)(controls,
(CNOT, Zip(tmpRes[p+pRes-1+n-Length(rs)..Min([n+p+pRes, 2*n-1])], rs)));
(CNOT, Zipped(tmpRes[p+pRes-1+n-Length(rs)..Min([n+p+pRes, 2*n-1])], rs)));
(Controlled Invert2sSI)([sign], SignedLittleEndian(LittleEndian(rs)));
(Adjoint ComputeReciprocalI)(LittleEndian(xs), LittleEndian(tmpRes));
(Controlled Adjoint Invert2sSI)

Просмотреть файл

@ -57,7 +57,7 @@ namespace Microsoft.Quantum.AmplitudeAmplification {
systemRegister : Qubit[]
)
: Unit is Adj + Ctl {
for ((startPhase, targetPhase) in Zip(phases!)) {
for ((startPhase, targetPhase) in Zipped(phases!)) {
if (startPhase != 0.0) {
startStateReflection::ApplyReflection(
startPhase, auxiliaryRegister

Просмотреть файл

@ -28,7 +28,7 @@ namespace Microsoft.Quantum.Arithmetic {
: Unit is Adj + Ctl {
ApplyToEachCA(
CControlledCA(X),
Zip(IntAsBoolArray(value, Length(target!)), target!)
Zipped(IntAsBoolArray(value, Length(target!)), target!)
);
}

Просмотреть файл

@ -182,7 +182,7 @@ namespace Microsoft.Quantum.Arithmetic {
CCNOT(xs![nQubits - 2], ys![nQubits - 1], carry);
ApplyToEachCA(X, Most(Rest(ys!))); // X on ys[1..(nQubits-2)]
CNOT(ancilla, ys![1]) ;
ApplyToEachCA(CNOT, Zip(Rest(Most(xs!)), Rest(Rest(ys!))));
ApplyToEachCA(CNOT, Zipped(Rest(Most(xs!)), Rest(Rest(ys!))));
}
/// # Summary
@ -222,7 +222,7 @@ namespace Microsoft.Quantum.Arithmetic {
using (auxiliary = Qubit()) {
within {
ApplyToEachCA(CNOT, Zip(Rest(xs!), Rest(ys!)));
ApplyToEachCA(CNOT, Zipped(Rest(xs!), Rest(ys!)));
CNOT(xs![1], auxiliary);
CCNOT(xs![0], ys![0], auxiliary);
ApplyOuterCDKMAdder(xs, ys, auxiliary);
@ -309,7 +309,7 @@ namespace Microsoft.Quantum.Arithmetic {
"Input registers must have the same number of qubits."
);
ApplyToEachCA(CNOT, Zip(Rest(xs!), Rest(ys!)));
ApplyToEachCA(CNOT, Zipped(Rest(xs!), Rest(ys!)));
Adjoint ApplyCNOTChain(Rest(xs!));
}
@ -492,7 +492,7 @@ namespace Microsoft.Quantum.Arithmetic {
else {
within {
ApplyToEachCA(X, ys!);
ApplyToEachCA(CNOT, Zip(Rest(xs!), Rest(ys!)));
ApplyToEachCA(CNOT, Zipped(Rest(xs!), Rest(ys!)));
} apply {
within {
(Adjoint ApplyCNOTChain) (Rest(xs!));

Просмотреть файл

@ -245,7 +245,7 @@ namespace Microsoft.Quantum.Arithmetic {
MultiplyAndAddByModularInteger(constMultiplier, modulus, multiplier, summandLE);
// now the joint state is |x⟩|x⋅a(mod N)⟩
ApplyToEachCA(SWAP, Zip(summandLE!, multiplier!));
ApplyToEachCA(SWAP, Zipped(summandLE!, multiplier!));
// now the joint state is |x⋅a(mod N)⟩|x⟩
let inverseMod = InverseModI(constMultiplier, modulus);

Просмотреть файл

@ -31,7 +31,7 @@ namespace Microsoft.Quantum.Arithmetic {
// of X instructions that flip all the zeros in our index.
ApplyToEachCA(
CControlledCA(X),
Zip(Mapped(Not, IntAsBoolArray(index, Length(reg!))), reg!)
Zipped(Mapped(Not, IntAsBoolArray(index, Length(reg!))), reg!)
);
} apply {
Controlled Z(Most(reg!), Tail(reg!));

Просмотреть файл

@ -63,10 +63,6 @@ namespace Microsoft.Quantum.Arrays {
return array[0 .. Length(array) - 2];
}
internal function Lookup<'T> (array : 'T[], index : Int) : 'T {
return array[index];
}
/// # Summary
/// Given an array, returns a function which returns elements of that
/// array.
@ -90,7 +86,7 @@ namespace Microsoft.Quantum.Arrays {
/// where functions are used to avoid the need to record an entire array
/// in memory.
function LookupFunction<'T> (array : 'T[]) : (Int -> 'T) {
return Lookup(array, _);
return ElementAt(_, array);
}
/// # Summary
@ -129,6 +125,40 @@ namespace Microsoft.Quantum.Arrays {
return array[0];
}
/// # Summary
/// Returns a tuple of first and all remaining elements of the array.
///
/// # Type Parameters
/// ## 'A
/// The type of the array elements.
///
/// # Input
/// ## array
/// An array with at least one element.
///
/// # Output
/// A tuple of first and all remaining elements of the array.
function HeadAndRest<'A>(array : 'A[]) : ('A, 'A[]) {
return (Head(array), Rest(array));
}
/// # Summary
/// Returns a tuple of all but one and the last element of the array.
///
/// # Type Parameters
/// ## 'A
/// The type of the array elements.
///
/// # Input
/// ## array
/// An array with at least one element.
///
/// # Output
/// A tuple of all but one and the last element of the array.
function MostAndTail<'A>(array : 'A[]) : ('A[], 'A) {
return (Most(array), Tail(array));
}
/// # Summary
/// Creates an array of given length with all elements equal to given value.
///
@ -182,9 +212,9 @@ namespace Microsoft.Quantum.Arrays {
/// ```qsharp
/// let array = [10, 11, 12, 13, 14, 15];
/// // The following line returns [10, 12, 15].
/// let subarray = Exclude([1, 3, 4], array);
/// let subarray = Excluding([1, 3, 4], array);
/// ```
function Exclude<'T> (remove : Int[], array : 'T[]) : 'T[] {
function Excluding<'T>(remove : Int[], array : 'T[]) : 'T[] {
let nSliced = Length(remove);
let nElements = Length(array);

Просмотреть файл

@ -0,0 +1,151 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
open Microsoft.Quantum.Arithmetic;
open Microsoft.Quantum.Logical;
/// # Summary
/// Given two arrays, returns a new array of pairs such that each pair
/// contains an element from each original array.
///
/// # Type Parameters
/// ## 'T
/// The type of the left array elements.
/// ## 'U
/// The type of the right array elements.
///
/// # Input
/// ## left
/// An array containing values for the first element of each tuple.
/// ## right
/// An array containing values for the second element of each tuple.
///
/// # Output
/// An array containing pairs of the form `(left[idx], right[idx])` for
/// each `idx`. If the two arrays are not of equal length, the output will
/// be as long as the shorter of the inputs.
///
/// # Remarks
/// ## Example
/// ```qsharp
/// let left = [1, 3, 71];
/// let right = [false, true];
/// let pairs = Zip(left, right); // [(1, false), (3, true)]
/// ```
///
/// # See Also
/// - Zip3
/// - Zip4
/// - Unzipped
@Deprecated("Microsoft.Quantum.Arrays.Zipped")
function Zip<'T, 'U> (left : 'T[], right : 'U[]) : ('T, 'U)[] {
return Zipped(left, right);
}
/// # Summary
/// Given three arrays, returns a new array of 3-tuples such that each 3-tuple
/// contains an element from each original array.
///
/// # Type Parameters
/// ## 'T1
/// The type of the first array elements.
/// ## 'T2
/// The type of the second array elements.
/// ## 'T3
/// The type of the third array elements.
///
/// # Input
/// ## first
/// An array containing values for the first element of each tuple.
/// ## second
/// An array containing values for the second element of each tuple.
/// ## third
/// An array containing values for the third element of each tuple.
///
/// # Output
/// An array containing 3-tuples of the form `(first[idx], second[idx], third[idx])` for
/// each `idx`. If the three arrays are not of equal length, the output will
/// be as long as the shorter of the inputs.
///
/// # See Also
/// - Zip
/// - Zip4
@Deprecated("Microsoft.Quantum.Arrays.Zipped3")
function Zip3<'T1, 'T2, 'T3> (first : 'T1[], second : 'T2[], third : 'T3[]) : ('T1, 'T2, 'T3)[] {
return Zipped3(first, second, third);
}
/// # Summary
/// Given four arrays, returns a new array of 4-tuples such that each 4-tuple
/// contains an element from each original array.
///
/// # Type Parameters
/// ## 'T1
/// The type of the first array elements.
/// ## 'T2
/// The type of the second array elements.
/// ## 'T3
/// The type of the third array elements.
/// ## 'T4
/// The type of the fourth array elements.
///
/// # Input
/// ## first
/// An array containing values for the first element of each tuple.
/// ## second
/// An array containing values for the second element of each tuple.
/// ## third
/// An array containing values for the third element of each tuple.
/// ## fourth
/// An array containing values for the fourth element of each tuple.
///
/// # Output
/// An array containing 4-tuples of the form `(first[idx], second[idx], third[idx], fourth[idx])` for
/// each `idx`. If the four arrays are not of equal length, the output will
/// be as long as the shorter of the inputs.
///
/// # See Also
/// - Zip
/// - Zip3
@Deprecated("Microsoft.Quantum.Arrays.Zipped4")
function Zip4<'T1, 'T2, 'T3, 'T4> (first : 'T1[], second : 'T2[], third : 'T3[], fourth : 'T4[]) : ('T1, 'T2, 'T3, 'T4)[] {
return Zipped4(first, second, third, fourth);
}
/// # Summary
/// Returns an array containing the elements of another array,
/// excluding elements at a given list of indices.
///
/// # Type Parameters
/// ## 'T
/// The type of the array elements.
///
/// # Input
/// ## remove
/// An array of indices denoting which elements should be excluded
/// from the output.
/// ## array
/// Array of which the values in the output array are taken.
///
/// # Output
/// An array `output` such that `output[0]` is the first element
/// of `array` whose index does not appear in `remove`,
/// such that `output[1]` is the second such element, and so
/// forth.
///
/// # Remarks
/// ## Example
/// ```qsharp
/// let array = [10, 11, 12, 13, 14, 15];
/// // The following line returns [10, 12, 15].
/// let subarray = Exclude([1, 3, 4], array);
/// ```
function Exclude<'T>(remove : Int[], array : 'T[]) : 'T[] {
return Excluding(remove, array);
}
}

Просмотреть файл

@ -51,7 +51,7 @@ namespace Microsoft.Quantum.Arrays {
if (Length(array1) != Length(array2)) {
return false;
}
return All(equal, Zip(array1, array2));
return All(equal, Zipped(array1, array2));
}
}

Просмотреть файл

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
@ -40,7 +40,7 @@ namespace Microsoft.Quantum.Arrays {
/// }
/// ```
/// The outcome one should expect from this example will be an array of numbers greater than 5.
function Filtered<'T> (predicate : ('T -> Bool), array : 'T[]) : 'T[] {
function Filtered<'T>(predicate : ('T -> Bool), array : 'T[]) : 'T[] {
mutable totalFound = 0;
mutable idxArray = new Int[Length(array)];
@ -80,4 +80,45 @@ namespace Microsoft.Quantum.Arrays {
);
}
/// # Summary
/// Given an array and a predicate that is defined
/// for the elements of the array, returns the number of elements
/// an array that consists of those elements that satisfy the predicate.
///
/// # Remarks
/// The function is defined for generic types, i.e., whenever we have
/// an array `'T[]` and a predicate `'T -> Bool` we can filter elements.
///
/// # Type Parameters
/// ## 'T
/// The type of `array` elements.
///
/// # Input
/// ## predicate
/// A function from `'T` to Boolean that is used to filter elements.
/// ## array
/// An array of elements over `'T`.
///
/// # Output
/// The number of elements in `array` that satisfy the predicate.
///
/// # Example
/// The following code demonstrates the "Count" function.
/// A predicate is defined using the @"microsoft.quantum.logical.greaterthani" function:
/// ```Q#
/// let predicate = GreaterThanI(_, 5);
/// let count = Count(predicate, [2, 5, 9, 1, 8]);
/// // count = 2
/// ```
function Count<'T>(predicate : ('T -> Bool), array : 'T[]) : Int {
mutable totalFound = 0;
for (element in array) {
if (predicate(element)) {
set totalFound += 1;
}
}
return totalFound;
}
}

Просмотреть файл

@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
open Microsoft.Quantum.Diagnostics;
/// # Summary
/// Interleaves two arrays of (almost) same size.
///
/// # Description
/// This function returns the interleaving of two arrays, starting
/// with the first element from the first array, then the first
/// element from the second array, and so on.
///
/// The first array must either be
/// of the same length as the second one, or can have one more element.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `first` and `second`.
///
/// # Input
/// ## first
/// The first array to be interleaved.
///
/// ## second
/// The second array to be interleaved.
///
/// # Output
/// Interleaved array
///
/// # Example
/// ```Q#
/// // same as int1 = [1, -1, 2, -2, 3, -3]
/// let int1 = Interleaved([1, 2, 3], [-1, -2, -3])
///
/// // same as int2 = [false, true, false, true, false]
/// let int2 = Interleaved(ConstantArray(3, false), ConstantArray(2, true));
/// ```
function Interleaved<'T>(first : 'T[], second : 'T[]) : 'T[] {
let lFirst = Length(first);
let lSecond = Length(second);
Fact(lFirst >= lSecond and lFirst - lSecond <= 1, "Array `first` is either of same size as `second`, or has one more element");
return new 'T[lFirst + lSecond]
w/ 0..2..(lFirst + lSecond - 1) <- first
w/ 1..2..(lFirst + lSecond - 1) <- second;
}
}

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
open Microsoft.Quantum.Math;
/// # Summary
/// Given an array and a function that is defined
@ -86,6 +87,109 @@ namespace Microsoft.Quantum.Arrays {
return resultArray;
}
/// # Summary
/// Given a range and a function that takes an integer as input,
/// returns a new array that consists
/// of the images of the range values under the function.
///
/// # Remarks
/// The function is defined for generic types, i.e., whenever we have
/// a function `mapper: Int -> 'T` we can map the values
/// of the range and produce an array of type `'T[]`.
///
/// # Type Parameters
/// ## 'T
/// The result type of the `mapper` function.
///
/// # Input
/// ## mapper
/// A function from `Int` to `'T` that is used to map range values.
/// ## range
/// A range of integers.
///
/// # Output
/// An array `'T[]` of elements that are mapped by the `mapper` function.
///
/// # Example
/// This example adds 1 to a range of even numbers:
/// ```Q#
/// let numbers = MappedOverRange(PlusI(1, _), 0..2..10);
/// // numbers = [1, 3, 5, 7, 9, 11]
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Arrays.Mapped
function MappedOverRange<'T> (mapper : (Int -> 'T), range : Range) : 'T[] {
let start = RangeStart(range);
let step = RangeStep(range);
let end = RangeEnd(range);
if ((end - start) / step >= 0) {
let nTerms = (end - start) / step + 1;
mutable resultArray = new 'T[nTerms];
mutable idxElement = 0;
for (elem in range) {
set resultArray w/= idxElement <- mapper(elem);
set idxElement += 1;
}
return resultArray;
} else {
return new 'T[0];
}
}
/// # Summary
/// Given an array and a function that maps an array element to some output
/// array, returns the concatenated output arrays for each array element.
///
/// # Type Parameters
/// ## 'TInput
/// The type of `array` elements.
/// ## 'TOutput
/// The `mapper` function returns arrays of this type.
///
/// # Input
/// ## mapper
/// A function from `'TInput` to `'TOutput[]` that is used to map array elements.
/// ## array
/// An array of elements.
///
/// # Output
/// An array of `'TOutput[]` which is the concatenation of all arrays generated by
/// the mapping function.
///
/// # Example
/// ```Q#
/// let Numbers = SequenceI(1, _); // generates numbers starting from 1
/// let values = FlatMapped(Numbers, [1, 2, 3]);
/// // values = [1, 1, 2, 1, 2, 3]
/// ```
function FlatMapped<'TInput, 'TOutput>(mapper : ('TInput -> 'TOutput[]), array : 'TInput[]) : 'TOutput[] {
return Fold(PlusA<'TOutput>, new 'TOutput[0], Mapped(mapper, array));
}
/// # Summary
/// Given an array of arrays, returns the concatenation of all arrays.
///
/// # Type Parameters
/// ## 'T
/// The type of `array` elements.
///
/// # Input
/// ## arrays
/// Array of arrays.
///
/// # Output
/// Concatenation of all arrays.
///
/// # Example
/// ```Q#
/// let flattened = Flattened([[1, 2], [3], [4, 5, 6]]);
/// // flattened = [1, 2, 3, 4, 5, 6]
/// ```
function Flattened<'T>(arrays : 'T[][]): 'T[] {
return Fold(PlusA<'T>, new 'T[0], arrays);
}
/// # Summary
/// Given an array and an operation that is defined
/// for the elements of the array, returns a new array that consists

Просмотреть файл

@ -0,0 +1,276 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Logical;
open Microsoft.Quantum.Math;
/// # Summary
/// Returns the transpose of a matrix represented as an array
/// of arrays.
///
/// # Description
/// Input as an $r \times c$ matrix with $r$ rows and $c$ columns. The matrix
/// is row-based, i.e., `matrix[i][j]` accesses the element at row $i$ and column $j$.
///
/// This function returns the $c \times r$ matrix that is the transpose of the
/// input matrix.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `matrix`.
///
/// # Input
/// ## matrix
/// Row-based $r \times c$ matrix
///
/// # Output
/// Transposed $c \times r$ matrix
///
/// # Example
/// ```Q#
/// // same as [[1, 4], [2, 5], [3, 6]]
/// let transposed = Transposed([[1, 2, 3], [4, 5, 6]]);
/// ```
function Transposed<'T>(matrix : 'T[][]) : 'T[][] {
let numRows = Length(matrix);
Fact(numRows > 0, "Matrix must have at least 1 row");
let numColumns = Length(Head(matrix));
Fact(numColumns > 0, "Matrix must have at least 1 column");
RectangularArrayFact(matrix, "Matrix is not a rectangular array");
return Mapped(ColumnAtUnchecked(_, matrix), SequenceI(0, numColumns - 1));
}
/// # Summary
/// Returns the at the given index of an array.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `array`.
///
/// # Input
/// ## index
/// Index of element
/// ## array
/// The array being indexed.
///
/// # Remark
/// This function is more general than `LookupFunction`, since
/// it can also be used for partial application on a fixed index.
/// Note that the type parameter must explicitly be provided in
/// this case as it cannot be deduced automatically.
///
/// # Example
/// Get the third number in four famous integer sequences. (note
/// that the 0 index corresponds to the _first_ value of the sequence.)
/// ```Q#
/// let lucas = [2, 1, 3, 4, 7, 11, 18, 29, 47, 76];
/// let prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
/// let fibonacci = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34];
/// let catalan = [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862];
/// let famous2 = Mapped(ElementAt<Int>(2, _), [lucas, prime, fibonacci, catalan]);
/// // same as: famous2 = [3, 5, 1, 2]
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Arrays.LookupFunction
/// - Microsoft.Quantum.Arrays.ElementsAt
function ElementAt<'T>(index : Int, array : 'T[]) : 'T {
Fact(index >= 0 and index < Length(array), "Index is out of bound");
return array[index];
}
/// # Summary
/// Returns the array's elements at a given range
/// of indices.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `array`.
///
/// # Input
/// ## range
/// Range of array indexes
/// ## array
/// Array
///
/// # Example
/// Get the odd indexes in famous integer sequences. (note
/// that the 0 index corresponds to the _first_ value of the sequence.)
/// ```Q#
/// let lucas = [2, 1, 3, 4, 7, 11, 18, 29, 47, 76];
/// let prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
/// let fibonacci = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34];
/// let catalan = [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862];
/// let famousOdd = Mapped(ElementsAt<Int>(0..2..9, _), [lucas, prime, fibonacci, catalan]);
/// // same as: famousOdd = [[2, 3, 7, 18, 47], [2, 5, 11, 17, 23], [0, 1, 3, 8, 21], [1, 2, 14, 132, 1430]]
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Arrays.ElementAt
/// - Microsoft.Quantum.Arrays.LookupFunction
function ElementsAt<'T>(range : Range, array : 'T[]) : 'T[] {
return array[range];
}
/// # Summary
/// Extracts a column from a matrix.
///
/// # Description
/// This function extracts a column in a matrix in row-wise order.
/// Extracting a row corrsponds to element access of the first index
/// and therefore requires no further treatment.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `matrix`.
///
/// # Input
/// ## column
/// Column of the matrix
/// ## matrix
/// 2-dimensional matrix in row-wise order
///
/// # Example
/// ```Q#
/// let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
/// let column = ColumnAt(0, matrix);
/// // same as: column = [1, 4, 7]
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Arrays.Transposed
/// - Microsoft.Quantum.Arrays.Diagonal
function ColumnAt<'T>(column : Int, matrix : 'T[][]) : 'T[] {
RectangularArrayFact(matrix, "Matrix is not a rectangular array");
return ColumnAtUnchecked(column, matrix);
}
/// # Summary
/// This function does not check for matrix shape
///
/// # Description
/// This function can be used in other multidimensional functions,
/// which already check the input matrix for a valid rectangular shape.
internal function ColumnAtUnchecked<'T>(column : Int, matrix : 'T[][]) : 'T[] {
return Mapped(
Compose(
ElementAt<'T>(column, _),
LookupFunction(matrix)
), RangeAsIntArray(IndexRange(matrix)));
}
/// # Summary
/// Returns an array of diagonal elements of a 2-dimensional array
///
/// # Description
/// If the 2-dimensional array has not a square shape, the diagonal over
/// the minimum over the number of rows and columns will be returned.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `matrix`.
///
/// # Input
/// ## matrix
/// 2-dimensional matrix in row-wise order
///
/// # Example
/// ```Q#
/// let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
/// let diagonal = Diagonal(matrix);
/// // same as: column = [1, 5, 9]
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Arrays.Transposed
function Diagonal<'T>(matrix : 'T[][]) : 'T[] {
RectangularArrayFact(matrix, "Matrix is not a rectangular array");
let numRows = Length(matrix);
let numColumns = numRows == 0 ? 0 | Length(Head(matrix));
return MappedOverRange(ElementAtDiagonal(_, matrix), 0..(MinI(numRows, numColumns) - 1));
}
internal function ElementAtDiagonal<'T>(index : Int, matrix : 'T[][]) : 'T {
return matrix[index][index];
}
/// # Summary
/// Represents a condition that a 2-dimensional array has a rectangular shape
///
/// # Description
/// This function asserts that each row in an array has the same length.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `array`.
///
/// # Input
/// ## array
/// A 2-dimensional array of elements
/// ## message
/// A message to be printed if the array is not a rectangular array
///
/// # Example
/// ```Q#
/// RectangularArrayFact([[1, 2], [3, 4]], "Array is not rectangular"); // okay
/// RectangularArrayFact([[1, 2, 3], [4, 5, 6]], "Array is not rectangular"); // okay
/// RectangularArrayFact([[1, 2], [3, 4, 5]], "Array is not rectangular"); // will fail
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Arrays.SquareArrayFact
function RectangularArrayFact<'T>(array : 'T[][], message : String) : Unit {
if (Length(array) == 0) {
return ();
} else {
let numColumns = Length(Head(array));
if (Any(Compose(NotEqualI(numColumns, _), Length<'T>), Rest(array))) {
fail message;
}
}
}
/// # Summary
/// Represents a condition that a 2-dimensional array has a square shape
///
/// # Description
/// This function asserts that each row in an array has
/// as many elements as there are rows (elements) in the array.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `array`.
///
/// # Input
/// ## array
/// A 2-dimensional array of elements
/// ## message
/// A message to be printed if the array is not a square array
///
/// # Example
/// ```Q#
/// SquareArrayFact([[1, 2], [3, 4]], "Array is not a square"); // okay
/// SquareArrayFact([[1, 2, 3], [4, 5, 6]], "Array is not a square"); // will fail
/// SquareArrayFact([[1, 2], [3, 4, 5]], "Array is not a square"); // will fail
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Arrays.RectangularArrayFact
function SquareArrayFact<'T>(array : 'T[][], message : String) : Unit {
if (Length(array) == 0) {
return ();
} else {
let numColumns = Length(array);
if (Any(Compose(NotEqualI(numColumns, _), Length<'T>), array)) {
fail message;
}
}
}
}

Просмотреть файл

@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
/// # Summary
/// Combines Mapped and Fold into a single function
///
/// # Description
/// This function iterates the `fn` function through the array, starting from
/// an initial state `state` and returns all intermediate values, not including
/// the inital state.
///
/// # Type Parameters
/// ## 'State
/// The type of states that the `fn` function operates on, i.e., accepts as its first
/// input and returns.
/// ## 'T
/// The type of `array` elements.
///
/// # Input
/// ## fn
/// A function to be folded over the array
///
/// ## state
/// The initial state to be folded
///
/// ## array
/// An array of values to be folded over
///
/// # Output
/// All intermediate states, including the final state, but not the initial state.
/// The length of the output array is of the same length as `array`.
///
/// # Remark
/// This function generalizes `Fold` since
/// `Tail(CumulativeFolded(fn, state, array))` is the same as `Fold(fn, state, array)`.
///
/// # Example
/// ```Q#
/// // same as sums = [1, 3, 6, 10, 15]
/// let sums = CumulativeFolded(PlusI, 0, SequenceI(1, 5));
/// ```
function CumulativeFolded<'State, 'T>(fn : (('State, 'T) -> 'State), state : 'State, array : 'T[]) : 'State[] {
mutable current = state;
mutable result = new 'State[Length(array)];
for ((i, elem) in Enumerated(array)) {
set current = fn(current, elem);
set result w/= i <- current;
}
return result;
}
}

Просмотреть файл

@ -0,0 +1,134 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
/// # Summary
/// Given two sorted arrays, returns a single array containing the
/// elements of both in sorted order. Used internally by merge sort.
internal function Merged<'T>(comparison : (('T, 'T) -> Bool), left : 'T[], right : 'T[]) : 'T[] {
mutable result = new 'T[0];
mutable l = left;
mutable r = right;
while ((not IsEmpty(l)) and (not IsEmpty(r))) {
if (comparison(Head(l), Head(r))) {
set result += [Head(l)];
set l = Rest(l);
} else {
set result += [Head(r)];
set r = Rest(r);
}
}
// Note that at this point, either or both of l and r are empty,
// such that we can simply append both to our result to get the
// whole merged array.
return result + l + r;
}
/// # Summary
/// Given an array, returns whether that array is sorted as defined by
/// a given comparison function.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `array`.
///
/// # Input
/// ## comparison
/// A function that compares two elements such that `a` is considered to
/// be less than or equal to `b` if `comparison(a, b)` is `true`.
/// ## array
/// The array to be checked.
///
/// # Output
/// `true` if and only if for each pair of elements `a` and `b` of
/// `array` occuring in that order, `comparison(a, b)` is `true`.
///
/// # Remarks
/// The function `comparison` is assumed to be transitive, such that
/// if `comparison(a, b)` and `comparison(b, c)`, then `comparison(a, c)`
/// is assumed. If this property does not hold, then the output of this
/// function may be incorrect.
function IsSorted<'T>(comparison : (('T, 'T) -> Bool), array : 'T[]) : Bool {
return All(
comparison,
Zipped(Most(array), Rest(array))
);
}
/// # Summary
/// Given an array, returns the elements of that array sorted by a given
/// comparison function.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `array`.
///
/// # Input
/// ## comparison
/// A function that compares two elements such that `a` is considered to
/// be less than or equal to `b` if `comparison(a, b)` is `true`.
/// ## array
/// The array to be sorted.
///
/// # Ouput
/// An array containing the same elements as `array`, such that for all
/// elements `a` occuring earlier than elements `b`, `comparison(a, b)`
/// is `true`.
///
/// # Example
/// The following snippet sorts an array of integers to occur in ascending
/// order:
/// ```Q#
/// let sortedArray = Sorted(LessThanOrEqualI, [3, 17, 11, -201, -11]);
/// ```
///
/// # Remarks
/// The function `comparison` is assumed to be transitive, such that
/// if `comparison(a, b)` and `comparison(b, c)`, then `comparison(a, c)`
/// is assumed. If this property does not hold, then the output of this
/// function may be incorrect.
///
/// As this is a function, the results are completely determinstic, even
/// when two elements are considered equal under `comparison`;
/// that is, when `comparison(a, b)` and `comparison(b, a)` are both `true`.
/// In particular, the sort performed by this function is guaranteed to be
/// stable, so that if two elements `a` and `b` occur in that order within
/// `array` and are considered equal under `comparison`, then `a` will also
/// appear before `b` in the output.
///
/// For example:
/// ```Q#
/// function LastDigitLessThanOrEqual(left : Int, right : Int) : Bool {
/// return LessThanOrEqualI(
/// left % 10, right % 10
/// );
/// }
///
/// function SortedByLastDigit() : Int[] {
/// return Sorted(LastDigitLessThanOrEqual, [3, 37, 11, 17]);
/// }
/// // returns [11, 3, 37, 17].
/// ```
function Sorted<'T>(comparison : (('T, 'T) -> Bool), array : 'T[]) : 'T[] {
if (Length(array) <= 1) {
return array;
} else {
let idxPivot = Length(array) / 2;
let left = array[...idxPivot - 1];
let right = array[idxPivot...];
// Sort each sublist, then merge them back into a single combined
// list and return.
return Merged<'T>(
comparison,
Sorted(comparison, left),
Sorted(comparison, right)
);
}
}
}

Просмотреть файл

@ -0,0 +1,59 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
/// # Summary
/// Returns a new array that has no equal adjacent elements.
///
/// # Description
/// Given some array of elements and a function to test equality, this
/// function returns a new array in which the relative order of elements
/// is kept, but all adjacent elements which are equal are filtered to
/// just a single element.
///
/// # Type Parameters
/// ## 'T
/// The type of each element of `array`.
///
/// # Input
/// ## equal
/// A function that compares two elements such that `a` is considered to
/// be equal to `b` if `equal(a, b)` is `true`.
/// ## array
/// The array to be filtered for unique elements.
///
/// # Output
/// Array with no equal adjacent elements.
///
/// # Remarks
/// If there are multiple elements that are equal but not next to each other,
/// there will be multiple occurrences in the output array. Use this function
/// together with `Sorted` to get an array with overall unique elements.
///
/// # Example
/// ```Q#
/// let unique1 = Unique(EqualI, [1, 1, 3, 3, 2, 5, 5, 5, 7]);
/// // same as [1, 3, 2, 5, 7]
/// let unique2 = Unique(EqualI, [2, 2, 1, 1, 2, 2, 1, 1]);
/// // same as [2, 1, 2, 1];
/// let unique3 = Unique(EqualI, Sorted(LessThanOrEqualI, [2, 2, 1, 1, 2, 2, 1, 1]));
/// // same as [1, 2];
/// ```
function Unique<'T>(equal : (('T, 'T) -> Bool), array : 'T[]) : 'T[] {
if (Length(array) == 0) {
return new 'T[0];
}
mutable unique = ConstantArray(Length(array), Head(array));
mutable count = 1;
for (elem in Rest(array)) {
if (not equal(elem, unique[count - 1])) {
set unique w/= count <- elem;
set count += 1;
}
}
return unique[0..count - 1];
}
}

Просмотреть файл

@ -0,0 +1,76 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
/// # Summary
/// Returns all consecutive subarrays of length `size`.
///
/// # Description
/// This function returns all `n - size + 1` subarrays of
/// length `size` in order, where `n` is the length of `arr`.
/// The first subarrays are `arr[0..size - 1], arr[1..size], arr[2..size + 1]`
/// until the last subarray `arr[n - size..n - 1]`.
///
/// If `size <= 0` or `size > n`, an empty array is returned.
///
/// # Type Parameters
/// ## 'T
/// The type of `array` elements.
///
/// # Input
/// ## size
/// Length of the subarrays.
///
/// ## array
/// An array of elements.
///
/// # Example
/// ```Q#
/// // same as [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
/// let windows = Windows(3, [1, 2, 3, 4, 5]);
/// ```
function Windows<'T>(size : Int, array : 'T[]) : 'T[][] {
let n = Length(array);
if (size <= 0 or size > n) {
return new 'T[][0];
}
mutable result = new 'T[][n + 1 - size];
for (i in 0..n - size) {
set result w/= i <- array[i..i + size - 1];
}
return result;
}
/// # Summary
/// Given an array, returns all its prefixes.
///
/// # Description
/// Returns an array of all prefixes, starting with an array that only
/// has the first element until the complete array.
///
/// # Type Parameters
/// ## 'T
/// The type of `array` elements.
///
/// # Input
/// ## array
/// An array of elements.
///
/// # Example
/// ```Q#
/// let prefixes = Prefixes([23, 42, 144]);
/// // prefixes = [[23], [23, 42], [23, 42, 144]]
/// ```
function Prefixes<'T>(array : 'T[]) : 'T[][] {
return MappedOverRange(Prefix(_, array), IndexRange(array));
}
internal function Prefix<'T>(to : Int, array : 'T[]) : 'T[] {
return array[0..to];
}
}

Просмотреть файл

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
@ -30,13 +30,14 @@ namespace Microsoft.Quantum.Arrays {
/// ```qsharp
/// let left = [1, 3, 71];
/// let right = [false, true];
/// let pairs = Zip(left, right); // [(1, false), (3, true)]
/// let pairs = Zipped(left, right); // [(1, false), (3, true)]
/// ```
///
/// # See Also
/// - Zip3
/// - Zip4
function Zip<'T, 'U> (left : 'T[], right : 'U[]) : ('T, 'U)[] {
/// - Microsoft.Quantum.Arrays.Zipped3
/// - Microsoft.Quantum.Arrays.Zipped4
/// - Microsoft.Quantum.Arrays.Unzipped
function Zipped<'T, 'U>(left : 'T[], right : 'U[]) : ('T, 'U)[] {
let nElements = Length(left) < Length(right)
? Length(left)
| Length(right);
@ -75,9 +76,9 @@ namespace Microsoft.Quantum.Arrays {
/// be as long as the shorter of the inputs.
///
/// # See Also
/// - Zip
/// - Zip4
function Zip3<'T1, 'T2, 'T3> (first : 'T1[], second : 'T2[], third : 'T3[]) : ('T1, 'T2, 'T3)[] {
/// - Microsoft.Quantum.Arrays.Zipped
/// - Microsoft.Quantum.Arrays.Zipped4
function Zipped3<'T1, 'T2, 'T3> (first : 'T1[], second : 'T2[], third : 'T3[]) : ('T1, 'T2, 'T3)[] {
let nElements = Min([Length(first), Length(second), Length(third)]);
mutable output = new ('T1, 'T2, 'T3)[nElements];
@ -118,9 +119,9 @@ namespace Microsoft.Quantum.Arrays {
/// be as long as the shorter of the inputs.
///
/// # See Also
/// - Zip
/// - Zip3
function Zip4<'T1, 'T2, 'T3, 'T4> (first : 'T1[], second : 'T2[], third : 'T3[], fourth : 'T4[]) : ('T1, 'T2, 'T3, 'T4)[] {
/// - Microsoft.Quantum.Arrays.Zipped
/// - Microsoft.Quantum.Arrays.Zipped3
function Zipped4<'T1, 'T2, 'T3, 'T4> (first : 'T1[], second : 'T2[], third : 'T3[], fourth : 'T4[]) : ('T1, 'T2, 'T3, 'T4)[] {
let nElements = Min([Length(first), Length(second), Length(third), Length(fourth)]);
mutable output = new ('T1, 'T2, 'T3, 'T4)[nElements];
@ -131,6 +132,46 @@ namespace Microsoft.Quantum.Arrays {
return output;
}
/// # Summary
/// Given an array of 2-tuples, returns a tuple of two arrays, each containing
/// the elements of the tuples of the input array.
///
/// # Type Parameters
/// ## 'T
/// The type of the first element in each tuple
/// ## 'U
/// The type of the second element in each tuple
///
/// # Input
/// ## arr
/// An array containing 2-tuples
///
/// # Output
/// Two arrays, the first one containing all first elements of the input
/// tuples, the second one containing all second elements of the input tuples.
///
/// # Example
/// ```Q#
/// // split is same as ([6, 5, 5, 3, 2, 1], [true, false, false, false, true, false])
/// let split = Unzipped([(6, true), (5, false), (5, false), (3, false), (2, true), (1, false)]);
/// ```
///
/// # Remark
/// This function is equivalent to `(Mapped(Fst<'T, 'U>, arr), Mapped(Snd<'T, 'U>, arr))`.
///
/// # See Also
/// - Microsoft.Quantum.Arrays.Zipped
function Unzipped<'T, 'U>(arr : ('T, 'U)[]) : ('T[], 'U[]) {
let nElements = Length(arr);
mutable first = new 'T[nElements];
mutable second = new 'U[nElements];
for (idxElement in 0 .. nElements - 1) {
let (left, right) = arr[idxElement];
set first w/= idxElement <- left;
set second w/= idxElement <- right;
}
return (first, second);
}
}

Просмотреть файл

@ -167,7 +167,7 @@ namespace Microsoft.Quantum.Canon {
if (i % 2 == 0) {
set j = 0;
} else {
let e = Zip(current, RangeAsIntArray(0..N - 1));
let e = Zipped(current, RangeAsIntArray(0..N - 1));
set j = Snd(Head(Filtered(Fst<Bool, Int>, e))) + 1;
}

Просмотреть файл

@ -34,7 +34,7 @@ namespace Microsoft.Quantum.Canon {
/// ```Q#
/// let bitstring = [true, false, true];
/// using (register = Qubit(3)) {
/// ApplyToEach(ApplyIf(X, _, _), Zip(bitstring, register));
/// ApplyToEach(ApplyIf(X, _, _), Zipped(bitstring, register));
/// // register should now be in the state |101⟩.
/// ...
/// }
@ -77,7 +77,7 @@ namespace Microsoft.Quantum.Canon {
/// ```Q#
/// let bitstring = [true, false, true];
/// using (register = Qubit(3)) {
/// ApplyToEach(ApplyIf(X, _, _), Zip(bitstring, register));
/// ApplyToEach(ApplyIf(X, _, _), Zipped(bitstring, register));
/// // register should now be in the state |101⟩.
/// ...
/// }
@ -120,7 +120,7 @@ namespace Microsoft.Quantum.Canon {
/// ```Q#
/// let bitstring = [true, false, true];
/// using (register = Qubit(3)) {
/// ApplyToEach(ApplyIf(X, _, _), Zip(bitstring, register));
/// ApplyToEach(ApplyIf(X, _, _), Zipped(bitstring, register));
/// // register should now be in the state |101⟩.
/// ...
/// }
@ -164,7 +164,7 @@ namespace Microsoft.Quantum.Canon {
/// ```Q#
/// let bitstring = [true, false, true];
/// using (register = Qubit(3)) {
/// ApplyToEach(ApplyIf(X, _, _), Zip(bitstring, register));
/// ApplyToEach(ApplyIf(X, _, _), Zipped(bitstring, register));
/// // register should now be in the state |101⟩.
/// ...
/// }

Просмотреть файл

@ -35,7 +35,7 @@ namespace Microsoft.Quantum.Canon {
if (Length(listOfOps) != Length(targets)) {
fail "The number of ops and number of targets do not match!";
}
for ((op, targetIndices) in Zip(listOfOps, targets)) {
for ((op, targetIndices) in Zipped(listOfOps, targets)) {
if (Length(targetIndices) > Length(register)) {
fail "There are too many targets!";
}
@ -69,7 +69,7 @@ namespace Microsoft.Quantum.Canon {
if (Length(listOfOps) != Length(targets)) {
fail "The number of ops and number of targets do not match!";
}
for ((op, targetIndices) in Zip(listOfOps, targets)) {
for ((op, targetIndices) in Zipped(listOfOps, targets)) {
if (Length(targetIndices) > Length(register)) {
fail "There are too many targets!";
}
@ -103,7 +103,7 @@ namespace Microsoft.Quantum.Canon {
if (Length(listOfOps) != Length(targets)) {
fail "The number of ops and number of targets do not match!";
}
for ((op, targetIndices) in Zip(listOfOps, targets)) {
for ((op, targetIndices) in Zipped(listOfOps, targets)) {
if (Length(targetIndices) > Length(register)) {
fail "There are too many targets!";
}
@ -137,7 +137,7 @@ namespace Microsoft.Quantum.Canon {
if (Length(listOfOps) != Length(targets)) {
fail "The number of ops and number of targets do not match!";
}
for ((op, targetIndices) in Zip(listOfOps, targets)) {
for ((op, targetIndices) in Zipped(listOfOps, targets)) {
if (Length(targetIndices) > Length(register)) {
fail "There are too many targets!";
}

Просмотреть файл

@ -0,0 +1,434 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Canon {
open Microsoft.Quantum.Arrays;
/// # Summary
/// Applies an operation to the first element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Head(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which the first will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # Example
/// The following Q# snippets are equivalent:
/// ```Q#
/// ApplyToHead(H, register);
/// H(Head(register));
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToHeadA
/// - Microsoft.Quantum.Canon.ApplyToHeadC
/// - Microsoft.Quantum.Canon.ApplyToHeadCA
operation ApplyToHead<'T>(op : ('T => Unit), targets : 'T[]) : Unit {
op(Head(targets));
}
/// # Summary
/// Applies an operation to the first element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Head(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which the first will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToHead
/// - Microsoft.Quantum.Canon.ApplyToHeadC
/// - Microsoft.Quantum.Canon.ApplyToHeadCA
operation ApplyToHeadA<'T>(op : ('T => Unit is Adj), targets : 'T[]) : Unit is Adj {
op(Head(targets));
}
/// # Summary
/// Applies an operation to the first element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Head(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which the first will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToHead
/// - Microsoft.Quantum.Canon.ApplyToHeadA
/// - Microsoft.Quantum.Canon.ApplyToHeadCA
operation ApplyToHeadC<'T>(op : ('T => Unit is Ctl), targets : 'T[]) : Unit is Ctl {
op(Head(targets));
}
/// # Summary
/// Applies an operation to the first element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Head(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which the first will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToHead
/// - Microsoft.Quantum.Canon.ApplyToHeadA
/// - Microsoft.Quantum.Canon.ApplyToHeadC
operation ApplyToHeadCA<'T>(op : ('T => Unit is Adj+Ctl), targets : 'T[]) : Unit is Adj+Ctl {
op(Head(targets));
}
/// # Summary
/// Applies an operation to all but the first element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Rest(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which all but the first will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # Example
/// The following Q# snippets are equivalent:
/// ```Q#
/// ApplyToRest(ApplyCNOTChain, register);
/// ApplyCNOTChain(Rest(register));
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToRestA
/// - Microsoft.Quantum.Canon.ApplyToRestC
/// - Microsoft.Quantum.Canon.ApplyToRestCA
operation ApplyToRest<'T>(op : ('T[] => Unit), targets : 'T[]) : Unit {
op(Rest(targets));
}
/// # Summary
/// Applies an operation to all but the first element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Rest(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which all but the first will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToRest
/// - Microsoft.Quantum.Canon.ApplyToRestC
/// - Microsoft.Quantum.Canon.ApplyToRestCA
operation ApplyToRestA<'T>(op : ('T[] => Unit is Adj), targets : 'T[]) : Unit is Adj {
op(Rest(targets));
}
/// # Summary
/// Applies an operation to all but the first element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Rest(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which all but the first will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToRest
/// - Microsoft.Quantum.Canon.ApplyToRestA
/// - Microsoft.Quantum.Canon.ApplyToRestCA
operation ApplyToRestC<'T>(op : ('T[] => Unit is Ctl), targets : 'T[]) : Unit is Ctl {
op(Rest(targets));
}
/// # Summary
/// Applies an operation to all but the first element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Rest(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which all but the first will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToRest
/// - Microsoft.Quantum.Canon.ApplyToRestA
/// - Microsoft.Quantum.Canon.ApplyToRestC
operation ApplyToRestCA<'T>(op : ('T[] => Unit is Adj+Ctl), targets : 'T[]) : Unit is Adj+Ctl {
op(Rest(targets));
}
/// # Summary
/// Applies an operation to the last element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Tail(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which the last will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # Example
/// The following Q# snippets are equivalent:
/// ```Q#
/// ApplyToTail(H, register);
/// H(Tail(register));
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToTailA
/// - Microsoft.Quantum.Canon.ApplyToTailC
/// - Microsoft.Quantum.Canon.ApplyToTailCA
operation ApplyToTail<'T>(op : ('T => Unit), targets : 'T[]) : Unit {
op(Tail(targets));
}
/// # Summary
/// Applies an operation to the last element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Tail(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which the last will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToTail
/// - Microsoft.Quantum.Canon.ApplyToTailC
/// - Microsoft.Quantum.Canon.ApplyToTailCA
operation ApplyToTailA<'T>(op : ('T => Unit is Adj), targets : 'T[]) : Unit is Adj {
op(Tail(targets));
}
/// # Summary
/// Applies an operation to the last element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Tail(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which the last will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToTail
/// - Microsoft.Quantum.Canon.ApplyToTailA
/// - Microsoft.Quantum.Canon.ApplyToTailCA
operation ApplyToTailC<'T>(op : ('T => Unit is Ctl), targets : 'T[]) : Unit is Ctl {
op(Tail(targets));
}
/// # Summary
/// Applies an operation to the last element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Tail(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which the last will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToTail
/// - Microsoft.Quantum.Canon.ApplyToTailA
/// - Microsoft.Quantum.Canon.ApplyToTailC
operation ApplyToTailCA<'T>(op : ('T => Unit is Adj+Ctl), targets : 'T[]) : Unit is Adj+Ctl {
op(Tail(targets));
}
/// # Summary
/// Applies an operation to all but the last element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Most(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which all but the last will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # Example
/// The following Q# snippets are equivalent:
/// ```Q#
/// ApplyToMost(ApplyCNOTChain, register);
/// ApplyCNOTChain(Most(register));
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToMostA
/// - Microsoft.Quantum.Canon.ApplyToMostC
/// - Microsoft.Quantum.Canon.ApplyToMostCA
operation ApplyToMost<'T>(op : ('T[] => Unit), targets : 'T[]) : Unit {
op(Most(targets));
}
/// # Summary
/// Applies an operation to all but the last element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Most(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which all but the last will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToMost
/// - Microsoft.Quantum.Canon.ApplyToMostC
/// - Microsoft.Quantum.Canon.ApplyToMostCA
operation ApplyToMostA<'T>(op : ('T[] => Unit is Adj), targets : 'T[]) : Unit is Adj {
op(Most(targets));
}
/// # Summary
/// Applies an operation to all but the last element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Most(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which all but the last will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToMost
/// - Microsoft.Quantum.Canon.ApplyToMostA
/// - Microsoft.Quantum.Canon.ApplyToMostCA
operation ApplyToMostC<'T>(op : ('T[] => Unit is Ctl), targets : 'T[]) : Unit is Ctl {
op(Most(targets));
}
/// # Summary
/// Applies an operation to all but the last element of an array.
///
/// # Description
/// Given an operation `op` and an array of targets `targets`,
/// applies `op(Most(targets))`.
///
/// # Input
/// ## op
/// An operation to be applied.
/// ## target
/// An array of targets, of which all but the last will be applied to `op`.
///
/// # Type Parameters
/// ## 'T
/// The input type of the operation to be applied.
///
/// # See Also
/// - Microsoft.Quantum.Canon.ApplyToMost
/// - Microsoft.Quantum.Canon.ApplyToMostA
/// - Microsoft.Quantum.Canon.ApplyToMostC
operation ApplyToMostCA<'T>(op : ('T[] => Unit is Adj+Ctl), targets : 'T[]) : Unit is Adj+Ctl {
op(Most(targets));
}
}

Просмотреть файл

@ -23,7 +23,7 @@ namespace Microsoft.Quantum.Canon {
/// ## qubits
/// Array of qubits whose parity is to be computed and stored.
operation ApplyCNOTChain(qubits : Qubit[]) : Unit is Adj + Ctl {
ApplyToEachCA(CNOT, Zip(Most(qubits), Rest(qubits)));
ApplyToEachCA(CNOT, Zipped(Most(qubits), Rest(qubits)));
}
/// # Summary

Просмотреть файл

@ -206,7 +206,7 @@ namespace Microsoft.Quantum.Characterization {
} apply {
preparation1(target1);
preparation2(target2);
ApplyToEachCA(Controlled SWAP([control], _), Zip(target1, target2));
ApplyToEachCA(Controlled SWAP([control], _), Zipped(target1, target2));
}
}

Просмотреть файл

@ -207,7 +207,7 @@ namespace Microsoft.Quantum.Diagnostics {
FormattedFailure(actual, expected, message);
}
Ignore(Mapped(EqualityFactB(_, _, message), Zip(actual, expected)));
Ignore(Mapped(EqualityFactB(_, _, message), Zipped(actual, expected)));
}
/// # Summary
@ -229,7 +229,7 @@ namespace Microsoft.Quantum.Diagnostics {
FormattedFailure(actual, expected, message);
}
Ignore(Mapped(EqualityFactI(_, _, message), Zip(actual, expected)));
Ignore(Mapped(EqualityFactI(_, _, message), Zipped(actual, expected)));
}
}

Просмотреть файл

@ -0,0 +1,85 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Logical {
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
/// # Summary
/// Given a comparison function, returns a new function that
/// lexographically compares two arrays.
///
/// # Type Parameters
/// ## 'T
/// The type of the elements of the arrays being compared.
///
/// # Input
/// ## elementComparison
/// A function that compares two elements `x` and `y` and returns if
/// `x` is less than or equal to `y`.
///
/// # Output
/// A function that compares two arrays `xs` and `ys` and returns if
/// `xs` occurs before or equal to `ys` in lexographical ordering.
///
/// # Remarks
/// The lexographic comparison between two arrays `xs` and `ys` is defined
/// by the following procedure. We say that two elements `x` and `y`
/// are equivalent if `elementComparison(x, y)` and `elementComparison(y, x)`
/// are both true.
///
/// - Both arrays are compared element-by-element until the first pair of
/// elements that are not equivalent. The array containing the element
/// that occurs first according to `elementComparison` is said to occur
/// first in lexographical ordering.
/// - If no inequivalent elements are found, and one array is longer than
/// the other, the shorter array is said to occur first.
///
/// # Examples
/// ```Q#
/// let arrayComparison = LexographicComparison(LessThanOrEqualD);
/// let data = [
/// [1.1, 2.2, 3.3],
/// [1.1, 2.2],
/// [0.2, 2.2],
/// [1.1, 2.7]
/// ];
/// let sorted = Sorted(arrayComparison, data);
/// // sorted:
/// // [
/// // [0.2, 2.2],
/// // [1.1, 2.2],
/// // [1.1, 2.2, 3.3],
/// // [1.1, 2.7]
/// // ];
/// ```
///
/// # See Also
/// - Microsoft.Quantum.Arrays.Sorted
function LexographicComparison<'T>(elementComparison : (('T, 'T) -> Bool)) : (('T[], 'T[]) -> Bool) {
return LessThanLexographic(elementComparison, _, _);
}
/// # Summary
/// Used to implement `LexographicComparison`.
internal function LessThanLexographic<'T>(comparison : (('T, 'T) -> Bool), left : 'T[], right : 'T[]) : Bool {
for ((l, r) in Zipped(left, right)) {
let lessThanOrEqual = comparison(l, r);
let greaterThanOrEqual = comparison(r, l);
let equal = lessThanOrEqual and greaterThanOrEqual;
if (lessThanOrEqual and not equal) {
return true;
} elif (greaterThanOrEqual and not equal) {
return false;
}
}
// At this point, all items in the common prefix of both arrays
// are equal to each other under comparison (l ≤ r and r ≤ l).
// Thus, if left is shorter than or equal to right, then left occurs
// at or before right in lexographical ordering.
return Length(left) <= Length(right);
}
}

Просмотреть файл

@ -22,7 +22,7 @@ namespace Microsoft.Quantum.Preparation {
fail $"Left and right registers must be the same length.";
}
for ((leftQubit, rightQubit) in Zip(left, right)) {
for ((leftQubit, rightQubit) in Zipped(left, right)) {
H(leftQubit);
Controlled X([leftQubit], rightQubit);
}

Просмотреть файл

@ -279,7 +279,7 @@ namespace Microsoft.Quantum.Synthesis {
let register = qubits!;
for ((func, target) in TruthTablesFromPermutation(perm, variableOrder)) {
ApplyXControlledOnTruthTable(func, Exclude([target], register), register[target]);
ApplyXControlledOnTruthTable(func, Excluding([target], register), register[target]);
}
}
}

Просмотреть файл

@ -54,11 +54,11 @@ namespace Microsoft.Quantum.Synthesis {
within {
for (target in Most(diff)) {
(BitControlledX(bbits[...target - 1] + abits[target + 1...]))(Exclude([target], qs), qs[target]);
(BitControlledX(bbits[...target - 1] + abits[target + 1...]))(Excluding([target], qs), qs[target]);
}
} apply {
let target = Tail(diff);
(BitControlledX(bbits[...target - 1] + abits[target + 1...]))(Exclude([target], qs), qs[target]);
(BitControlledX(bbits[...target - 1] + abits[target + 1...]))(Excluding([target], qs), qs[target]);
}
}
}

Просмотреть файл

@ -1,18 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Tests {
open Microsoft.Quantum.Logical;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Logical;
open Microsoft.Quantum.Math;
@Test("QuantumSimulator")
function ZipTest() : Unit {
function TestZipped() : Unit {
let left = [1, 2, 101];
let right = [PauliY, PauliI];
let zipped = Zip(left, right);
let zipped = Zipped(left, right);
let (leftActual1, rightActual1) = zipped[0];
if (leftActual1 != 1 or rightActual1 != PauliY) {
@ -26,9 +27,19 @@ namespace Microsoft.Quantum.Tests {
}
}
@Test("QuantumSimulator")
function TestUnzipped() : Unit {
let first = [6, 5, 5, 3, 2, 1];
let second = [true, false, false, false, true, false];
let (first2, second2) = Unzipped(Zipped(first, second));
AllEqualityFactI(first2, first, "Unexpected array of integers");
AllEqualityFactB(second2, second, "Unexpected array of Booleans");
}
@Test("QuantumSimulator")
function LookupTest () : Unit {
function TestLookup() : Unit {
let array = [1, 12, 71, 103];
let fn = LookupFunction(array);
@ -41,21 +52,21 @@ namespace Microsoft.Quantum.Tests {
}
internal function AllEqualI(expected : Int[], actual : Int[]) : Bool {
return All(EqualI, Zip(expected, actual));
return All(EqualI, Zipped(expected, actual));
}
@Test("QuantumSimulator")
function ChunksTest() : Unit {
function TestChunks() : Unit {
let data = [10, 11, 12, 13, 14, 15];
// 2 × 3 case.
Fact(All(AllEqualI, Zip(
Fact(All(AllEqualI, Zipped(
[[10, 11], [12, 13], [14, 15]],
Chunks(2, data)
)), "Wrong chunks in 2x3 case.");
// Case with some leftovers.
Fact(All(AllEqualI, Zip(
Fact(All(AllEqualI, Zipped(
[[10, 11, 12, 13], [14, 15]],
Chunks(4, data)
)), "Wrong chunks in case with leftover elements.");
@ -65,13 +76,15 @@ namespace Microsoft.Quantum.Tests {
return x * x;
}
function ConstantArrayTest () : Unit {
@Test("QuantumSimulator")
function ConstantArrayOfDoublesIsCorrect() : Unit {
let dblArray = ConstantArray(71, 2.17);
EqualityFactI(Length(dblArray), 71, $"ConstantArray(Int, Double) had the wrong length.");
let ignore = Mapped(NearEqualityFactD(_, 2.17), dblArray);
}
@Test("QuantumSimulator")
function ConstantArrayOfFunctionsIsCorrect() : Unit {
// Stress test by making an array of Int -> Int.
let fnArray = ConstantArray(7, Squared);
EqualityFactI(Length(fnArray), 7, $"ConstantArray(Int, Int -> Int) had the wrong length.");
@ -80,36 +93,40 @@ namespace Microsoft.Quantum.Tests {
function SubarrayTest () : Unit {
let array0 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let subarrayOdd = Subarray([1, 3, 5, 7, 9], array0);
let subarrayEven = Subarray([0, 2, 4, 6, 8, 10], array0);
Fact(All(IsEven, subarrayEven), $"the even elements of [1..10] were not correctly sliced.");
Fact(not Any(IsEven, subarrayOdd), $"the odd elements of [1..10] were not correctly sliced.");
let array1 = [10, 11, 12, 13];
Ignore(Mapped(EqualityFactI(_, _, $"Subarray failed: subpermutation case."), Zip([12, 11], Subarray([2, 1], array1))));
Ignore(Mapped(EqualityFactI(_, _, $"Subarray failed: subpermutation case."), Zipped([12, 11], Subarray([2, 1], array1))));
}
function FilterTest () : Unit {
@Test("QuantumSimulator")
function FilteredIsEvenHasNoOdds() : Unit {
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let evenArray = Filtered(IsEven, array);
EqualityFactB(All(IsEven, evenArray), true, $"the even elements of [1..10] were not correctly filtered.");
Fact(All(IsEven, evenArray), $"the even elements of [1..10] were not correctly filtered.");
}
@Test("QuantumSimulator")
function CountOfIsEvenIsCorrect() : Unit {
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let countEvens = Count(IsEven, array);
EqualityFactI(countEvens, 5, $"the even elements of [1..10] were not correctly counted.");
}
function ReverseTest () : Unit {
let array = [1, 2, 3];
Ignore(Mapped(EqualityFactI(_, _, $"Reversed failed."), Zip([3, 2, 1], Reversed(array))));
Ignore(Mapped(EqualityFactI(_, _, $"Reversed failed."), Zipped([3, 2, 1], Reversed(array))));
}
function ExcludeTest () : Unit {
function ExcludingTest () : Unit {
let array = [10, 11, 12, 13, 14, 15];
Ignore(Mapped(EqualityFactI(_, _, $"Exclude failed."), Zip([10, 11, 13, 14], Exclude([2, 5], array))));
Ignore(Mapped(EqualityFactI(_, _, $"Excluding failed."), Zipped([10, 11, 13, 14], Excluding([2, 5], array))));
}
@ -120,7 +137,7 @@ namespace Microsoft.Quantum.Tests {
for (idxTest in IndexRange(arrayTestCase)) {
let (nElementsTotal, defaultElement, inputArray, outputArray) = arrayTestCase[idxTest];
let paddedArray = Padded(nElementsTotal, defaultElement, inputArray);
Ignore(Mapped(EqualityFactI(_, _, $"Padded failed."), Zip(outputArray, paddedArray)));
Ignore(Mapped(EqualityFactI(_, _, $"Padded failed."), Zipped(outputArray, paddedArray)));
}
}
@ -129,7 +146,7 @@ namespace Microsoft.Quantum.Tests {
let expected = [(0, 37), (1, 12)];
let actual = Enumerated(example);
for ((actualElement, expectedElement) in Zip(actual, expected)) {
for ((actualElement, expectedElement) in Zipped(actual, expected)) {
EqualityFactI(Fst(actualElement), Fst(expectedElement), "Indices did not match.");
EqualityFactI(Snd(actualElement), Snd(expectedElement), "Elements did not match.");
}
@ -140,9 +157,9 @@ namespace Microsoft.Quantum.Tests {
let expected = [[0, 1, 2, 3], [23, 24, 25, 26, 27, 28, 29], [-5, -4, -3, -2]];
let actual = Mapped(SequenceI, example);
for ((exp, act) in Zip(expected, actual)) {
for ((exp, act) in Zipped(expected, actual)) {
EqualityFactI(Length(exp), Length(act), "Lengths of arrays did not match.");
for ((i, j) in Zip(exp, act)) {
for ((i, j) in Zipped(exp, act)) {
EqualityFactI(i, j, "Elements did not match.");
}
}
@ -153,9 +170,9 @@ namespace Microsoft.Quantum.Tests {
let expected = [[0L, 1L, 2L, 3L], [23L, 24L, 25L, 26L, 27L, 28L, 29L], [-5L, -4L, -3L, -2L]];
let actual = Mapped(SequenceL, example);
for ((exp, act) in Zip(expected, actual)) {
for ((exp, act) in Zipped(expected, actual)) {
EqualityFactI(Length(exp), Length(act), "Lengths of arrays did not match.");
for ((i, j) in Zip(exp, act)) {
for ((i, j) in Zipped(exp, act)) {
EqualityFactL(i, j, "Elements did not match.");
}
}
@ -166,9 +183,9 @@ namespace Microsoft.Quantum.Tests {
let expected = [[0, 1, 2, 3], [0, 1, 2, 3, 4, 5], [0]];
let actual = Mapped(SequenceI(0, _), example);
for ((exp, act) in Zip(expected, actual)) {
for ((exp, act) in Zipped(expected, actual)) {
EqualityFactI(Length(exp), Length(act), "Lengths of arrays did not match.");
for ((i, j) in Zip(exp, act)) {
for ((i, j) in Zipped(exp, act)) {
EqualityFactI(i, j, "Elements did not match.");
}
}
@ -188,7 +205,7 @@ namespace Microsoft.Quantum.Tests {
let actual = _SwapOrderToPermuteArray(newOrder);
EqualityFactI(Length(expected), Length(actual), "Number of swaps does not match");
for ((exp, act) in Zip(expected, actual)) {
for ((exp, act) in Zipped(expected, actual)) {
let (leftExp, rightExp) = exp;
let (leftAct, rightAct) = act;
@ -205,7 +222,7 @@ namespace Microsoft.Quantum.Tests {
let newArray = Swapped(leftIndex, rightIndex, example);
EqualityFactI(Length(expected), Length(newArray), "Swapped array is a different size than original");
for ((exp, act) in Zip(expected, newArray)) {
for ((exp, act) in Zipped(expected, newArray)) {
EqualityFactI(exp, act, "Elements did not match");
}
}
@ -216,8 +233,8 @@ namespace Microsoft.Quantum.Tests {
let actual = TupleArrayAsNestedArray(example);
EqualityFactI(Length(expected), Length(actual), "Arrays are of different sizes");
for ((exp, act) in Zip(expected, actual)) {
for ((elementExp, elementAct) in Zip(exp, act)) {
for ((exp, act) in Zipped(expected, actual)) {
for ((elementExp, elementAct) in Zipped(exp, act)) {
EqualityFactI(elementExp, elementAct, "Elements did not match");
}
}
@ -237,6 +254,109 @@ namespace Microsoft.Quantum.Tests {
let differentElements = EqualA(EqualR, [One, Zero], [One, One]);
Fact(not differentElements, "Arrays with different elements were reported as equal");
}
@Test("QuantumSimulator")
operation TestInterleaved() : Unit {
AllEqualityFactI(Interleaved([1, 2, 3], [-1, -2, -3]), [1, -1, 2, -2, 3, -3], "Interleaving failed");
AllEqualityFactB(Interleaved(ConstantArray(3, false), ConstantArray(2, true)), [false, true, false, true, false], "Interleaving failed");
}
@Test("QuantumSimulator")
operation TestCumulativeFolded() : Unit {
AllEqualityFactI(CumulativeFolded(PlusI, 0, SequenceI(1, 5)), [1, 3, 6, 10, 15], "CumulativeFolded failed");
}
@Test("QuantumSimulator")
operation TestTransposed() : Unit {
for ((actual, expected) in Zipped(Transposed([[1, 2, 3], [4, 5, 6]]), [[1, 4], [2, 5], [3, 6]])) {
AllEqualityFactI(actual, expected, "Transposed failed");
}
}
@Test("QuantumSimulator")
operation TestColumnAt() : Unit {
let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
AllEqualityFactI(ColumnAt(0, matrix), [1, 4, 7], "ColumnAt failed");
AllEqualityFactI(ColumnAt(1, matrix), [2, 5, 8], "ColumnAt failed");
AllEqualityFactI(ColumnAt(2, matrix), [3, 6, 9], "ColumnAt failed");
}
@Test("QuantumSimulator")
operation TestElementAt() : Unit {
let lucas = [2, 1, 3, 4, 7, 11, 18, 29, 47, 76];
let prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
let fibonacci = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34];
let catalan = [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862];
let famous2 = Mapped(ElementAt<Int>(2, _), [lucas, prime, fibonacci, catalan]);
AllEqualityFactI(famous2, [3, 5, 1, 2], "ElementAt failed");
}
@Test("QuantumSimulator")
operation TestElementsAt() : Unit {
let lucas = [2, 1, 3, 4, 7, 11, 18, 29, 47, 76];
let prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
let fibonacci = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34];
let catalan = [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862];
let famousOdd = Mapped(ElementsAt<Int>(0..2..9, _), [lucas, prime, fibonacci, catalan]);
for ((actual, expected) in Zipped(famousOdd, [[2, 3, 7, 18, 47], [2, 5, 11, 17, 23], [0, 1, 3, 8, 21], [1, 2, 14, 132, 1430]])) {
AllEqualityFactI(actual, expected, "ElementsAt failed");
}
}
@Test("QuantumSimulator")
operation TestDiagonal() : Unit {
AllEqualityFactI(Diagonal([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), [1, 5, 9], "Diagonal failed");
AllEqualityFactI(Diagonal([[1, 2, 3], [4, 5, 6]]), [1, 5], "Diagonal failed");
AllEqualityFactI(Diagonal([[1, 2], [4, 5], [7, 8]]), [1, 5], "Diagonal failed");
}
@Test("QuantumSimulator")
operation TestWindows() : Unit {
let EqualIntA = EqualA<Int>(EqualI, _, _);
let EqualIntAA = EqualA<Int[]>(EqualIntA, _, _);
Fact(EqualIntAA(Windows(-1, [1, 2, 3]), new Int[][0]), "unexpected windows");
Fact(EqualIntAA(Windows(0, [1, 2, 3]), new Int[][0]), "unexpected windows");
Fact(EqualIntAA(Windows(1, [1, 2, 3]), [[1], [2], [3]]), "unexpected windows");
Fact(EqualIntAA(Windows(2, [1, 2, 3]), [[1, 2], [2, 3]]), "unexpected windows");
Fact(EqualIntAA(Windows(3, [1, 2, 3]), [[1, 2, 3]]), "unexpected windows");
Fact(EqualIntAA(Windows(4, [1, 2, 3]), new Int[][0]), "unexpected windows");
}
@Test("QuantumSimulator")
operation TestPrefixes() : Unit {
let array = [0, 1, 1, 2, 3, 5];
let prefixes = Prefixes(array);
EqualityFactI(Length(prefixes), Length(array), "unexpected length for prefixes");
AllEqualityFactI(prefixes[0], [0], "unexpected prefix");
AllEqualityFactI(prefixes[1], [0, 1], "unexpected prefix");
AllEqualityFactI(prefixes[2], [0, 1, 1], "unexpected prefix");
AllEqualityFactI(prefixes[3], [0, 1, 1, 2], "unexpected prefix");
AllEqualityFactI(prefixes[4], [0, 1, 1, 2, 3], "unexpected prefix");
AllEqualityFactI(prefixes[5], [0, 1, 1, 2, 3, 5], "unexpected prefix");
}
@Test("QuantumSimulator")
operation TestSuccessfulRectangularFact() : Unit {
RectangularArrayFact([[1, 2], [3, 4]], "Array is not rectangular");
RectangularArrayFact([[1, 2, 3], [4, 5, 6]], "Array is not rectangular");
}
operation RectangularFactTestShouldFail() : Unit {
RectangularArrayFact([[1, 2], [3, 4, 5]], "Array is not rectangular");
}
@Test("QuantumSimulator")
operation TestSuccessfulSquareFact() : Unit {
SquareArrayFact([[1, 2], [3, 4]], "Array is not a square");
}
operation SquareFact1TestShouldFail() : Unit {
SquareArrayFact([[1, 2, 3], [4, 5, 6]], "Array is not a square");
}
operation SquareFact2TestShouldFail() : Unit {
SquareArrayFact([[1, 2], [3, 4, 5]], "Array is not a square");
}
}

Просмотреть файл

@ -0,0 +1,76 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
open Microsoft.Quantum.Random;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Logical;
@Test("QuantumSimulator")
function IntsAreSorted() : Unit {
Fact(IsSorted(LessThanOrEqualI, [1, 10, 100]), "[1, 10, 100] was marked as unsorted.");
}
@Test("QuantumSimulator")
function DoublesAreSorted() : Unit {
Fact(IsSorted(LessThanOrEqualD, [1.0, 10.1, 100.2]), "[1.0, 10.1, 100.2] was marked as unsorted.");
}
@Test("QuantumSimulator")
function IntsAreNotSorted() : Unit {
Contradiction(IsSorted(LessThanOrEqualI, [100, 10, 3]), "[100, 10, 3] was marked as sorted.");
}
@Test("QuantumSimulator")
function SortedIntsAreSorted() : Unit {
Fact(IsSorted(LessThanOrEqualI,
Sorted(LessThanOrEqualI, [100, 10, 3])),
"Sorted(<=, [100, 10, 3]) was marked as unsorted."
);
}
@Test("QuantumSimulator")
function SortedDoublesAreSorted() : Unit {
Fact(IsSorted(LessThanOrEqualD,
Sorted(LessThanOrEqualD, [100.0, 10.1, 3.14])),
"Sorted(<=, [100.0, 10.1, 3.14]) was marked as unsorted."
);
}
@Test("QuantumSimulator")
operation CheckRandomArraysAreSortedWhenSorted() : Unit {
let nItems = 100;
let nTrials = 10;
let maxItem = 1000;
for (_ in 0..nTrials - 1) {
let data = DrawMany((DiscreteUniformDistribution(0, maxItem))::Sample, nItems, ());
Fact(IsSorted(LessThanOrEqualI, Sorted(LessThanOrEqualI, data)), $"{data} was not sorted after running Sorted.");
}
}
@Test("QuantumSimulator")
function LexographicSortIsCorrect() : Unit {
let arrayComparison = LexographicComparison(LessThanOrEqualI);
let data = [
[1, 2, 3],
[1, 2],
[0, 2],
[1, 3]
];
let sorted = Sorted(arrayComparison, data);
AllEqualityFactI(
sorted[0], [0, 2], "0th item was not correct."
);
AllEqualityFactI(
sorted[1], [1, 2], "1st item was not correct."
);
AllEqualityFactI(
sorted[2], [1, 2, 3], "2nd item was not correct."
);
AllEqualityFactI(
sorted[3], [1, 3], "3rd item was not correct."
);
}
}

Просмотреть файл

@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Arrays {
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Logical;
@Test("QuantumSimulator")
operation UniqueInts() : Unit {
AllEqualityFactI(Unique(EqualI, [0, 0, 1, 2, 2, 3, 4, 5, 5, 8, 42, 42, 39]), [0, 1, 2, 3, 4, 5, 8, 42, 39], "Data is not unique");
AllEqualityFactI(Unique(EqualI, [0, 1, 1, 0, 0, 1, 1, 0]), [0, 1, 0, 1, 0], "Data is not unique");
AllEqualityFactI(Unique(EqualI, Sorted(LessThanOrEqualI, [2, 2, 1, 1, 2, 2, 1, 1])), [1, 2], "Sorted data is not unique");
}
@Test("QuantumSimulator")
operation UniqueDoubles() : Unit {
let unique = Unique(EqualD, [1.1, 1.1, 2.2, 2.2, 2.2, 3.3, 0.5, 42.0]);
EqualityFactI(Length(unique), 5, "Unexpected length of unique data");
Fact(unique[0] == 1.1, "Unexpected element in unique data");
Fact(unique[1] == 2.2, "Unexpected element in unique data");
Fact(unique[2] == 3.3, "Unexpected element in unique data");
Fact(unique[3] == 0.5, "Unexpected element in unique data");
Fact(unique[4] == 42.0, "Unexpected element in unique data");
}
}

Просмотреть файл

@ -134,14 +134,14 @@ namespace Microsoft.Quantum.Tests {
operation CControlledActual (op : (Qubit => Unit), target : Qubit[]) : Unit {
ApplyToEach(CControlled(op), Zip([true, false, true], target));
ApplyToEach(CControlled(op), Zipped([true, false, true], target));
}
operation CControlledActualC (op : (Qubit => Unit is Ctl), target : Qubit[]) : Unit {
body (...) {
ApplyToEachC(CControlledC(op), Zip([true, false, true], target));
ApplyToEachC(CControlledC(op), Zipped([true, false, true], target));
}
controlled distribute;
@ -151,7 +151,7 @@ namespace Microsoft.Quantum.Tests {
operation CControlledActualA (op : (Qubit => Unit is Adj), target : Qubit[]) : Unit {
body (...) {
ApplyToEachA(CControlledA(op), Zip([true, false, true], target));
ApplyToEachA(CControlledA(op), Zipped([true, false, true], target));
}
adjoint invert;
@ -161,7 +161,7 @@ namespace Microsoft.Quantum.Tests {
operation CControlledActualCA (op : (Qubit => Unit is Adj + Ctl), target : Qubit[]) : Unit {
body (...) {
ApplyToEachCA(CControlledCA(op), Zip([true, false, true], target));
ApplyToEachCA(CControlledCA(op), Zipped([true, false, true], target));
}
adjoint invert;

Просмотреть файл

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Tests {
open Microsoft.Quantum.Math;
@ -59,6 +59,33 @@ namespace Microsoft.Quantum.Tests {
EqualityFactI(Fold(Add, 0, squaredArray), 30, $"the sum of the squares of [1, 2, 3, 4] was not found to be 30.");
}
@Test("QuantumSimulator")
function TestMappedOverNonEmptyRange() : Unit {
AllEqualityFactI(MappedOverRange(PlusI(_, 2), 1..5), [3, 4, 5, 6, 7], "MappedOverRange failed.");
}
@Test("QuantumSimulator")
function TestMappedOverReversedRange() : Unit {
AllEqualityFactI(MappedOverRange(TimesI(_, 2), 4..-2..-4), [8, 4, 0, -4, -8], "MappedOverRange failed.");
}
@Test("QuantumSimulator")
function TestMappedOverEmpty() : Unit {
AllEqualityFactI(MappedOverRange(TimesI(_, 2), 1..-1..2), new Int[0], "MappedOverRange failed.");
}
@Test("QuantumSimulator")
function TestFlatMapped() : Unit {
let numbers = FlatMapped(SequenceI(1, _), SequenceI(1, 5));
AllEqualityFactI(numbers, [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5], "FlatMapped failed");
}
@Test("QuantumSimulator")
function TestFlattened() : Unit {
let numbers = Flattened(ConstantArray(3, SequenceI(1, 3)));
AllEqualityFactI(numbers, [1, 2, 3, 1, 2, 3, 1, 2, 3], "Flattened failed");
}
function ExtremaTest () : Unit {
let array = [-10, 10, 7, 0];
EqualityFactI(-10, Min(array), $"Min failed.");

Просмотреть файл

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Tests {
open Microsoft.Quantum.Logical;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Arrays;
function LexographicComparisonIsCorrect() : Unit {
let lexographicComparison = LexographicComparison(LessThanOrEqualD);
Fact(
lexographicComparison(
[1.1, 2.2], [1.1, 2.2, 3.3]
),
"Shorter array should have occured first."
);
Fact(
lexographicComparison(
[0.7, 2.2], [1.1, 2.2]
),
"Array with smaller first element should have occured first."
);
Fact(
lexographicComparison(
[1.1, 2.2], [1.1, 2.2]
),
"Identical arrays should be marked as less than or equal."
);
Contradiction(
lexographicComparison(
[1.1, 2.7], [1.1, 2.2, 3.3]
),
"Array with larger second element should have occured second."
);
}
}

Просмотреть файл

@ -145,7 +145,7 @@ namespace Microsoft.Quantum.Tests {
for (idxTest in IndexRange(testCases)) {
let (expected, range) = testCases[idxTest];
let output = RangeAsIntArray(range);
Ignore(Mapped(EqualityFactI(_, _, "Padded failed."), Zip(output, expected)));
Ignore(Mapped(EqualityFactI(_, _, "Padded failed."), Zipped(output, expected)));
}
}