Create "Unitary Patterns" kata and tools for working with it (#69)
This commit is contained in:
Родитель
476ba89c2f
Коммит
94b8fbef0b
|
@ -50,6 +50,10 @@
|
|||
"path": "QEC_BitFlipCode",
|
||||
"name": "11. QEC: Bit-flip Code"
|
||||
},
|
||||
{
|
||||
"path": "UnitaryPatterns",
|
||||
"name": "12*. Unitary Patterns"
|
||||
},
|
||||
],
|
||||
"settings": {
|
||||
"csharp.suppressDotnetRestoreNotification": true,
|
||||
|
|
|
@ -27,6 +27,8 @@ Currently covered topics are:
|
|||
This kata covers phase estimation algorithms.
|
||||
* **[Bit-flip error correcting code](./QEC_BitFlipCode/)**.
|
||||
This kata introduces a 3-qubit error correcting code for protecting against bit-flip errors.
|
||||
* **[Unitary Patterns*](./UnitaryPatterns/)**.
|
||||
This unusual kata offers tasks on implementing unitaries with matrices that follow certain patterns of zero and non-zero elements.
|
||||
|
||||
Each kata is a separate project which includes:
|
||||
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// This file contains parts of the testing harness.
|
||||
// You should not modify anything in this file.
|
||||
// The tasks themselves can be found in Tasks.qs file.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Quantum.Simulation.Core;
|
||||
using Microsoft.Quantum.Simulation.Simulators;
|
||||
|
||||
namespace Quantum.Kata.UnitaryPatterns
|
||||
{
|
||||
/// <summary>
|
||||
/// This custom quantum simulator keeps track of the number of times
|
||||
/// each operation is executed, by providing a custom native operation:
|
||||
/// `AssertOracleCallsCount` which asserts the number of times
|
||||
/// the given oracle (operation) has been called.
|
||||
/// </summary>
|
||||
public class CounterSimulator : QuantumSimulator
|
||||
{
|
||||
private Dictionary<ICallable, int> _operationsCount = new Dictionary<ICallable, int>();
|
||||
private long _qubitsAllocated = 0;
|
||||
private long _maxQubitsAllocated = 0;
|
||||
|
||||
#region Counting operations
|
||||
public CounterSimulator(
|
||||
bool throwOnReleasingQubitsNotInZeroState = true,
|
||||
uint? randomNumberGeneratorSeed = null,
|
||||
bool disableBorrowing = false) :
|
||||
base(throwOnReleasingQubitsNotInZeroState, randomNumberGeneratorSeed, disableBorrowing)
|
||||
{
|
||||
this.OnOperationStart += CountOperationCalls;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback method for the OnOperationStart event.
|
||||
/// </summary>
|
||||
public void CountOperationCalls(ICallable op, IApplyData data)
|
||||
{
|
||||
if (_operationsCount.ContainsKey(op))
|
||||
{
|
||||
_operationsCount[op]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_operationsCount[op] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Custom Native operation to reset the oracle counts back to 0.
|
||||
public class ResetOracleCallsImpl : ResetOracleCallsCount
|
||||
{
|
||||
CounterSimulator _sim;
|
||||
|
||||
public ResetOracleCallsImpl(CounterSimulator m) : base(m)
|
||||
{
|
||||
_sim = m;
|
||||
}
|
||||
|
||||
public override Func<QVoid, QVoid> Body => (__in) =>
|
||||
{
|
||||
_sim._operationsCount.Clear();
|
||||
return QVoid.Instance;
|
||||
};
|
||||
}
|
||||
|
||||
public class GetOracleCallsImpl<T> : GetOracleCallsCount<T>
|
||||
{
|
||||
CounterSimulator _sim;
|
||||
|
||||
public GetOracleCallsImpl(CounterSimulator m) : base(m)
|
||||
{
|
||||
_sim = m;
|
||||
}
|
||||
|
||||
public override Func<T, long> Body => (__in) =>
|
||||
{
|
||||
var oracle = __in;
|
||||
|
||||
var op = oracle as ICallable;
|
||||
|
||||
var actual = _sim._operationsCount.ContainsKey(op) ? _sim._operationsCount[op] : 0;
|
||||
|
||||
return actual;
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Counting allocated qubits
|
||||
new public class Allocate : Microsoft.Quantum.Simulation.Simulators.SimulatorBase.Allocate
|
||||
{
|
||||
CounterSimulator _sim;
|
||||
|
||||
public Allocate(CounterSimulator m) : base(m)
|
||||
{
|
||||
_sim = m;
|
||||
}
|
||||
|
||||
public override Qubit Apply()
|
||||
{
|
||||
_sim._qubitsAllocated++;
|
||||
if (_sim._qubitsAllocated > _sim._maxQubitsAllocated)
|
||||
{
|
||||
_sim._maxQubitsAllocated = _sim._qubitsAllocated;
|
||||
}
|
||||
return base.Apply();
|
||||
}
|
||||
|
||||
public override QArray<Qubit> Apply(long count)
|
||||
{
|
||||
_sim._qubitsAllocated += count;
|
||||
if (_sim._qubitsAllocated > _sim._maxQubitsAllocated)
|
||||
{
|
||||
_sim._maxQubitsAllocated = _sim._qubitsAllocated;
|
||||
}
|
||||
return base.Apply(count);
|
||||
}
|
||||
}
|
||||
|
||||
new public class Release : Microsoft.Quantum.Simulation.Simulators.SimulatorBase.Release
|
||||
{
|
||||
CounterSimulator _sim;
|
||||
|
||||
public Release(CounterSimulator m) : base(m)
|
||||
{
|
||||
_sim = m;
|
||||
}
|
||||
|
||||
public override void Apply(Qubit q)
|
||||
{
|
||||
_sim._qubitsAllocated--;
|
||||
base.Apply(q);
|
||||
}
|
||||
|
||||
public override void Apply(QArray<Qubit> qubits)
|
||||
{
|
||||
_sim._qubitsAllocated -= qubits.Length;
|
||||
base.Apply(qubits);
|
||||
}
|
||||
}
|
||||
|
||||
public class ResetQubitCountImpl : ResetQubitCount
|
||||
{
|
||||
CounterSimulator _sim;
|
||||
|
||||
public ResetQubitCountImpl(CounterSimulator m) : base(m)
|
||||
{
|
||||
_sim = m;
|
||||
}
|
||||
|
||||
public override Func<QVoid, QVoid> Body => (__in) =>
|
||||
{
|
||||
_sim._qubitsAllocated = 0;
|
||||
_sim._maxQubitsAllocated = 0;
|
||||
return QVoid.Instance;
|
||||
};
|
||||
}
|
||||
|
||||
public class GetMaxQubitCountImpl : GetMaxQubitCount
|
||||
{
|
||||
CounterSimulator _sim;
|
||||
|
||||
public GetMaxQubitCountImpl(CounterSimulator m) : base(m)
|
||||
{
|
||||
_sim = m;
|
||||
}
|
||||
|
||||
public override Func<QVoid, long> Body => (__in) =>
|
||||
{
|
||||
return _sim._maxQubitsAllocated;
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# Welcome!
|
||||
|
||||
The "Unitary Patterns" kata offers tasks on creating unitary transformations which can be represented
|
||||
with matrices of certain shapes (with certain pattern of zero and non-zero values).
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// This file contains reference solutions to all tasks.
|
||||
// The tasks themselves can be found in Tasks.qs file.
|
||||
// We recommend that you try to solve the tasks yourself first,
|
||||
// but feel free to look up the solution if you get stuck.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Quantum.Kata.UnitaryPatterns {
|
||||
|
||||
open Microsoft.Quantum.Extensions.Convert;
|
||||
open Microsoft.Quantum.Extensions.Math;
|
||||
open Microsoft.Quantum.Primitive;
|
||||
open Microsoft.Quantum.Canon;
|
||||
|
||||
|
||||
// Task 1. Main diagonal
|
||||
operation MainDiagonal_Reference (qs : Qubit[]) : Unit {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Task 2. All-non-zero matrix
|
||||
operation AllNonZero_Reference (qs : Qubit[]) : Unit {
|
||||
ApplyToEach(H, qs);
|
||||
}
|
||||
|
||||
|
||||
// Task 3. Quarters
|
||||
operation Quarters_Reference (qs : Qubit[]) : Unit {
|
||||
ApplyToEach(H, Most(qs));
|
||||
}
|
||||
|
||||
|
||||
// Task 4. Even chessboard pattern
|
||||
operation EvenChessPattern_Reference (qs : Qubit[]) : Unit {
|
||||
ApplyToEach(H, qs[1 .. Length(qs) - 1]);
|
||||
}
|
||||
|
||||
|
||||
// Task 5. Odd chessboard pattern
|
||||
operation OddChessPattern_Reference (qs : Qubit[]) : Unit {
|
||||
ApplyToEach(H, qs[1 .. Length(qs) - 1]);
|
||||
X(Head(qs));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Quantum.Kata.UnitaryPatterns {
|
||||
|
||||
open Microsoft.Quantum.Extensions.Convert;
|
||||
open Microsoft.Quantum.Extensions.Math;
|
||||
open Microsoft.Quantum.Primitive;
|
||||
open Microsoft.Quantum.Canon;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Welcome!
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
// The "Unitary Patterns" quantum kata is a series of exercises designed
|
||||
// to get you comfortable with creating unitary transformations which can be represented
|
||||
// with matrices of certain shapes (with certain pattern of zero and non-zero values).
|
||||
|
||||
// Each task is wrapped in one operation preceded by the description of the task.
|
||||
// Each task has a unit test associated with it, which initially fails.
|
||||
// Your goal is to fill in the blank (marked with // ... comment)
|
||||
// with some Q# code to make the failing test pass.
|
||||
|
||||
// The tasks are given in approximate order of increasing difficulty;
|
||||
// harder ones are marked with asterisks.
|
||||
|
||||
// Each task describes a matrix which your unitary needs to implement.
|
||||
// The row and column indices of the matrix elements are in little-endian format (the least significant bit is stored first).
|
||||
// For example, index 1 corresponds to the qubit state |10..0⟩, and to store this state in an array of qubits qs
|
||||
// its first element qs[0] would have to be in state |1⟩ and the rest of the qubits would have to be in state |0⟩.
|
||||
|
||||
// In the example patterns provided in the tasks, X marks a "non-zero" element, and . marks a "zero" element.
|
||||
// "Zero" element of a matrix is a complex number which has an absolute value of 0.001 or less,
|
||||
// and "non-zero" element is a complex number which has an absolute value of 0.001 or greater.
|
||||
// You can see the details of the verification in Tests.qs file, operation AssertOperationMatrixMatchesPattern.
|
||||
|
||||
// Note that all tasks require you to implement a unitary transformation,
|
||||
// which means that you're not allowed to use any measurements.
|
||||
|
||||
|
||||
|
||||
// Task 1. Main diagonal
|
||||
// Input: N qubits in an arbitrary state.
|
||||
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
|
||||
// with non-zero elements on the main diagonal and zero elements everywhere else.
|
||||
// Example: For N = 2, the matrix of the transformation should look as follows:
|
||||
// X...
|
||||
// .X..
|
||||
// ..X.
|
||||
// ...X
|
||||
operation MainDiagonal (qs : Qubit[]) : Unit {
|
||||
// The simplest example of such a unitary transformation is represented by an identity matrix.
|
||||
// This means that the operation doesn't need to do anything with the input qubits.
|
||||
// Build the project and run the tests to see that T01_MainDiagonal_Test test passes.
|
||||
|
||||
// You are welcome to try and come up with other diagonal unitaries.
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
// Task 2. All-non-zero matrix
|
||||
// Input: N qubits in an arbitrary state.
|
||||
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
|
||||
// with all elements non-zero.
|
||||
// Example: For N = 2, the matrix of the transformation should look as follows:
|
||||
// XXXX
|
||||
// XXXX
|
||||
// XXXX
|
||||
// XXXX
|
||||
operation AllNonZero (qs : Qubit[]) : Unit {
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
// Task 3. Quarters
|
||||
// Input: N qubits in an arbitrary state.
|
||||
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
|
||||
// with non-zero elements in top left and bottom right quarters
|
||||
// and zero elements everywhere else.
|
||||
// Example: For N = 2, the matrix of the transformation should look as follows:
|
||||
// XX..
|
||||
// XX..
|
||||
// ..XX
|
||||
// ..XX
|
||||
operation Quarters (qs : Qubit[]) : Unit {
|
||||
// Hint: represent this matrix as a tensor product of a 2x2 diagonal matrix and a larger matrix with all non-zero elements.
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
// Task 4. Even chessboard pattern
|
||||
// Input: N qubits in an arbitrary state.
|
||||
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
|
||||
// with non-zero elements in positions where row and column indices have the same parity
|
||||
// and zero elements everywhere else.
|
||||
// Example: For N = 2, the matrix of the transformation should look as follows:
|
||||
// X.X.
|
||||
// .X.X
|
||||
// X.X.
|
||||
// .X.X
|
||||
operation EvenChessPattern (qs : Qubit[]) : Unit {
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
// Task 5. Odd chessboard pattern
|
||||
// Input: N qubits in an arbitrary state.
|
||||
// Goal: Implement a unitary transformation on N qubits which is represented by a matrix
|
||||
// with non-zero elements in positions where row and column indices have different parity
|
||||
// and zero elements everywhere else.
|
||||
// Example: For N = 2, the matrix of the transformation should look as follows:
|
||||
// .X.X
|
||||
// X.X.
|
||||
// .X.X
|
||||
// X.X.
|
||||
operation OddChessPattern (qs : Qubit[]) : Unit {
|
||||
// ...
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// This file contains parts of the testing harness.
|
||||
// You should not modify anything in this file.
|
||||
// The tasks themselves can be found in Tasks.qs file.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
using Microsoft.Quantum.Simulation.XUnit;
|
||||
using Microsoft.Quantum.Simulation.Simulators;
|
||||
using Xunit.Abstractions;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Quantum.Kata.UnitaryPatterns
|
||||
{
|
||||
public class TestSuiteRunner
|
||||
{
|
||||
private readonly ITestOutputHelper output;
|
||||
|
||||
public TestSuiteRunner(ITestOutputHelper output)
|
||||
{
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This driver will run all Q# tests (operations named "...Test")
|
||||
/// that belong to namespace Quantum.Kata.UnitaryPatterns.
|
||||
/// </summary>
|
||||
[OperationDriver(TestNamespace = "Quantum.Kata.UnitaryPatterns")]
|
||||
public void TestTarget(TestOperation op)
|
||||
{
|
||||
using (var sim = new CounterSimulator())
|
||||
{
|
||||
// OnLog defines action(s) performed when Q# test calls function Message
|
||||
sim.OnLog += (msg) => { output.WriteLine(msg); };
|
||||
sim.OnLog += (msg) => { Debug.WriteLine(msg); };
|
||||
op.TestOperationRunner(sim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// This file contains testing harness for all tasks.
|
||||
// You should not modify anything in this file.
|
||||
// The tasks themselves can be found in Tasks.qs file.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Quantum.Kata.UnitaryPatterns {
|
||||
|
||||
open Microsoft.Quantum.Primitive;
|
||||
open Microsoft.Quantum.Canon;
|
||||
open Microsoft.Quantum.Extensions.Convert;
|
||||
open Microsoft.Quantum.Extensions.Math;
|
||||
open Microsoft.Quantum.Extensions.Testing;
|
||||
open Microsoft.Quantum.Extensions.Diagnostics;
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Test harness: given an operation on N qubits and a function which takes two indices between 0 and 2^N-1
|
||||
// and returns false if the element of the matrix at that index is 0 and true if it is non-zero,
|
||||
// test that the operation implements a matrix of this shape
|
||||
operation AssertOperationMatrixMatchesPattern (N : Int, op : (Qubit[] => Unit), pattern : ((Int, Int, Int) -> Bool)) : Unit {
|
||||
let size = 1 <<< N;
|
||||
|
||||
//Message($"Testing on {N} qubits");
|
||||
let ε = 0.000001;
|
||||
|
||||
using (qs = Qubit[N]) {
|
||||
for (k in 0 .. size - 1) {
|
||||
// Prepare k-th basis vector
|
||||
let binary = BoolArrFromPositiveInt(k, N);
|
||||
|
||||
//Message($"{k}/{N} = {binary}");
|
||||
// binary is little-endian notation, so the second vector tried has qubit 0 in state 1 and the rest in state 0
|
||||
ApplyPauliFromBitString(PauliX, true, binary, qs);
|
||||
|
||||
// Reset the counter of measurements done outside of the solution call
|
||||
ResetOracleCallsCount();
|
||||
|
||||
// Apply the operation
|
||||
op(qs);
|
||||
|
||||
// Make sure the solution didn't use any measurements
|
||||
AssertIntEqual(GetOracleCallsCount(M), 0, "You are not allowed to use measurements in this task");
|
||||
AssertIntEqual(GetOracleCallsCount(Measure), 0, "You are not allowed to use measurements in this task");
|
||||
|
||||
// Test that the result matches the k-th column
|
||||
// DumpMachine($"C:/Tmp/dump{N}_{k}.txt");
|
||||
for (j in 0 .. size - 1) {
|
||||
let nonZero = pattern(size, j, k);
|
||||
|
||||
if (nonZero) {
|
||||
AssertProbInt(j, 0.5 + ε, LittleEndian(qs), 0.5);
|
||||
}
|
||||
else {
|
||||
AssertProbInt(j, 0.0, LittleEndian(qs), ε);
|
||||
}
|
||||
}
|
||||
|
||||
ResetAll(qs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
function MainDiagonal_Pattern (size : Int, row : Int, col : Int) : Bool {
|
||||
return row == col;
|
||||
}
|
||||
|
||||
|
||||
operation T01_MainDiagonal_Test () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
AssertOperationMatrixMatchesPattern(n, MainDiagonal, MainDiagonal_Pattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
function AllNonZero_Pattern (size : Int, row : Int, col : Int) : Bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
operation T02_AllNonZero_Test () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
AssertOperationMatrixMatchesPattern(n, AllNonZero, AllNonZero_Pattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
function Quarters_Pattern (size : Int, row : Int, col : Int) : Bool {
|
||||
// The indices are little-endian, with qubit 0 corresponding to the least significant bit
|
||||
// and qubits 1..N-1 corresponding to most significant bits.
|
||||
// The pattern of quarters corresponds to equality of the most significant bits of row and column (qubit N-1)
|
||||
return row / (size / 2) == col / (size / 2);
|
||||
}
|
||||
|
||||
|
||||
operation T03_Quarters_Test () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
AssertOperationMatrixMatchesPattern(n, Quarters, Quarters_Pattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
function EvenChessPattern_Pattern (size : Int, row : Int, col : Int) : Bool {
|
||||
// The indices are little-endian, qubit 0 corresponding to the least significant bit
|
||||
// and qubits 1..N-1 corresponding to most significant bits.
|
||||
// The chessboard pattern corresponds to equality of the least significant bits of row and column (qubit 0)
|
||||
return row % 2 == col % 2;
|
||||
}
|
||||
|
||||
|
||||
operation T04_EvenChessPattern_Test () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
AssertOperationMatrixMatchesPattern(n, EvenChessPattern, EvenChessPattern_Pattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
function OddChessPattern_Pattern (size : Int, row : Int, col : Int) : Bool {
|
||||
// The indices are little-endian, qubit 0 corresponding to the least significant bit
|
||||
// and qubits 1..N-1 corresponding to most significant bits.
|
||||
// The chessboard pattern corresponds to inequality of the least significant bits of row and column (qubit 0)
|
||||
return row % 2 != col % 2;
|
||||
}
|
||||
|
||||
|
||||
operation T05_OddChessPattern_Test () : Unit {
|
||||
for (n in 2 .. 5) {
|
||||
AssertOperationMatrixMatchesPattern(n, OddChessPattern, OddChessPattern_Pattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
function GetOracleCallsCount<'T> (oracle : 'T) : Int { return 0; }
|
||||
|
||||
function ResetOracleCallsCount () : Unit { }
|
||||
|
||||
function GetMaxQubitCount () : Int { return 0; }
|
||||
|
||||
function ResetQubitCount () : Unit { }
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<IsPackable>false</IsPackable>
|
||||
<RootNamespace>Quantum.Kata.UnitaryPatterns</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.4.1901.3104" />
|
||||
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.4.1901.3104" />
|
||||
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.4.1901.3104" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.3.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="README.md" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2036
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitaryPatterns", "UnitaryPatterns.csproj", "{4BAAB76A-ABFA-4F5C-9E5B-788BB3E8647E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4BAAB76A-ABFA-4F5C-9E5B-788BB3E8647E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4BAAB76A-ABFA-4F5C-9E5B-788BB3E8647E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4BAAB76A-ABFA-4F5C-9E5B-788BB3E8647E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4BAAB76A-ABFA-4F5C-9E5B-788BB3E8647E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7CB0806C-1BBF-4E0C-BDFC-04A9A068F41C}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
|
||||
using Microsoft.Quantum.Simulation.Simulators;
|
||||
|
||||
namespace Quantum.DumpUnitary
|
||||
{
|
||||
class Driver
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
double eps = 1E-5; // the square of the absolute value of the amplitude has to be less than or equal to eps^2 to be considered 0
|
||||
|
||||
int N = 3; // the number of qubits on which the unitary acts
|
||||
using (var qsim = new QuantumSimulator())
|
||||
{
|
||||
CallDumpUnitary.Run(qsim, N).Wait();
|
||||
}
|
||||
|
||||
// read the content of the files and store it in a single unitary
|
||||
int size = 1 << N;
|
||||
string[,] unitary = new string[size, size];
|
||||
string[] unitaryPattern = new string[size];
|
||||
for (int column = 0; column < size; ++column) {
|
||||
string fileName = $"DU_{N}_{column}.txt";
|
||||
string[] fileContent = System.IO.File.ReadAllLines(fileName);
|
||||
for (int row = 0; row < size; ++row) {
|
||||
// skip the first line of the file (header)
|
||||
string line = fileContent[row + 1];
|
||||
// split the line into 3 space-separated elements: index, real part and complex part
|
||||
string[] parts = line.Split('\t');
|
||||
// drop the index and store real and complex parts
|
||||
string real = parts[1];
|
||||
string complex = parts[2];
|
||||
// write the number to the matrix as a string "(real, complex)"
|
||||
unitary[column, row] = $"({real}, {complex})";
|
||||
// for a pattern, convert real and complex parts into doubles and add them up
|
||||
double amplitudeSquare = Math.Pow(double.Parse(real), 2) + Math.Pow(double.Parse(complex), 2);
|
||||
unitaryPattern[row] += (amplitudeSquare > eps * eps) ? 'X' : '.';
|
||||
}
|
||||
// clean up the file with individual amplitudes
|
||||
System.IO.File.Delete(fileName);
|
||||
}
|
||||
|
||||
// print the combined unitary to a file
|
||||
string[] outputLines = new string[size];
|
||||
for (int row = 0; row < size; ++row) {
|
||||
outputLines[row] = unitary[row, 0];
|
||||
for (int col = 1; col < size; ++col) {
|
||||
outputLines[row] += "\t" + unitary[row, col];
|
||||
}
|
||||
}
|
||||
System.IO.File.WriteAllLines("DumpUnitary.txt", outputLines);
|
||||
|
||||
System.IO.File.WriteAllLines("DumpUnitaryPattern.txt", unitaryPattern);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="README.md" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Quantum.Canon" Version="0.4.1901.3104" />
|
||||
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.4.1901.3104" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28010.2048
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DumpUnitary", "DumpUnitary.csproj", "{3C9C8FE0-2BF7-4D61-B8CF-1038F18FA4CD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3C9C8FE0-2BF7-4D61-B8CF-1038F18FA4CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3C9C8FE0-2BF7-4D61-B8CF-1038F18FA4CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3C9C8FE0-2BF7-4D61-B8CF-1038F18FA4CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3C9C8FE0-2BF7-4D61-B8CF-1038F18FA4CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8AA4DE96-4B44-46A3-AC24-C6A90CFB86D6}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Quantum.DumpUnitary
|
||||
{
|
||||
open Microsoft.Quantum.Primitive;
|
||||
open Microsoft.Quantum.Canon;
|
||||
open Microsoft.Quantum.Extensions.Diagnostics;
|
||||
|
||||
operation DumpUnitaryToFiles (N : Int, unitary : (Qubit[] => Unit)) : Unit {
|
||||
let size = 1 <<< N;
|
||||
|
||||
using (qs = Qubit[N]) {
|
||||
for (k in 0 .. size - 1) {
|
||||
// Prepare k-th basis vector
|
||||
let binary = BoolArrFromPositiveInt(k, N);
|
||||
|
||||
//Message($"{k}/{N} = {binary}");
|
||||
// binary is little-endian notation, so the second vector tried has qubit 0 in state 1 and the rest in state 0
|
||||
ApplyPauliFromBitString(PauliX, true, binary, qs);
|
||||
|
||||
// Apply the operation
|
||||
unitary(qs);
|
||||
|
||||
// Dump the contents of the k-th column
|
||||
DumpMachine($"DU_{N}_{k}.txt");
|
||||
|
||||
ResetAll(qs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The operation which is called from C# code
|
||||
operation CallDumpUnitary (N : Int) : Unit {
|
||||
// make sure the operation passed to DumpUnitaryToFiles matches the number of qubits set in Driver.cs
|
||||
let unitary = ApplyToEach(I, _);
|
||||
|
||||
DumpUnitaryToFiles(N, unitary);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# DumpUnitary tool
|
||||
|
||||
This is a simple tool to help you work through the tasks in the UnitaryPatterns kata. It dumps the pattern implemented by the provided operation ("DumpUnitaryPattern.txt") and the matrix of complex numbers from which the pattern has been obtained ("DumpUnitary.txt"). The row/column ordering and the conversion of the matrix into the pattern follow the description in the kata.
|
||||
|
||||
**Note 1.** The columns of the matrix are obtained independently, and the relative phase between the columns is not preserved. Thus the matrix dumped might differ from the actual unitary implemented in phases of the entries (the absolute values of the amplitudes are preserved).
|
||||
|
||||
**Note 2.** The tool does not verify that the operation you provided is a unitary; it will process operations which use measurements, even though their results might not be unitary.
|
Загрузка…
Ссылка в новой задаче