Various additions and improvements to Microsoft.Quantum.Arrays (#330)
This commit is contained in:
Родитель
fdd6b964c1
Коммит
c4f69418a5
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче