Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

quantum counting algorithm #168

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Counting/Counting.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<IsPackable>false</IsPackable>
<RootNamespace>Quantum.Kata.Counting</RootNamespace>
<AssemblyName>Counting</AssemblyName>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.8.1907.1701" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.8.1907.1701" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.8.1907.1701" />
<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>
316 changes: 316 additions & 0 deletions Counting/Counting.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Counting\n",
"\n",
"\n",
"\n",
"The **Quantum Counting** quantum kata is a series of exercises designed\n",
"to get you familiar with quantum counting algorithm.\n",
"\n",
"It covers the following topics:\n",
"\n",
"* writing oracles for counting,\n",
"* performing actual counting.\n",
" \n",
"\n",
"*Reading material:*\n",
"\n",
"* The tasks follow the explanation from *Quantum Computation and Quantum Information* by Nielsen and Chuang.\n",
" In the 10th anniversary edition, this is section 6.3 on pages 261-263.\n",
" \n",
"Each task is wrapped in one operation preceded by the description of the task.\n",
"Your goal is to fill in the blanks (marked with the `// ...` comments)\n",
"with some Q# code that solves the task. To verify your answer, run the cell with Ctrl/⌘+Enter.\n",
"\n",
"Within each section, tasks are given in approximate order of increasing difficulty;\n",
"harder ones are marked with asterisks."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To begin, first prepare this notebook for execution (if you skip this step, you'll get \"Syntax does not match any known patterns\" error when you try to execute Q# code in the next cells):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%package Microsoft.Quantum.Katas::0.8.1907.1701\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.\n",
"> <details>\n",
"> <summary><u>How to install the right IQ# version</u></summary>\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.1.2.3, the installation steps are as follows:\n",
">\n",
"> 1. Stop the kernel.\n",
"> 2. Uninstall the existing version of IQ#:\n",
"> dotnet tool uninstall microsoft.quantum.iqsharp -g\n",
"> 3. Install the matching version:\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.1.2.3\n",
"> 4. Reinstall the kernel:\n",
"> dotnet iqsharp install\n",
"> 5. Restart the Notebook.\n",
"> </details>\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Part I. Oracle Counting\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Task 1.1. The Sprinkler oracle\n",
"\n",
"Let us consider an example inspired by the sprinkler problem of (Pearl 1988): \n",
"we have three Boolean variable, $s$, $r$, $w$ representing respectively propositions \n",
"“the sprinkler was on”, \"ıt rained last night” and “the grass is wet”. \n",
"We know that if the sprinkler was on the grass is wet ($s \\to w$), \n",
"if it rained last night the grass is wet ($r \\to w$) \n",
"and that the the sprinkler being on and rain last night cannot be true at the same time ($s, r \\to$).\n",
"Transformed in conjunctive normal formal we obtain formula $(\\neg s \\vee w) \\wedge (\\neg r \\vee w) \\wedge\n",
"(\\neg s \\vee \\neg r)$.\n",
"Let $s,r,w$=`queryRegister[0],queryRegister[1],queryRegister[2]`\n",
"Hint: to solve this task you also need to use ancilla qubits\n",
"This formula has 4 models out of 8 possible worlds.\n",
"\n",
"<br/>\n",
"<details>\n",
" <summary>Need a hint? Click here </summary>\n",
" Here is what the circuit looks like\n",
"<img src=\"sprinkler.png\" />\n",
"</details>\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/snippet:(1,26): error QS6104: No namespace with that name exists.\n",
"/snippet:(3,10): error QS6104: No namespace with that name exists.\n",
"/snippet:(14,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(15,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(16,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(17,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(19,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(20,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(21,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(22,17): error QS5022: No identifier with that name exists.\n",
"/snippet:(23,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(24,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(25,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(27,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(28,5): error QS5022: No identifier with that name exists.\n",
"/snippet:(29,5): error QS5022: No identifier with that name exists.\n"
]
}
],
"source": [
"%kata T11_Oracle_Sprinkler_Test \n",
"\n",
"\n",
"operation Oracle_Sprinkler (queryRegister : Qubit[], target : Qubit, ancilla : Qubit[]) : Unit\n",
" { \n",
"\t body (...) {\n",
"\t\t\t\tX(queryRegister[2]);\n",
"\t\t\t\tX(ancilla[0]);\n",
"\t\t\t\tX(ancilla[1]);\n",
"\t\t\t\tX(ancilla[2]);\n",
" \n",
"\t\t\t\tCCNOT(queryRegister[0],queryRegister[1],ancilla[0]);\n",
"\t\t\t\tCCNOT(queryRegister[1],queryRegister[2],ancilla[1]);\n",
"\t\t\t\tCCNOT(queryRegister[0],queryRegister[2],ancilla[2]);\n",
"\t\t\t\t(Controlled X)([ancilla[0],ancilla[1],ancilla[2]],target);\n",
"\t\t\t\tCCNOT(queryRegister[0],queryRegister[2],ancilla[2]);\n",
"\t\t\t\tCCNOT(queryRegister[1],queryRegister[2],ancilla[1]);\n",
"\t\t\t\tCCNOT(queryRegister[0],queryRegister[1],ancilla[0]);\n",
"\n",
"\t\t\t\tX(ancilla[2]);\n",
"\t\t\t\tX(ancilla[1]);\n",
"\t\t\t\tX(ancilla[0]); \n",
" }\n",
"\t\t\tadjoint invert;\n",
"\t\t\tcontrolled auto;\n",
"\t\t\tcontrolled adjoint auto;\n",
" }"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## Part II. Counting"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Task 2.1. Implement counting using operations from ReferenceImplementation.qs\n",
"* UnitaryPowerImpl, for computing powers of a unitary operation\n",
"* GroverIteration for the Grover operator\n",
"* QuantumPhaseEstimation, for estimating the phase\n",
"* Counting should return the number of models, 4 in this case\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/snippet:(1,26): error QS6104: No namespace with that name exists.\n",
"/snippet:(7,27): error QS5022: No identifier with that name exists.\n",
"/snippet:(7,43): error QS5022: No identifier with that name exists.\n",
"/snippet:(9,22): error QS5022: No identifier with that name exists.\n",
"/snippet:(9,37): error QS5022: No identifier with that name exists.\n",
"/snippet:(9,54): error QS5022: No identifier with that name exists.\n",
"/snippet:(14,35): error QS5022: No identifier with that name exists.\n",
"/snippet:(16,17): error QS5022: No identifier with that name exists.\n",
"/snippet:(19,13): error QS5022: No identifier with that name exists.\n",
"/snippet:(21,25): error QS5022: No identifier with that name exists.\n",
"/snippet:(21,37): error QS5022: No identifier with that name exists.\n",
"/snippet:(21,52): error QS5022: No identifier with that name exists.\n",
"/snippet:(21,97): error QS5022: No identifier with that name exists.\n",
"/snippet:(23,13): error QS5022: No identifier with that name exists.\n",
"/snippet:(24,13): error QS5022: No identifier with that name exists.\n",
"/snippet:(26,21): error QS5022: No identifier with that name exists.\n",
"/snippet:(27,20): error QS5022: No identifier with that name exists.\n",
"/snippet:(27,25): error QS5022: No identifier with that name exists.\n"
]
}
],
"source": [
" operation Counting() : Double {\n",
" mutable phase = -1.0;\n",
" let n=4;\n",
" using ((reg,phaseRegister,ancilla)=(Qubit[3],Qubit[n],Qubit[3]))\n",
" {\n",
" // Construct a phase estimation oracle from the unitary\n",
" let phaseOracle = OracleConverter(Oracle_Sprinkler_Reference(_,_,ancilla));\n",
"\n",
" let oracle = DiscreteOracle(UnitaryPowerImpl(GroverIteration(_, phaseOracle), _, _));\n",
"\n",
"\n",
" // Allocate qubits to hold the eigenstate of U and the phase in a big endian register \n",
" \n",
" let phaseRegisterBE = BigEndian(phaseRegister);\n",
" // Prepare the eigenstate of U\n",
" HadamardTransform(reg);\n",
"//should return 0.5\n",
" // Call library\n",
" QuantumPhaseEstimation(oracle, reg, phaseRegisterBE);\n",
" // Read out the phase\n",
" set phase = IntAsDouble(MeasureInteger(BigEndianAsLittleEndian(phaseRegisterBE))) / IntAsDouble(1 <<< (n));\n",
"\n",
" ResetAll(reg);\n",
" ResetAll(phaseRegister);\n",
" }\n",
" let angle = PI()*phase;\n",
" let res = (PowD(Sin(angle),2.0));\n",
"\n",
" return 8.0*res;\n",
" }\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Task 3.2. Using Counting \n",
"\n",
"**Goal:** Use your implementation of Counting from Task 2.1 and the oracle from part 1\n",
" to find the number of solutions of the sprinkler problem. This task is not covered by a test and allows you to experiment with running the algorithm.\n",
" \n",
"> This is an open-ended task, and is not covered by a unit test. To run the code, execute the cell with the definition of the `Run_Counting` operation first; if it compiled successfully without any errors, you can run the operation by executing the next cell (`%simulate Run_GroversSearch_Algorithm`).\n",
"\n",
"> Note that this task relies on your implementations of the previous tasks. If you are getting the \"No variable with that name exists.\" error, you might have to execute previous code cells before retrying this task.\n",
"\n",
"<br/>\n",
"<details closed>\n",
" <summary>Hint #3</summary>\n",
" You can use the Message function to output the results.\n",
"</details>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
" operation Run_Counting() : Unit {\n",
"\n",
"\t\tlet res=Counting();\n",
" Message(DoubleAsString(res));\n",
"\n",
" }\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Invalid operation name: Run_Counting\n"
]
}
],
"source": [
"%simulate Run_Counting"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Q#",
"language": "qsharp",
"name": "iqsharp"
},
"language_info": {
"file_extension": ".qs",
"mimetype": "text/x-qsharp",
"name": "qsharp",
"version": "0.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
25 changes: 25 additions & 0 deletions Counting/Counting.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28729.10
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Counting", "Counting.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
11 changes: 11 additions & 0 deletions Counting/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Welcome!

The Counting kata covers the quantum counting algorithm, which is based on Grover's search algorithm.
It solves the problem of computing the number of assignments of Boolean input variables
that make a Boolean function (oracle) true.

#### Theory

* The tasks follow the explanation from *Quantum Computation and Quantum Information* by Nielsen and Chuang.
In the 10th anniversary edition, this is section 6.3 on pages 261-263.

Loading