185 строки
7.2 KiB
Plaintext
185 строки
7.2 KiB
Plaintext
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
namespace Microsoft.Quantum.Tests {
|
|
open Microsoft.Quantum.Arithmetic;
|
|
open Microsoft.Quantum.Arrays;
|
|
open Microsoft.Quantum.Canon;
|
|
open Microsoft.Quantum.Convert;
|
|
open Microsoft.Quantum.Diagnostics;
|
|
open Microsoft.Quantum.Intrinsic;
|
|
open Microsoft.Quantum.Math;
|
|
open Microsoft.Quantum.Measurement;
|
|
open Microsoft.Quantum.Synthesis;
|
|
open Microsoft.Quantum.Random;
|
|
|
|
internal operation CheckApplyPermutation (synthesisOperation : ((Int[], LittleEndian) => Unit is Adj + Ctl)) : Unit {
|
|
let permutations = [
|
|
[0, 2, 1, 3],
|
|
[0, 1, 3, 2],
|
|
[0, 1, 2, 3],
|
|
[3, 2, 1, 0],
|
|
[0, 1, 2, 3, 4, 5, 7, 6],
|
|
[0, 2, 4, 6, 1, 3, 5, 7],
|
|
[0, 2, 3, 5, 7, 11, 13, 1, 4, 6, 8, 9, 10, 12, 14, 15]
|
|
];
|
|
|
|
for perm in permutations {
|
|
let numQubits = BitSizeI(Length(perm) - 1);
|
|
|
|
use qs = Qubit[numQubits];
|
|
let register = LittleEndian(qs);
|
|
for i in 0..Length(perm) - 1 {
|
|
ApplyXorInPlace(i, register);
|
|
synthesisOperation(perm, register);
|
|
EqualityFactI(MeasureInteger(register), perm[i], $"ApplyPermutation failed for permutation {perm} at index {i}");
|
|
}
|
|
}
|
|
}
|
|
|
|
internal operation ApplyPermutationUsingDecompositionWithReverseVariableOrder (perm : Int[], qubits : LittleEndian) : Unit is Adj + Ctl {
|
|
let variableOrder = Reversed(SequenceI(0, Length(qubits!) - 1));
|
|
ApplyPermutationUsingDecompositionWithVariableOrder(perm, variableOrder, qubits);
|
|
}
|
|
|
|
@Test("ToffoliSimulator")
|
|
operation CheckTransformationBasedSynthesis () : Unit {
|
|
CheckApplyPermutation(ApplyPermutationUsingTransformation);
|
|
}
|
|
|
|
@Test("QuantumSimulator")
|
|
operation CheckDecompositionBasedSynthesis () : Unit {
|
|
CheckApplyPermutation(ApplyPermutationUsingDecomposition);
|
|
CheckApplyPermutation(ApplyPermutationUsingDecompositionWithReverseVariableOrder);
|
|
}
|
|
|
|
@Test("ToffoliSimulator")
|
|
operation CheckApplyTransposition () : Unit {
|
|
for numQubits in 2..6 {
|
|
for _ in 1..10 {
|
|
let a = DrawRandomInt(0, 2^numQubits - 1);
|
|
let b = DrawRandomInt(0, 2^numQubits - 1);
|
|
|
|
use qs = Qubit[numQubits];
|
|
let register = LittleEndian(qs);
|
|
|
|
for i in 0..2^numQubits - 1 {
|
|
ApplyXorInPlace(i, register);
|
|
ApplyTransposition(a, b, register);
|
|
EqualityFactI(
|
|
MeasureInteger(register),
|
|
i == a ? b | (i == b ? a | i),
|
|
$"ApplyTransposition failed for {numQubits} qubits when a = {a} and b = {b}"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal operation RandomBool() : Bool {
|
|
return DrawRandomInt(0, 1) == 1;
|
|
}
|
|
|
|
// from ControlledOnTruthTable.qs
|
|
internal function SizeAdjustedTruthTable(table : Bool[], numVars : Int) : Bool[] {
|
|
let numEntries = 2^numVars;
|
|
if (numEntries < Length(table)) {
|
|
return table[...numEntries - 1];
|
|
} elif (numEntries > Length(table)) {
|
|
return Padded(-numEntries, false, table);
|
|
} else {
|
|
return table;
|
|
}
|
|
}
|
|
|
|
@Test("QuantumSimulator")
|
|
operation CheckApplyXControlledOnTruthTable () : Unit {
|
|
for numQubits in 2..5 {
|
|
for round in 1..5 {
|
|
// TODO: replace with BigUniform.
|
|
let func = IntAsBigInt(DrawRandomInt(0, 2^(2^numQubits) - 1));
|
|
let truthValues = SizeAdjustedTruthTable(BigIntAsBoolArray(func), numQubits);
|
|
|
|
use controls = Qubit[numQubits];
|
|
use target = Qubit();
|
|
for i in 0..(2^numQubits - 1) {
|
|
let targetInit = RandomBool();
|
|
ApplyIf(targetInit, X, target);
|
|
within {
|
|
ApplyXorInPlace(i, LittleEndian(controls));
|
|
} apply {
|
|
ApplyXControlledOnTruthTable(func, controls, target);
|
|
}
|
|
EqualityFactB(
|
|
IsResultOne(MResetZ(target)) != targetInit,
|
|
truthValues[i],
|
|
$"Measured value does not correspond to truth table bit in truth table {func} and bit {i}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test("QuantumSimulator")
|
|
operation CheckControlledApplyXControlledOnTruthTable () : Unit {
|
|
for numQubits in 2..5 {
|
|
for round in 1..5 {
|
|
// TODO: replace with BigUniform.
|
|
let func = IntAsBigInt(DrawRandomInt(0, 2^(2^numQubits) - 1));
|
|
let truthValues = SizeAdjustedTruthTable(BigIntAsBoolArray(func), numQubits);
|
|
|
|
use controls = Qubit[numQubits];
|
|
use control = Qubit();
|
|
use target = Qubit();
|
|
for i in 0..(2^numQubits - 1) {
|
|
let controlInit = RandomBool();
|
|
let targetInit = RandomBool();
|
|
ApplyIf(targetInit, X, target);
|
|
within {
|
|
ApplyIfA(controlInit, X, control);
|
|
ApplyXorInPlace(i, LittleEndian(controls));
|
|
} apply {
|
|
Controlled ApplyXControlledOnTruthTable([control], (func, controls, target));
|
|
}
|
|
|
|
let result = IsResultOne(MResetZ(target));
|
|
if (controlInit) {
|
|
EqualityFactB(
|
|
result != targetInit,
|
|
truthValues[i],
|
|
$"Measured value does not correspond to truth table bit in truth table {func} and bit {i}");
|
|
} else {
|
|
EqualityFactB(result, targetInit, $"Target should not have been changed from its initial value {targetInit}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test("QuantumSimulator")
|
|
operation CheckApplyXControlledOnTruthTableWithCleanTarget () : Unit {
|
|
for numQubits in 2..5 {
|
|
for round in 1..5 {
|
|
// TODO: replace with BigUniform.
|
|
let func = IntAsBigInt(DrawRandomInt(0, 2^(2^numQubits) - 1));
|
|
let truthValues = SizeAdjustedTruthTable(BigIntAsBoolArray(func), numQubits);
|
|
|
|
use controls = Qubit[numQubits];
|
|
use target = Qubit();
|
|
use copy = Qubit();
|
|
for i in 0..(2^numQubits - 1) {
|
|
within {
|
|
ApplyXorInPlace(i, LittleEndian(controls));
|
|
ApplyXControlledOnTruthTableWithCleanTarget(func, controls, target);
|
|
} apply {
|
|
CNOT(target, copy);
|
|
}
|
|
EqualityFactB(
|
|
IsResultOne(MResetZ(copy)),
|
|
truthValues[i],
|
|
$"Measured value does not correspond to truth table bit in truth table {func} and bit {i}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|