├── .devcontainer └── devcontainer.json ├── .github └── workflows │ ├── docs.yml │ ├── publish.yml │ └── test.yml ├── .gitignore ├── .vscode └── extensions.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── QRam.sln ├── README.md ├── docfx.json ├── docs ├── api │ ├── .gitignore │ └── index.md ├── articles │ ├── intro.md │ └── toc.yml ├── images │ ├── basic-qrom-exorcised.eps │ ├── basic-qrom.eps │ ├── basicbb-qram-notes.jpg │ ├── basicbb-qram.png │ ├── bb-00.eps │ ├── bb-01.eps │ ├── bb-02.eps │ ├── bb-03.eps │ ├── bb-2qubit-3bitout.eps │ ├── bb-combined.eps │ ├── bb.gif │ ├── bb_2address_ccz_full.eps │ ├── bb_2address_cczfanout.eps │ ├── bb_3address_ccz_full.eps │ ├── bb_3address_cczfanout.eps │ ├── bb_phase_query.eps │ ├── ccz-clifford-t.eps │ ├── ccz-simplification.eps │ ├── ccz.eps │ ├── constant-bb-useful-identities.eps │ ├── docs.png │ ├── exorcism-t-count.pdf │ ├── exorcism-t-depth.pdf │ ├── fanout-ram-queried.eps │ ├── fanout-ram.eps │ ├── github-screencap.png │ ├── intellisense.png │ ├── kaiser-bio.png │ ├── matt-toffoli-decomp.png │ ├── memory-models.eps │ ├── milestones.png │ ├── olivia-talk-title.png │ ├── qram-cover.png │ ├── qrom-code.png │ ├── qsc-projects.png │ ├── sarah-twitch.png │ ├── select-swap-lambda-1.eps │ ├── select-swap-lambda-2.eps │ ├── select-swap-lambda-3.eps │ ├── select-swap-only-select.eps │ ├── src-screenshot.png │ ├── superposition-query.png │ ├── tests-screenshot.png │ ├── tests-vs-screenshot.png │ └── toffoli.eps ├── index.md ├── presentation.ipynb ├── primer.bib ├── primer.pdf ├── primer.tex ├── project_plan.md ├── rise.css └── toc.yml ├── environment.yml ├── samples ├── BucketBrigade │ ├── BucketBrigadeSample.csproj │ └── BucketBrigadeSample.qs ├── Grover │ ├── Grover.csproj │ ├── Grover.qs │ └── Reflections.qs ├── Python-ResourceEstimation │ ├── Exorcism-Estimates.ipynb │ ├── abc.md │ ├── analysis.py │ ├── exorcised_resources.csv │ ├── guessed_resources.csv │ ├── mpmct_resources.py │ ├── parse_pla.py │ ├── test_exorcisms │ │ ├── all_max.exorcised │ │ ├── all_min.exorcised │ │ ├── one_each.exorcised │ │ └── random.exorcised │ └── test_parse_pla.py ├── Qrom │ ├── QromSample.csproj │ ├── QromSample.ipynb │ └── QromSample.qs ├── ResourceEstimation │ ├── Operations.qs │ ├── QromEstimation.ipynb │ ├── ResourceEstimation.cs │ └── ResourceEstimation.csproj └── SelectSwap │ ├── SelectSwapSample.csproj │ └── SelectSwapSample.qs ├── src ├── BucketBrigade.qs ├── Common.qs ├── Qrom.qs ├── Select.qs ├── SelectSwapQrom.qs └── qram.csproj └── tests ├── BucketBrigadeBit.qs ├── BucketBrigadePhase.qs ├── CommonTest.qs ├── QromTest.qs ├── SelectSwapTest.qs ├── SelectTest.qs └── tests.csproj /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "dockerFile": "../Dockerfile", 3 | "extensions": [ 4 | "quantum.quantum-devkit-vscode", 5 | "ms-vscode.csharp", 6 | "editorconfig.editorconfig", 7 | "ms-python.python" 8 | ], 9 | "remoteEnv": { 10 | "IQSHARP_HOSTING_ENV": "QRAM_DEVCONTAINER" 11 | } 12 | } -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Update Docs 2 | 3 | on: 4 | pull_request: 5 | branches: [ master ] 6 | paths: 7 | - 'docs/*' 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 14 | - uses: actions/checkout@v2 15 | 16 | - uses: xu-cheng/latex-action@v2 17 | with: 18 | working_directory: docs 19 | root_file: primer.tex 20 | compiler: pdflatex 21 | 22 | - uses: actions/upload-artifact@v2 23 | with: 24 | name: primer-notes 25 | path: docs/primer.pdf 26 | 27 | # - name: Add & Commit 28 | # uses: EndBug/add-and-commit@v4.4.0 29 | # with: 30 | # # Arguments for the git add command 31 | # add: docs/primer.pdf 32 | # # The name of the user that will be displayed as the author of the commit 33 | # author_name: GitHubActionsBot 34 | # # The directory where your repository is located. You should use actions/checkout first to set it up 35 | # #cwd: # optional, default is . 36 | # # Whether to use the force option on git add, in order to bypass eventual gitignores 37 | # #force: # optional, default is false 38 | # # The message for the commit 39 | # message: "Updating primer.pdf" 40 | # # Name of the branch to use, if different from the one that triggered the workflow 41 | # #ref: docs 42 | # # Arguments for the git rm command 43 | # #remove: # optional, default is 44 | # # The name of the tag to add to the new commit 45 | # tag: docs-bot 46 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Publish to GitHub Packages 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | push: 9 | branches: [ master ] 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | # This workflow contains a single job called "build" 14 | build: 15 | # The type of runner that the job will run on 16 | runs-on: windows-latest 17 | 18 | # Steps represent a sequence of tasks that will be executed as part of the job 19 | steps: 20 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 21 | - uses: actions/checkout@v2 22 | # https://stackoverflow.com/questions/57889719/how-to-push-nuget-package-in-github-actions 23 | - name: "Setup .NET Core @ Latest" 24 | uses: actions/setup-dotnet@v1 25 | with: 26 | dotnet-version: '3.1.x' 27 | source-url: https://nuget.pkg.github.com/qsharp-community/index.json 28 | env: 29 | NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} 30 | 31 | # Runs a set of commands using the runners shell 32 | - name: .NET pack 33 | run: dotnet pack -c Release -o ../drop /p:Version="0.1.$Env:GITHUB_RUN_NUMBER" 34 | shell: pwsh 35 | working-directory: src 36 | 37 | - name: Push to GitHub Packages 38 | run: dotnet nuget push (Join-Path "drop" "*.nupkg") 39 | shell: pwsh 40 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Tests 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | workflow_dispatch: 9 | pull_request: 10 | branches: [ master ] 11 | 12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 13 | jobs: 14 | # This workflow contains a single job called "build" 15 | build: 16 | # The type of runner that the job will run on 17 | runs-on: ubuntu-latest 18 | 19 | # Steps represent a sequence of tasks that will be executed as part of the job 20 | steps: 21 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 22 | - uses: actions/checkout@v2 23 | 24 | # Runs a set of commands using the runners shell 25 | - name: .NET tests 26 | run: dotnet test 27 | working-directory: tests 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # DocFX 2 | _site/ 3 | docs/apidoc/ 4 | 5 | # Python temporary files 6 | .ipynb_checkpoints 7 | .pytest_cache 8 | 9 | # Git ignore file for the Solid project 10 | 11 | # Build artifacts 12 | *.g.cs 13 | bin/ 14 | obj/ 15 | Documentation/Help/ 16 | packages/ 17 | *.obj 18 | *.dll 19 | *.pdb 20 | *.exe 21 | *.chm 22 | 23 | # test outputs 24 | TestResults/ 25 | *.qxe 26 | 27 | # Random VS files 28 | *.suo 29 | *.vssscc 30 | *.vspscc 31 | UpgradeLog.htm 32 | 33 | # Random non-solution files 34 | ~$Solid.docx 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | ## 39 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 40 | 41 | # User-specific files 42 | *.suo 43 | *.user 44 | *.userosscache 45 | *.sln.docstates 46 | 47 | # User-specific files (MonoDevelop/Xamarin Studio) 48 | *.userprefs 49 | 50 | # Build results 51 | [Dd]ebug/ 52 | [Dd]ebugPublic/ 53 | [Rr]elease/ 54 | [Rr]eleases/ 55 | x64/ 56 | x86/ 57 | bld/ 58 | [Bb]in/ 59 | [Oo]bj/ 60 | [Ll]og/ 61 | 62 | # Visual Studio 2015 cache/options directory 63 | .vs/ 64 | # Uncomment if you have tasks that create the project's static files in wwwroot 65 | #wwwroot/ 66 | 67 | # MSTest test Results 68 | [Tt]est[Rr]esult*/ 69 | [Bb]uild[Ll]og.* 70 | 71 | # NUNIT 72 | *.VisualState.xml 73 | TestResult.xml 74 | 75 | # Build Results of an ATL Project 76 | [Dd]ebugPS/ 77 | [Rr]eleasePS/ 78 | dlldata.c 79 | 80 | # Benchmark Results 81 | BenchmarkDotNet.Artifacts/ 82 | 83 | # .NET Core 84 | project.lock.json 85 | project.fragment.lock.json 86 | artifacts/ 87 | **/Properties/launchSettings.json 88 | 89 | *_i.c 90 | *_p.c 91 | *_i.h 92 | *.ilk 93 | *.meta 94 | *.obj 95 | *.pch 96 | *.pdb 97 | *.pgc 98 | *.pgd 99 | *.rsp 100 | *.sbr 101 | *.tlb 102 | *.tli 103 | *.tlh 104 | *.tmp 105 | *.tmp_proj 106 | *.log 107 | *.vspscc 108 | *.vssscc 109 | .builds 110 | *.pidb 111 | *.svclog 112 | *.scc 113 | 114 | # Chutzpah Test files 115 | _Chutzpah* 116 | 117 | # Visual C++ cache files 118 | ipch/ 119 | *.aps 120 | *.ncb 121 | *.opendb 122 | *.opensdf 123 | *.sdf 124 | *.cachefile 125 | *.VC.db 126 | *.VC.VC.opendb 127 | 128 | # Visual Studio profiler 129 | *.psess 130 | *.vsp 131 | *.vspx 132 | *.sap 133 | 134 | # TFS 2012 Local Workspace 135 | $tf/ 136 | 137 | # Guidance Automation Toolkit 138 | *.gpState 139 | 140 | # ReSharper is a .NET coding add-in 141 | _ReSharper*/ 142 | *.[Rr]e[Ss]harper 143 | *.DotSettings.user 144 | 145 | # JustCode is a .NET coding add-in 146 | .JustCode 147 | 148 | # TeamCity is a build add-in 149 | _TeamCity* 150 | 151 | # DotCover is a Code Coverage Tool 152 | *.dotCover 153 | 154 | # AxoCover is a Code Coverage Tool 155 | .axoCover/* 156 | !.axoCover/settings.json 157 | 158 | # Visual Studio code coverage results 159 | *.coverage 160 | *.coveragexml 161 | 162 | # NCrunch 163 | _NCrunch_* 164 | .*crunch*.local.xml 165 | nCrunchTemp_* 166 | 167 | # MightyMoose 168 | *.mm.* 169 | AutoTest.Net/ 170 | 171 | # Web workbench (sass) 172 | .sass-cache/ 173 | 174 | # Installshield output folder 175 | [Ee]xpress/ 176 | 177 | # DocProject is a documentation generator add-in 178 | DocProject/buildhelp/ 179 | DocProject/Help/*.HxT 180 | DocProject/Help/*.HxC 181 | DocProject/Help/*.hhc 182 | DocProject/Help/*.hhk 183 | DocProject/Help/*.hhp 184 | DocProject/Help/Html2 185 | DocProject/Help/html 186 | 187 | # Click-Once directory 188 | publish/ 189 | 190 | # Publish Web Output 191 | *.[Pp]ublish.xml 192 | *.azurePubxml 193 | # Note: Comment the next line if you want to checkin your web deploy settings, 194 | # but database connection strings (with potential passwords) will be unencrypted 195 | *.pubxml 196 | *.publishproj 197 | 198 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 199 | # checkin your Azure Web App publish settings, but sensitive information contained 200 | # in these scripts will be unencrypted 201 | PublishScripts/ 202 | 203 | # NuGet Packages 204 | *.nupkg 205 | # The packages folder can be ignored because of Package Restore 206 | **/packages/* 207 | # except build/, which is used as an MSBuild target. 208 | !**/packages/build/ 209 | # Uncomment if necessary however generally it will be regenerated when needed 210 | #!**/packages/repositories.config 211 | # NuGet v3's project.json files produces more ignorable files 212 | *.nuget.props 213 | *.nuget.targets 214 | 215 | # Microsoft Azure Build Output 216 | csx/ 217 | *.build.csdef 218 | 219 | # Microsoft Azure Emulator 220 | ecf/ 221 | rcf/ 222 | 223 | # Windows Store app package directories and files 224 | AppPackages/ 225 | BundleArtifacts/ 226 | Package.StoreAssociation.xml 227 | _pkginfo.txt 228 | *.appx 229 | 230 | # Visual Studio cache files 231 | # files ending in .cache can be ignored 232 | *.[Cc]ache 233 | # but keep track of directories ending in .cache 234 | !*.[Cc]ache/ 235 | 236 | # Others 237 | ClientBin/ 238 | ~$* 239 | *~ 240 | *.dbmdl 241 | *.dbproj.schemaview 242 | *.jfm 243 | *.pfx 244 | *.publishsettings 245 | orleans.codegen.cs 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | 262 | # SQL Server files 263 | *.mdf 264 | *.ldf 265 | *.ndf 266 | 267 | # Business Intelligence projects 268 | *.rdl.data 269 | *.bim.layout 270 | *.bim_*.settings 271 | 272 | # Microsoft Fakes 273 | FakesAssemblies/ 274 | 275 | # GhostDoc plugin setting file 276 | *.GhostDoc.xml 277 | 278 | # Node.js Tools for Visual Studio 279 | .ntvs_analysis.dat 280 | node_modules/ 281 | 282 | # Typescript v1 declaration files 283 | typings/ 284 | 285 | # Visual Studio 6 build log 286 | *.plg 287 | 288 | # Visual Studio 6 workspace options file 289 | *.opt 290 | 291 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 292 | *.vbw 293 | 294 | # Visual Studio LightSwitch build output 295 | **/*.HTMLClient/GeneratedArtifacts 296 | **/*.DesktopClient/GeneratedArtifacts 297 | **/*.DesktopClient/ModelManifest.xml 298 | **/*.Server/GeneratedArtifacts 299 | **/*.Server/ModelManifest.xml 300 | _Pvt_Extensions 301 | 302 | # Paket dependency manager 303 | .paket/paket.exe 304 | paket-files/ 305 | 306 | # FAKE - F# Make 307 | .fake/ 308 | 309 | # JetBrains Rider 310 | .idea/ 311 | *.sln.iml 312 | 313 | # CodeRush 314 | .cr/ 315 | 316 | # Python Tools for Visual Studio (PTVS) 317 | __pycache__/ 318 | *.pyc 319 | 320 | # Cake - Uncomment if you are using it 321 | # tools/** 322 | # !tools/packages.config 323 | 324 | # Tabs Studio 325 | *.tss 326 | 327 | # Telerik's JustMock configuration file 328 | *.jmconfig 329 | 330 | # BizTalk build output 331 | *.btp.cs 332 | *.btm.cs 333 | *.odx.cs 334 | *.xsd.cs 335 | 336 | # Really random 337 | *.ionide 338 | 339 | ## Core latex/pdflatex auxiliary files: 340 | *.aux 341 | *.lof 342 | *.log 343 | *.lot 344 | *.fls 345 | *.out 346 | *.toc 347 | *.fmt 348 | *.fot 349 | *.cb 350 | *.cb2 351 | .*.lb 352 | 353 | ## Build tool auxiliary files: 354 | *.fdb_latexmk 355 | *.synctex 356 | *.synctex(busy) 357 | *.synctex.gz 358 | *.synctex.gz(busy) 359 | *.pdfsync 360 | 361 | ## Intermediate documents: 362 | *.dvi 363 | *.xdv 364 | *-converted-to.* 365 | # these rules might exclude image files for figures etc. 366 | # *.ps 367 | # *.eps 368 | # Allow PDFs in fig/. 369 | !fig/*.pdf 370 | 371 | ## Bibliography auxiliary files (bibtex/biblatex/biber): 372 | *.bbl 373 | *.bcf 374 | *.blg 375 | *-blx.aux 376 | *-blx.bib 377 | *.run.xml 378 | *Notes.bib 379 | 380 | ## Images 381 | *.png 382 | *.svg 383 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "quantum.quantum-devkit-vscode", 8 | "ms-python.python", 9 | "GitHub.vscode-pull-request-github", 10 | "donjayamanne.githistory", 11 | "eamodio.gitlens", 12 | "cschleiden.vscode-github-actions", 13 | "ms-vsliveshare.vsliveshare", 14 | "ms-vscode-remote.vscode-remote-extensionpack" 15 | ], 16 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 17 | "unwantedRecommendations": [ 18 | 19 | ] 20 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at sckaiser@sckaiser.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of at least one other developers, or if you 17 | do not have permission to do that, you may request the reviewer to merge it for you. 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/quantum/iqsharp-base:0.15.2101125897 2 | 3 | ENV IQSHARP_HOSTING_ENV=QRAM_DOCKER 4 | USER root 5 | RUN pip install RISE 6 | 7 | # Make sure the contents of our repo are in ${HOME}. 8 | # These steps are required for use on mybinder.org. 9 | COPY . ${HOME} 10 | RUN chown -R ${USER} ${HOME} 11 | 12 | # Drop back down to user permissions for things that don't need it. 13 | USER ${USER} 14 | 15 | RUN mkdir ${HOME}/local-nuget && \ 16 | dotnet nuget add source ${HOME}/local-nuget -n "Qram" && \ 17 | dotnet pack ${HOME}/src/qram.csproj && \ 18 | cp ${HOME}/src/bin/Debug/*.nupkg ${HOME}/local-nuget && \ 19 | pip install numpy matplotlib 20 | 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Q# Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /QRam.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30330.147 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qram", "src\qram.csproj", "{DDD89D88-1484-4D86-B18C-F9267AB73C74}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tests", "tests\tests.csproj", "{F0398818-74CB-4B47-981B-39CA7B214E5A}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{BC9A489D-88AF-4DE2-A3EE-F31A1FE47D7A}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QromSample", "samples\Qrom\QromSample.csproj", "{7DAD2361-E333-4076-B840-FACA90D354F7}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BucketBrigadeSample", "samples\BucketBrigade\BucketBrigadeSample.csproj", "{187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Debug|x64 = Debug|x64 20 | Debug|x86 = Debug|x86 21 | Release|Any CPU = Release|Any CPU 22 | Release|x64 = Release|x64 23 | Release|x86 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Debug|x64.ActiveCfg = Debug|Any CPU 29 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Debug|x64.Build.0 = Debug|Any CPU 30 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Debug|x86.ActiveCfg = Debug|Any CPU 31 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Debug|x86.Build.0 = Debug|Any CPU 32 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Release|x64.ActiveCfg = Release|Any CPU 35 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Release|x64.Build.0 = Release|Any CPU 36 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Release|x86.ActiveCfg = Release|Any CPU 37 | {DDD89D88-1484-4D86-B18C-F9267AB73C74}.Release|x86.Build.0 = Release|Any CPU 38 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Debug|x64.ActiveCfg = Debug|Any CPU 41 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Debug|x64.Build.0 = Debug|Any CPU 42 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Debug|x86.ActiveCfg = Debug|Any CPU 43 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Debug|x86.Build.0 = Debug|Any CPU 44 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Release|x64.ActiveCfg = Release|Any CPU 47 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Release|x64.Build.0 = Release|Any CPU 48 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Release|x86.ActiveCfg = Release|Any CPU 49 | {F0398818-74CB-4B47-981B-39CA7B214E5A}.Release|x86.Build.0 = Release|Any CPU 50 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Debug|x64.ActiveCfg = Debug|Any CPU 53 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Debug|x64.Build.0 = Debug|Any CPU 54 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Debug|x86.ActiveCfg = Debug|Any CPU 55 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Debug|x86.Build.0 = Debug|Any CPU 56 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Release|x64.ActiveCfg = Release|Any CPU 59 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Release|x64.Build.0 = Release|Any CPU 60 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Release|x86.ActiveCfg = Release|Any CPU 61 | {7DAD2361-E333-4076-B840-FACA90D354F7}.Release|x86.Build.0 = Release|Any CPU 62 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Debug|x64.ActiveCfg = Debug|Any CPU 65 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Debug|x64.Build.0 = Debug|Any CPU 66 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Debug|x86.ActiveCfg = Debug|Any CPU 67 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Debug|x86.Build.0 = Debug|Any CPU 68 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Release|x64.ActiveCfg = Release|Any CPU 71 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Release|x64.Build.0 = Release|Any CPU 72 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Release|x86.ActiveCfg = Release|Any CPU 73 | {187BDA1B-2BF1-488D-9B8B-D1F0C7D83235}.Release|x86.Build.0 = Release|Any CPU 74 | EndGlobalSection 75 | GlobalSection(SolutionProperties) = preSolution 76 | HideSolutionNode = FALSE 77 | EndGlobalSection 78 | GlobalSection(NestedProjects) = preSolution 79 | {7DAD2361-E333-4076-B840-FACA90D354F7} = {BC9A489D-88AF-4DE2-A3EE-F31A1FE47D7A} 80 | EndGlobalSection 81 | GlobalSection(ExtensibilityGlobals) = postSolution 82 | SolutionGuid = {59FFFA5F-EA28-4011-8AE3-3AF0A57A9265} 83 | EndGlobalSection 84 | EndGlobal 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qRAM Library for Q\# 2 | 3 | [![Unitary Fund](https://img.shields.io/badge/Supported%20By-UNITARY%20FUND-brightgreen.svg?style=flat)](http://unitary.fund) 4 | 5 | This library implements a variety of different proposals for memory for quantum computers, also commonly called qRAM. 6 | 7 | > Want to learn more about what qRAM is? 8 | > Check out the [primer on memory for quantum computers](https://github.com/qsharp-community/qram/tree/master/docs/primer.pdf) in our docs! 9 | 10 | ## Motivation 11 | 12 | There are many different proposals for qRAM in quantum computing that each have different tradeoffs, and currently come up a lot in quantum machine learning applications. 13 | We want to better understand the costs and benefits of different qRAM implementations in quantum machine learning as well as quantum computing more generally. 14 | This library will help achieve these goals by giving us a concrete way to measure the resources each approach takes; choosing to do this in Q# allows us to leverage the built-in resource estimator to quickly iterate profiling the qRAM implementations and optimizing the circuits. 15 | 16 | #### FAQ: 17 | 18 | - **Do I need a qRAM?** 19 | 20 | _Sometimes_. 21 | You'll need a qRAM, or some more general means of _quantum state preparation_ in quantum machine learning (QML) algorithms that require you to load in classical data, or query an oracle that returns classical data. I've heard a number of stories of people working on QML being actively discouraged from doing so because ``QML won't work without a qRAM''. That's just not true, because *many QML algorithms do not need a qRAM*. Now, whether or not they yield any quantum advantage is a separate question, and won't be discussed here. The key point is that *some* QML algorithms need a qRAM, and they will potentially run into trouble as per the next question. 22 | 23 | - **Can we design an efficient qRAM?** 24 | 25 | _Maybe_. In the primer we'll take a look at proposals that will in principle run in polynomial depth, and others that scale far worse. There are some very interesting qubit-time tradeoffs one can explore, in particular if the data being stored has some sort of underlying structure. Regardless, even if we can design an efficient circuit, we'd also like something that is efficient in a fault-tolerant setting, and this is potentially very expensive. 26 | 27 | - **Can I build one?** 28 | 29 | _Maybe_. No one has actually done so, but there are a handful of hardware proposals that will be discussed in more detail in the hardware section of [the primer on memory for quantum computers](https://github.com/qsharp-community/qram/tree/master/docs/primer.pdf). 30 | 31 | ## Build status 32 | 33 | [![Run Tests](https://github.com/qsharp-community/qram/workflows/Run%20Tests/badge.svg)](https://github.com/qsharp-community/qram/actions?query=workflow%3A%22Run+Tests%22) 34 | [![Build and publish NuGet package to GitHub packages](https://github.com/qsharp-community/qram/workflows/Build%20and%20publish%20NuGet%20package%20to%20GitHub%20packages/badge.svg)](https://github.com/qsharp-community/qram/actions?query=workflow%3A%22Build+and+publish+NuGet+package+to+GitHub+packages%22) 35 | 36 | ## Code style 37 | 38 | [![q# code style](https://img.shields.io/badge/code%20style-Q%23-blue)](https://docs.microsoft.com/quantum/contributing/style-guide?tabs=guidance) 39 | [![q# APIcode style](https://img.shields.io/badge/code%20style-Q%23%20API-ff69b4)](https://docs.microsoft.com/quantum/contributing/style-guide?tabs=guidance) 40 | [![c# APIcode style](https://img.shields.io/badge/code%20style-C%23-lightgrey)](https://docs.microsoft.com/dotnet/csharp/programming-guide/inside-a-program/coding-conventions) 41 | [![CoC](https://img.shields.io/badge/code%20of%20conduct-contributor%20covenant-yellow)](CODE_OF_CONDUCT.md) 42 | 43 | ## Screenshots 44 | 45 | **Example of a Bucket Brigade qRAM circuit:** 46 | TODO: Q# notebook screenshots/gif 47 | TODO: Source in VS Code/gif 48 | 49 | ![Bucket Brigade qRAM](docs/images/bb.gif) 50 | 51 | ## Tech/framework used 52 | 53 | **Built with:** 54 | 55 | - [Quantum Development Kit](https://docs.microsoft.com/quantum/) 56 | - [.NET Core SDK 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) 57 | - [Python](https://www.python.org/downloads/) 58 | - [Visual Studio Code](https://code.visualstudio.com/) and [Visual Studio](https://visualstudio.microsoft.com/) 59 | - [Jupyter Notebook](https://jupyter.org/) 60 | 61 | ## Features 62 | 63 | This library implements a [**variety of different approaches**]() for qRAM and qROM, including: 64 | 65 | - **Bucket Brigade qRAM:** A read/write style memory where specific qubits are set aside to hold the data in the memory. The information can be queried so that the data returned is either bit encoded or phase encoded. 66 | - Relevant paper(s): Initial proposals in [0708.1879](https://arxiv.org/abs/0708.1879), [0807.4994](https://arxiv.org/abs/0807.4994); circuit model [1502.03450](https://arxiv.org/abs/1502.03450), and recent optimization [2002.09340](https://arxiv.org/abs/2002.09340) 67 | 68 | - **qROM:** A read-only style memory that creates a fixed operation that given an address and a target, encodes the data at that address on the target. qROMs are like quantum lookup tables. 69 | - Relevant paper(s): [Shafaei et al.](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.407.9599), [Abdessaied et al.](https://ieeexplore.ieee.org/document/7515539), [1902.01329](https://arxiv.org/abs/1902.01329). 70 | - **SELECT-SWAP qROM:** A read-only style memory similar to the basic qROM but that has multiplexing optimizations that can help you adjust your program resources. 71 | - Relevant paper(s): [1812.00954](https://arxiv.org/abs/1812.00954). 72 | 73 | It is important to us that we come up with an extensible framework for implementing as many qRAM/qROM implementation as possible so we can have a uniform way to evaluate and compare these proposals. 74 | We also include a [**sample for doing resource estimation**](./samples/ResourcesEstimation) (and not actually simulating) so that you can get an idea of what the resources are needed to run your memory. 75 | 76 | To validate the qRAM/qROM implementations in this library, this library includes [**unit tests for small memories**](./tests/) that can be simulated classically. 77 | 78 | This library is highly portable, and can easily be added to any Q# project with just a package include in your project file! 79 | Check out the [**instructions below**](./README.md#how-to-use) for adding the qRAM library to your project. 80 | 81 | ## Code Example 82 | 83 | ### Creating and then measuring a read-only memory: 84 | 85 | ```c# 86 | operation QromQuerySample(queryAddress : Int) : Int { 87 | // Generate a (Int, Bool[]) array of data. 88 | let data = GenerateMemoryData(); 89 | // Create the QRAM. 90 | let memory = QromOracle(data::DataSet); 91 | // Measure and return the data value stored at `queryAddress`. 92 | return QueryAndMeasureQROM(memory, queryAddress); 93 | } 94 | ``` 95 | See [Qrom sample](/samples/Qrom) for the rest of this implementation! 96 | 97 | ### Using a phase query Bucket Brigade QRAM to reflect about a marked state: 98 | 99 | ```c# 100 | operation GroverSearch(addressSize : Int, markedElements : Int[]) : Int { 101 | // First, set up a qRAM with marked elements set to 1. 102 | let nMarkedElements = Length(markedElements); 103 | mutable groverMemoryContents = Mapped(MemoryCell(_, [false]), RangeAsIntArray(0..2^addressSize - 1)); 104 | 105 | // Set the data value to true for each marked address. 106 | for (markedElement in markedElements) { 107 | set groverMemoryContents w/= markedElement <- MemoryCell(markedElement, [true]); 108 | } 109 | 110 | using ((groverQubits, targetQubit, flatMemoryRegister) = 111 | (Qubit[addressSize], Qubit[1], Qubit[2^addressSize]) 112 | ) { 113 | // Create a structured register to make indexing through the memory easier. 114 | let memoryRegister = PartitionMemoryRegister( 115 | flatMemoryRegister, 116 | GeneratedMemoryBank(groverMemoryContents) 117 | ); 118 | // Prepare the memory register with the initial data. 119 | let memory = BucketBrigadeQRAMOracle(groverMemoryContents, memoryRegister); 120 | 121 | // Initialize a uniform superposition over all possible inputs. 122 | PrepareUniform(groverQubits); 123 | 124 | // Grover iterations - the reflection about the marked element is implemented 125 | // as a QRAM phase query. Only the memory cells storing a 1 will produce a phase. 126 | for (idxIteration in 0..NIterations(nMarkedElements, addressSize) - 1) { 127 | 128 | memory::QueryPhase(AddressRegister(groverQubits), memoryRegister, targetQubit); 129 | ReflectAboutUniform(groverQubits); 130 | 131 | // It's necessary to remove phase since QueryPhase only sets phase 132 | // on the specific address instead of inverting like traditional Grover's. 133 | ApplyToEach(Z, targetQubit); 134 | ResetAll(targetQubit); 135 | } 136 | ResetAll(flatMemoryRegister); 137 | 138 | // Measure and return the answer. 139 | ResetAll(targetQubit); 140 | return MeasureInteger(LittleEndian(groverQubits)); 141 | } 142 | } 143 | ``` 144 | See [the Grover sample](/samples/Grover) for the rest of this implementation! 145 | 146 | TODO: #37 147 | 148 | 149 | ## Installation 150 | 151 | Anywhere you can use Q#, you can use this library! 152 | 153 | - Python host program 154 | - Jupyter Notebooks 155 | - Stand-alone command line application 156 | - C#/F# host program 157 | 158 | For complete and up-to-date ways to install the Quantum Development Kit (including Q# tooling) see [the official Q# docs](https://docs.microsoft.com/quantum/quickstarts/). 159 | 160 | For convenience, in this repo we include the following ways to make it easier to use this project. 161 | 162 | - [Remote Development Environment (VS Code)](https://code.visualstudio.com/blogs/2019/05/02/remote-development) 163 | - Once you open this repo in VS Code, you should be able to open the command pallet and select `Remote-Containers: Reopen in Container` and your editor will re-launch in a local docker container that will be properly configured to use the project. 164 | - Binder in-browser host (Web): TODO: Test 165 | 166 | ## API Reference 167 | 168 | TODO: See [#27](https://github.com/qsharp-community/qram/issues/27) 169 | 170 | ## Tests 171 | 172 | The tests for this library all live in the `tests` directory. 173 | To run the tests, navigate to that directory and run `dotnet test` and the .NET project will find and run all the tests in this directory. 174 | If you are adding new features or functionality, make sure to add some tests to either the existing files, or make a new one. 175 | For more info on writing tests for Q#, check out the [official Q# docs](https://docs.microsoft.com/quantum/user-guide/using-qsharp/testing-debugging). 176 | 177 | ## How to use? 178 | 179 | ### You want to use a published version of the library package: 180 | 181 | TODO: more detail on nuget.org stuff once published there. 182 | 183 | _For more information on adding packages to Q# projects (the instructions are the same as for C# packages) check out the [official docs](https://docs.microsoft.com/nuget/consume-packages/install-use-packages-dotnet-cli#install-a-package)._ 184 | 185 | ### You want to work on developing the library and use a locally built version of the project: 186 | 187 | The basic idea in this case is build locally a version of the nuget packages and then put it in a folder locally that is a known source to nuget. 188 | 189 | 0. Remove any previous copies of the package from your local nuget feed (you likely picked this location), and global nuget cache (default path on Windows 10 for the cache is below): 190 | 191 | ```Powershell 192 | > rm C:\Users\skais\nuget-packages\QSharpCommunity.Libraries.Qram.X.X.X.nupkg 193 | > rm C:\Users\skais\.nuget\packages\QSharpCommunity.Libraries.Qram\ 194 | ``` 195 | 196 | 1. Build the package for the Qram library: 197 | 198 | ```Powershell 199 | > cd src 200 | > dotnet pack 201 | ``` 202 | 203 | 2. Copy the package to your local nuget source (a location you selected, an example one is below). The `X` in the name are the place holder for the version number you are building (should be generated by the previous step). 204 | 205 | ```Powershell 206 | > cp .\bin\Debug\QSharpCommunity.Libraries.Qram.X.X.X.nupkg 'C:\Users\skais\nuget-packages\' 207 | ``` 208 | 209 | ## Contribute 210 | 211 | Please see our [contributing guidelines](CONTRIBUTING.md) and our [code of conduct](CODE_OF_CONDUCT.md) before working on a contribution, thanks! 212 | 213 | ## Credits 214 | - Primary developers: @glassnotes, @crazy4pi314 215 | - Code review and API design assistance: @RolfHuisman, @cgranade, @amirebrahimi 216 | 217 | #### Anything else that seems useful 218 | 219 | - [WIQCA talk](https://www.wiqca.dev/events/quantum101-qml_qram.html) on qRAM by @glassnotes 220 | - [QSI seminar](https://www.youtube.com/watch?v=IicCWK2D7sg) by @glassnotes 221 | - Live development of this library with @crazy4pi314 on [Twitch](https://twitch.tv/crazy4pi314) 222 | 223 | ## License 224 | 225 | MIT © [qsharp-community](https://github.com/qsharp-community/qram/blob/master/LICENSE) 226 | -------------------------------------------------------------------------------- /docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "files": [ 7 | "src/**.csproj" 8 | ] 9 | } 10 | ], 11 | "dest": "docs/api", 12 | "disableGitFeatures": false, 13 | "disableDefaultFilter": false 14 | } 15 | ], 16 | "build": { 17 | "content": [ 18 | { 19 | "files": [ 20 | "docs/api/**.yml", 21 | "docs/api/index.md" 22 | ] 23 | }, 24 | { 25 | "files": [ 26 | "articles/**.md", 27 | "articles/**/toc.yml", 28 | "toc.yml", 29 | "*.md" 30 | ] 31 | } 32 | ], 33 | "resource": [ 34 | { 35 | "files": [ 36 | "docs/images/**" 37 | ] 38 | } 39 | ], 40 | "overwrite": [ 41 | { 42 | "files": [ 43 | "docs/apidoc/**.md" 44 | ], 45 | "exclude": [ 46 | "obj/**", 47 | "_site/**" 48 | ] 49 | } 50 | ], 51 | "dest": "_site", 52 | "globalMetadataFiles": [], 53 | "fileMetadataFiles": [], 54 | "template": [ 55 | "default" 56 | ], 57 | "postProcessors": [], 58 | "markdownEngineName": "markdig", 59 | "noLangKeyword": false, 60 | "keepFileLink": false, 61 | "cleanupCacheHistory": false, 62 | "disableGitFeatures": false 63 | } 64 | } -------------------------------------------------------------------------------- /docs/api/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # temp file # 3 | ############### 4 | *.yml 5 | .manifest 6 | -------------------------------------------------------------------------------- /docs/api/index.md: -------------------------------------------------------------------------------- 1 | # PLACEHOLDER 2 | TODO: Add .NET projects to the *src* folder and run `docfx` to generate **REAL** *API Documentation*! 3 | -------------------------------------------------------------------------------- /docs/articles/intro.md: -------------------------------------------------------------------------------- 1 | # General project goals 2 | 3 | - Proficiency with Q# as a programming language 4 | - Understanding the role of qRAM in quantum computing, its benefits, and costs 5 | - Describe the different memory paradigms in quantum machine learning 6 | 7 | ### Bonus goals 8 | 9 | - Actually run a small qRAM on a quantum machine; how well does it work? 10 | - Describe the different types of classical RAM 11 | - Describe how one might implement a qRAM in hardware 12 | 13 | ## Key Deliverables 14 | 15 | - Q# Library, to be released open-source 16 | - Implementations: 17 | - [ ] Bucket-brigade (original circuit model, and updated constant-depth model) 18 | - [ ] Various qROMs 19 | - [ ] Quantum state preparation ("select/SWAP" oracles) 20 | - [ ] Application-specific qROMs 21 | - Samples: 22 | - [ ] Instantiation and querying all implemented qRAMs/qROMs 23 | - [ ] Resource estimation 24 | - Written report about the different methods used 25 | -------------------------------------------------------------------------------- /docs/articles/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Introduction 2 | href: intro.md 3 | -------------------------------------------------------------------------------- /docs/images/basicbb-qram-notes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/basicbb-qram-notes.jpg -------------------------------------------------------------------------------- /docs/images/basicbb-qram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/basicbb-qram.png -------------------------------------------------------------------------------- /docs/images/bb-00.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-3.0 2 | %%Creator: cairo 1.16.0 (https://cairographics.org) 3 | %%CreationDate: Wed Jun 17 16:48:50 2020 4 | %%Pages: 1 5 | %%DocumentData: Clean7Bit 6 | %%LanguageLevel: 2 7 | %%BoundingBox: 0 0 722 506 8 | %%EndComments 9 | %%BeginProlog 10 | 50 dict begin 11 | /q { gsave } bind def 12 | /Q { grestore } bind def 13 | /cm { 6 array astore concat } bind def 14 | /w { setlinewidth } bind def 15 | /J { setlinecap } bind def 16 | /j { setlinejoin } bind def 17 | /M { setmiterlimit } bind def 18 | /d { setdash } bind def 19 | /m { moveto } bind def 20 | /l { lineto } bind def 21 | /c { curveto } bind def 22 | /h { closepath } bind def 23 | /re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto 24 | 0 exch rlineto 0 rlineto closepath } bind def 25 | /S { stroke } bind def 26 | /f { fill } bind def 27 | /f* { eofill } bind def 28 | /n { newpath } bind def 29 | /W { clip } bind def 30 | /W* { eoclip } bind def 31 | /BT { } bind def 32 | /ET { } bind def 33 | /BDC { mark 3 1 roll /BDC pdfmark } bind def 34 | /EMC { mark /EMC pdfmark } bind def 35 | /cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def 36 | /Tj { show currentpoint cairo_store_point } bind def 37 | /TJ { 38 | { 39 | dup 40 | type /stringtype eq 41 | { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse 42 | } forall 43 | currentpoint cairo_store_point 44 | } bind def 45 | /cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore 46 | cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def 47 | /Tf { pop /cairo_font exch def /cairo_font_matrix where 48 | { pop cairo_selectfont } if } bind def 49 | /Td { matrix translate cairo_font_matrix matrix concatmatrix dup 50 | /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point 51 | /cairo_font where { pop cairo_selectfont } if } bind def 52 | /Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def 53 | cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def 54 | /g { setgray } bind def 55 | /rg { setrgbcolor } bind def 56 | /d1 { setcachedevice } bind def 57 | /cairo_data_source { 58 | CairoDataIndex CairoData length lt 59 | { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } 60 | { () } ifelse 61 | } def 62 | /cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def 63 | /cairo_image { image cairo_flush_ascii85_file } def 64 | /cairo_imagemask { imagemask cairo_flush_ascii85_file } def 65 | %%EndProlog 66 | %%BeginSetup 67 | %%BeginResource: font f-0-0 68 | %!FontType1-1.1 f-0-0 1.0 69 | 11 dict begin 70 | /FontName /f-0-0 def 71 | /PaintType 0 def 72 | /FontType 1 def 73 | /FontMatrix [0.001 0 0 0.001 0 0] readonly def 74 | /FontBBox {0 -10 702 698 } readonly def 75 | /Encoding 256 array 76 | 0 1 255 {1 index exch /.notdef put} for 77 | dup 48 /zero put 78 | dup 49 /one put 79 | dup 97 /a put 80 | dup 105 /i put 81 | dup 116 /t put 82 | dup 119 /w put 83 | readonly def 84 | currentdict end 85 | currentfile eexec 86 | f983ef0097ece636fb4a96c74d26ab84185f6dfa4a16a7a1c27bbe3f1156aea698df336d20b467 87 | b10e7f33846656653c5ac6962759d3056cbdb3190bac614b984bf5a132dc418192443014ba63de 88 | 800d392b6fea026574bb2535fd7bb5338f35bf15a88ea328fdaa49670c7852e3d060f3c5d6b07f 89 | 2ef6d0f22646c5d18e19a2ae3ee120390f6dd96f76dcf1e127de5e9299077a00c17c0d71e36e5b 90 | 9d5ec58fceda57739a6a4214d4b79d6c48d2784b60c320323c7acddddf34db833cac0cf109f799 91 | 69d114a330d372e5c978a66acc84e3fe5557f6240856a013ffaa0199444e5c5036f775eba4a5c5 92 | 8cde66cf604b9aca2178431127b8a1ff7ed633a65c04600af5f573483112251ca5d188dea508ed 93 | e1b2455317d2f89946db9171817b252ef4aed3bc64913054f9fabfdd9a8863712febbc215a6c69 94 | 6ecf9194a96092d834aac6afe5dffc5dfd22588efe04012d7700dc969594a72cf2c193e5d39d97 95 | d6854786255065746c1782a4ff637faa86dc84199929576c841060c40ee279569057b09ed3b0dd 96 | 679928887acc14f981327eb6ca2ff8e5412628734989884679b967c16fe3ff30905b3268bcea98 97 | 35a594f6725d41c0b973247348692f32f20197c48895d4d6e7ba05b6419ee08933be2d81a60c9a 98 | b9e51db2fa7a3b27c1e1125908dd5bf112959ed7bf458f03fa6fb4ef1a13d2339b8eac65fd5035 99 | 2ee9bd68a68b1b115130682d6a39d62e94e40644dc3a5fa4491bda7e2d7a682237946ff49c0692 100 | 9ed0d5412f682f404b9f67d8288f8983ff7ab49988e5cae1a4d75f3384dd8777e6096c0e0ce0ea 101 | 618907a7519dcc7caf54989ee48613edcf0c8d87e054f4d016cfbe9820ecb2f11e8f43b34c9c04 102 | ff4b4a919d6a6044d2d2da540b1167768a7e26e8009884d703ad244066f114613a7bb228fd3c45 103 | cf962332455520c0aa90f5cf7b753532c5050fa399d68162eef69a1d926fa02fb0e58ec32d19d8 104 | 0f5c8727b1c5d4ef131b33a88a4e8a4c645c27a9c7c9ab371b43bb66e6350e3e1d39029852e486 105 | f6682ecad5f445b0f2b629eb071f5f51c3c3a3b2a2c71a3ca62fd7003d1bb9ac3aaf78243c52d4 106 | e02e8274e91cf7306ccee21b3f4229c5f33dc23ceca7e6d1a85240fcf64fac0e2834b2e41a4baf 107 | a861fe1d62fdc9ee189b1d6a07bc206c340953b0b2b4468aae90d741a56b46b5f28228da1a88da 108 | 3552be40e4cc8c24b2c0dee1dc3945fb16ca91e1761597c582d4fae541de2b3d24e915bc790716 109 | 8207a6e0b561103f4f575a11f7ecd03cf0fee5f90d5aa9e8f7ddf802bab796195e8686b201ae1a 110 | 1b0a32561c2449d1f59bdc79210835ac3bdfd097daaccc4be8fb93557f88f7aafcca3e9142d327 111 | b77c58000eccec6034e0b2cfa2d5b770bf43f19b5b25205e61c6a8fedb8030d98064724f7c4e07 112 | b4295ccaca2c4a36bb81ff9f9467994c14ffad99d0a5d5b5d6a52cd557107024e1d69efb3437a0 113 | 788826a3165dbe3986f153dc1cc040edf3102ce4e5bd0688dd6090772acf844f91249b3f3d68c5 114 | 2b22619649a0abee277d76368e6885ea757515bda298460f89726db571f1d2b1a2c8e0463ad442 115 | de7cdcb9ac7bf959f73901db309fc6de9bd8037ae843709097e0f8dcffe00e1c2bafc7e16820e6 116 | 4a8357de9bbd42e46fcc674efbf8f6c6d531e8429a08ff9765fd7a14d9b59a03309c5be1033bed 117 | 4e97274d0fd5a97076562233c79bc5bec546f2b7d1ffea4488de185b58ffd68c508b5ac3e3bca2 118 | 988035f09cd4aad7040b7d100042b09c52264614f650376a07947492bff6eb7a25ce35483a7a4d 119 | c973bbc12386547e7f122dbfeaeac3ed44d1e76f1ad96533f6c05d0feace9fa6b94b476060d383 120 | 6259fe269a37b841b7d9c45c26d269c75b15981aed3aacac7a066b94c610a7bc32a6b28857a8e5 121 | 4b866b5a1100a6f6075c3eea48da8f27452eda2c7b37b40627a405b719ab39f3163f1efb07ded7 122 | 7520a5e3799ca270d956383a1d4f11c1f4f4940224ae08680000000000000000000000000000000000000000000000000000000000000000 123 | 0000000000000000000000000000000000000000000000000000000000000000 124 | 0000000000000000000000000000000000000000000000000000000000000000 125 | 0000000000000000000000000000000000000000000000000000000000000000 126 | 0000000000000000000000000000000000000000000000000000000000000000 127 | 0000000000000000000000000000000000000000000000000000000000000000 128 | 0000000000000000000000000000000000000000000000000000000000000000 129 | 0000000000000000000000000000000000000000000000000000000000000000 130 | cleartomark 131 | %%EndResource 132 | %%EndSetup 133 | %%Page: 1 1 134 | %%BeginPageSetup 135 | %%PageBoundingBox: 0 0 722 506 136 | %%EndPageSetup 137 | q 0 0 722 506 rectclip 138 | 1 0 0 -1 0 506 cm q 139 | 0.0117647 0 0 rg 140 | 3.323898 w 141 | 0 J 142 | 0 j 143 | [] 0.0 d 144 | 4 M q 1 0 0 1 0 0 cm 145 | 71.574 288.012 m 28.129 421.867 l S Q 146 | q 1 0 0 1 0 0 cm 147 | 259.453 286.836 m 216.008 420.695 l S Q 148 | q 1 0 0 1 0 0 cm 149 | 446.148 288.012 m 402.703 421.867 l S Q 150 | q 1 0 0 1 0 0 cm 151 | 634.027 286.836 m 590.586 420.695 l S Q 152 | 0 g 153 | q 1 0 0 1 0 0 cm 154 | 167.273 151.215 m 262.977 288.012 l S Q 155 | q 1 0 0 1 0 0 cm 156 | 541.848 151.215 m 637.551 288.012 l S Q 157 | 0.831373 0 0 rg 158 | 354.562 12.648 m 541.848 151.215 541.848 151.215 541.848 151.215 c f 159 | 0 g 160 | q 1 0 0 1 0 0 cm 161 | 354.562 12.648 m 541.848 151.215 541.848 151.215 541.848 151.215 c S Q 162 | 1.381514 w 163 | q 1 0 0 1 0 0 cm 164 | 0.691 425.891 m 0.691 484.598 l 52.508 484.598 l 52.508 425.891 l S Q 165 | 3.321211 w 166 | q 1 0 0 1 0 0 cm 167 | 354.562 12.648 m 167.273 151.215 167.273 151.215 167.273 151.215 c S Q 168 | q 1 0 0 1 0 0 cm 169 | 167.273 151.215 m 71.574 288.012 l S Q 170 | 3.323898 w 171 | q 1 0 0 1 0 0 cm 172 | 541.848 151.215 m 446.148 288.012 l S Q 173 | 0.0117647 0 0 rg 174 | 3.321211 w 175 | q 1 0 0 1 0 0 cm 176 | 75.094 289.184 m 118.539 423.043 l S Q 177 | q 1 0 0 1 0 0 cm 178 | 262.977 288.012 m 306.422 421.867 l S Q 179 | q 1 0 0 1 0 0 cm 180 | 449.672 289.184 m 493.117 423.043 l S Q 181 | q 1 0 0 1 0 0 cm 182 | 637.191 290.359 m 680.645 424.215 l S Q 183 | 0 g 184 | 1.381514 w 185 | q 1 0 0 1 0 0 cm 186 | 657.695 425.891 m 657.695 484.598 l 709.512 484.598 l 709.512 425.891 l 187 | S Q 188 | q 1 0 0 1 0 0 cm 189 | 564.891 425.891 m 564.891 484.598 l 616.695 484.598 l 616.695 425.891 l 190 | S Q 191 | q 1 0 0 1 0 0 cm 192 | 470.539 425.891 m 470.539 484.598 l 522.344 484.598 l 522.344 425.891 l 193 | S Q 194 | q 1 0 0 1 0 0 cm 195 | 376.824 425.891 m 376.824 484.598 l 428.629 484.598 l 428.629 425.891 l 196 | S Q 197 | q 1 0 0 1 0 0 cm 198 | 282.797 425.891 m 282.797 484.598 l 334.602 484.598 l 334.602 425.891 l 199 | S Q 200 | q 1 0 0 1 0 0 cm 201 | 188.758 425.891 m 188.758 484.598 l 240.574 484.598 l 240.574 425.891 l 202 | S Q 203 | q 1 0 0 1 0 0 cm 204 | 94.73 425.891 m 94.73 484.598 l 146.535 484.598 l 146.535 425.891 l S Q 205 | BT 206 | 25.91501 0 0 -25.91501 198.255821 159.078727 Tm 207 | /f-0-0 1 Tf 208 | (wait)Tj 209 | ET 210 | 194.758 138.531 m 194.758 138.355 l 194.746 138.273 l 194.746 138.148 l 211 | 194.734 138.109 l 194.734 138.066 l 194.723 138.031 l 194.723 137.996 l 212 | 194.711 137.961 l 194.711 137.926 l 194.688 137.855 l 194.664 137.836 l 213 | 194.652 137.797 l 194.641 137.773 l 194.617 137.738 l 194.57 137.695 l 214 | 194.535 137.672 l 194.523 137.672 l 194.504 137.66 l 194.492 137.648 l 194.48 215 | 137.648 l 194.469 137.633 l 194.441 137.621 l 194.43 137.621 l 194.406 216 | 137.609 l 194.352 137.609 l 194.328 137.602 l 194.223 137.602 l 193.699 217 | 137.602 193.699 138.066 193.699 138.543 c 193.699 162.969 l 193.699 163.445 218 | 193.699 163.906 194.223 163.906 c 194.758 163.906 194.758 163.445 194.758 219 | 162.969 c h 220 | 194.758 138.531 m f* 221 | 254.047 151.133 m 254.047 151.121 l 254.059 151.109 l 254.059 151.098 l 222 | 254.07 151.086 l 254.07 151.074 l 254.082 151.062 l 254.082 151.039 l 254.094 223 | 151.039 l 254.094 151.027 l 254.105 151.027 l 254.105 151.004 l 254.117 224 | 150.996 l 254.117 150.969 l 254.129 150.945 l 254.129 150.934 l 254.141 225 | 150.922 l 254.141 150.898 l 254.152 150.887 l 254.152 150.867 l 254.164 226 | 150.867 l 254.164 150.809 l 254.176 150.809 l 254.176 150.758 l 254.176 227 | 150.668 254.176 150.621 254.047 150.309 c 249.434 138.195 l 249.281 137.75 228 | 249.117 137.602 248.824 137.602 c 248.539 137.602 248.305 137.832 248.305 229 | 138.121 c 248.305 138.195 248.305 138.25 248.434 138.543 c 253.105 150.758 230 | l 248.434 162.918 l 248.305 163.211 248.305 163.258 248.305 163.387 c 248.305 231 | 163.676 248.539 163.906 248.824 163.906 c 249.176 163.906 249.281 163.652 232 | 249.387 163.387 c h 233 | 254.047 151.133 m f* 234 | BT 235 | 25.91501 0 0 -25.91501 389.496364 21.477687 Tm 236 | /f-0-0 1 Tf 237 | (wait)Tj 238 | ET 239 | 385.996 0.934 m 385.996 0.758 l 385.984 0.676 l 385.984 0.547 l 385.977 240 | 0.5 l 385.977 0.465 l 385.965 0.434 l 385.965 0.395 l 385.953 0.359 l 385.953 241 | 0.328 l 385.926 0.258 l 385.891 0.199 l 385.879 0.164 l 385.812 0.094 l 242 | 385.777 0.07 l 385.766 0.07 l 385.75 0.059 l 385.727 0.047 l 385.719 0.047 243 | l 385.707 0.035 l 385.684 0.023 l 385.672 0.023 l 385.648 0.012 l 385.625 244 | 0.012 l 385.613 0 l 385.465 0 l 384.938 0 384.938 0.465 384.938 0.934 c 245 | 384.938 25.367 l 384.938 25.844 384.938 26.309 385.465 26.309 c 385.996 246 | 26.309 385.996 25.844 385.996 25.367 c h 247 | 385.996 0.934 m f* 248 | 445.285 13.531 m 445.285 13.52 l 445.297 13.508 l 445.297 13.496 l 445.309 249 | 13.484 l 445.309 13.477 l 445.32 13.465 l 445.32 13.441 l 445.332 13.441 250 | l 445.332 13.43 l 445.344 13.418 l 445.344 13.406 l 445.355 13.395 l 445.355 251 | 13.367 l 445.367 13.348 l 445.367 13.336 l 445.379 13.324 l 445.379 13.301 252 | l 445.391 13.289 l 445.391 13.266 l 445.402 13.266 l 445.402 13.207 l 445.414 253 | 13.207 l 445.414 13.16 l 445.414 13.066 445.414 13.02 445.285 12.707 c 254 | 440.668 0.594 l 440.52 0.152 440.355 0 440.066 0 c 439.777 0 439.543 0.23 255 | 439.543 0.523 c 439.543 0.594 439.543 0.652 439.668 0.93 c 444.344 13.16 256 | l 439.668 25.309 l 439.543 25.602 439.543 25.656 439.543 25.785 c 439.543 257 | 26.078 439.777 26.309 440.066 26.309 c 440.414 26.309 440.52 26.055 440.625 258 | 25.785 c h 259 | 445.285 13.531 m f* 260 | BT 261 | 25.91501 0 0 -25.91501 573.086813 159.078727 Tm 262 | /f-0-0 1 Tf 263 | (wait)Tj 264 | ET 265 | 569.59 138.531 m 569.59 138.355 l 569.578 138.273 l 569.578 138.148 l 569.566 266 | 138.109 l 569.566 138.066 l 569.555 138.031 l 569.555 137.996 l 569.543 267 | 137.961 l 569.543 137.926 l 569.516 137.855 l 569.496 137.836 l 569.484 268 | 137.797 l 569.473 137.773 l 569.449 137.738 l 569.402 137.695 l 569.367 269 | 137.672 l 569.355 137.672 l 569.344 137.66 l 569.32 137.648 l 569.309 137.648 270 | l 569.297 137.633 l 569.273 137.621 l 569.262 137.621 l 569.242 137.609 271 | l 569.184 137.609 l 569.16 137.602 l 569.055 137.602 l 568.531 137.602 272 | 568.531 138.066 568.531 138.543 c 568.531 162.969 l 568.531 163.445 568.531 273 | 163.906 569.055 163.906 c 569.59 163.906 569.59 163.445 569.59 162.969 274 | c h 275 | 569.59 138.531 m f* 276 | 628.879 151.133 m 628.879 151.121 l 628.891 151.109 l 628.891 151.098 l 277 | 628.898 151.086 l 628.898 151.074 l 628.91 151.062 l 628.91 151.039 l 628.922 278 | 151.039 l 628.922 151.027 l 628.934 151.027 l 628.934 151.004 l 628.945 279 | 150.996 l 628.945 150.969 l 628.957 150.945 l 628.957 150.934 l 628.969 280 | 150.922 l 628.969 150.898 l 628.98 150.887 l 628.98 150.867 l 628.992 150.867 281 | l 628.992 150.809 l 629.004 150.809 l 629.004 150.758 l 629.004 150.668 282 | 629.004 150.621 628.875 150.309 c 624.262 138.195 l 624.109 137.75 623.945 283 | 137.602 623.656 137.602 c 623.363 137.602 623.133 137.832 623.133 138.121 284 | c 623.133 138.195 623.133 138.25 623.262 138.543 c 627.934 150.758 l 623.262 285 | 162.918 l 623.133 163.211 623.133 163.258 623.133 163.387 c 623.133 163.676 286 | 623.363 163.906 623.656 163.906 c 624.004 163.906 624.109 163.652 624.215 287 | 163.387 c h 288 | 628.879 151.133 m f* 289 | BT 290 | 25.91501 0 0 -25.91501 102.671198 293.756317 Tm 291 | /f-0-0 1 Tf 292 | (wait)Tj 293 | ET 294 | 99.172 273.27 m 99.172 273.098 l 99.16 273 l 99.16 272.875 l 99.148 272.84 295 | l 99.148 272.793 l 99.137 272.758 l 99.137 272.727 l 99.125 272.688 l 99.125 296 | 272.652 l 99.102 272.586 l 99.078 272.562 l 99.066 272.523 l 99.055 272.504 297 | l 99.031 272.469 l 98.984 272.422 l 98.949 272.398 l 98.938 272.398 l 98.926 298 | 272.387 l 98.902 272.375 l 98.895 272.375 l 98.883 272.363 l 98.859 272.352 299 | l 98.824 272.352 l 98.797 272.34 l 98.766 272.34 l 98.742 272.328 l 98.637 300 | 272.328 l 98.113 272.328 98.113 272.793 98.113 273.27 c 98.113 297.695 301 | l 98.113 298.172 98.113 298.648 98.637 298.648 c 99.172 298.648 99.172 298.172 302 | 99.172 297.695 c h 303 | 99.172 273.27 m f* 304 | 158.461 285.867 m 158.461 285.855 l 158.473 285.844 l 158.473 285.832 l 305 | 158.484 285.82 l 158.484 285.809 l 158.496 285.797 l 158.496 285.785 l 306 | 158.508 285.773 l 158.508 285.762 l 158.52 285.762 l 158.52 285.738 l 158.531 307 | 285.727 l 158.531 285.703 l 158.547 285.68 l 158.547 285.668 l 158.555 308 | 285.656 l 158.555 285.648 l 158.566 285.621 l 158.566 285.598 l 158.578 309 | 285.598 l 158.578 285.551 l 158.59 285.539 l 158.59 285.496 l 158.59 285.41 310 | 158.59 285.355 158.461 285.039 c 153.848 272.938 l 153.695 272.488 153.535 311 | 272.336 153.242 272.336 c 152.953 272.336 152.719 272.566 152.719 272.859 312 | c 152.719 272.938 152.719 272.988 152.848 273.273 c 157.52 285.496 l 152.848 313 | 297.656 l 152.719 297.945 152.719 297.992 152.719 298.121 c 152.719 298.41 314 | 152.953 298.645 153.242 298.645 c 153.59 298.645 153.695 298.387 153.801 315 | 298.121 c h 316 | 158.461 285.867 m f* 317 | BT 318 | 25.91501 0 0 -25.91501 291.283849 293.756317 Tm 319 | /f-0-0 1 Tf 320 | (wait)Tj 321 | ET 322 | 287.785 273.27 m 287.785 273.098 l 287.773 273 l 287.773 272.875 l 287.762 323 | 272.84 l 287.762 272.793 l 287.75 272.758 l 287.75 272.727 l 287.738 272.688 324 | l 287.738 272.652 l 287.715 272.586 l 287.691 272.562 l 287.68 272.523 325 | l 287.668 272.504 l 287.645 272.469 l 287.598 272.422 l 287.562 272.398 326 | l 287.551 272.398 l 287.539 272.387 l 287.516 272.375 l 287.508 272.375 327 | l 287.496 272.363 l 287.469 272.352 l 287.434 272.352 l 287.41 272.34 l 328 | 287.379 272.34 l 287.355 272.328 l 287.25 272.328 l 286.727 272.328 286.727 329 | 272.793 286.727 273.27 c 286.727 297.695 l 286.727 298.172 286.727 298.648 330 | 287.25 298.648 c 287.785 298.648 287.785 298.172 287.785 297.695 c h 331 | 287.785 273.27 m f* 332 | 347.074 285.867 m 347.074 285.855 l 347.086 285.844 l 347.086 285.832 l 333 | 347.098 285.82 l 347.098 285.809 l 347.109 285.797 l 347.109 285.785 l 334 | 347.121 285.773 l 347.121 285.762 l 347.133 285.762 l 347.133 285.738 l 335 | 347.145 285.727 l 347.145 285.703 l 347.156 285.68 l 347.156 285.668 l 347.168 336 | 285.656 l 347.168 285.648 l 347.18 285.621 l 347.18 285.598 l 347.191 285.598 337 | l 347.191 285.551 l 347.203 285.539 l 347.203 285.496 l 347.203 285.41 338 | 347.203 285.355 347.074 285.039 c 342.457 272.938 l 342.309 272.484 342.145 339 | 272.336 341.855 272.336 c 341.566 272.336 341.332 272.566 341.332 272.859 340 | c 341.332 272.938 341.332 272.984 341.457 273.273 c 346.133 285.496 l 341.457 341 | 297.656 l 341.332 297.945 341.332 297.992 341.332 298.121 c 341.332 298.41 342 | 341.566 298.645 341.855 298.645 c 342.203 298.645 342.309 298.387 342.414 343 | 298.121 c h 344 | 347.074 285.867 m f* 345 | BT 346 | 25.91501 0 0 -25.91501 478.780475 293.756317 Tm 347 | /f-0-0 1 Tf 348 | (wait)Tj 349 | ET 350 | 475.281 273.27 m 475.281 273.098 l 475.27 273 l 475.27 272.875 l 475.258 351 | 272.84 l 475.258 272.793 l 475.246 272.758 l 475.246 272.727 l 475.234 352 | 272.688 l 475.234 272.652 l 475.211 272.586 l 475.188 272.562 l 475.176 353 | 272.523 l 475.164 272.504 l 475.141 272.469 l 475.098 272.422 l 475.059 354 | 272.398 l 475.047 272.398 l 475.035 272.387 l 475.012 272.375 l 475.004 355 | 272.375 l 474.992 272.363 l 474.969 272.352 l 474.934 272.352 l 474.91 272.34 356 | l 474.875 272.34 l 474.852 272.328 l 474.746 272.328 l 474.223 272.328 357 | 474.223 272.793 474.223 273.27 c 474.223 297.695 l 474.223 298.172 474.223 358 | 298.648 474.746 298.648 c 475.281 298.648 475.281 298.172 475.281 297.695 359 | c h 360 | 475.281 273.27 m f* 361 | 534.57 285.867 m 534.57 285.855 l 534.582 285.844 l 534.582 285.832 l 534.594 362 | 285.82 l 534.594 285.809 l 534.605 285.797 l 534.605 285.785 l 534.617 363 | 285.773 l 534.617 285.762 l 534.629 285.762 l 534.629 285.738 l 534.641 364 | 285.727 l 534.641 285.703 l 534.652 285.68 l 534.652 285.668 l 534.664 285.656 365 | l 534.664 285.648 l 534.676 285.621 l 534.676 285.598 l 534.688 285.598 366 | l 534.688 285.551 l 534.699 285.539 l 534.699 285.496 l 534.699 285.41 367 | 534.699 285.355 534.57 285.039 c 529.953 272.938 l 529.805 272.484 529.641 368 | 272.336 529.348 272.336 c 529.059 272.336 528.828 272.566 528.828 272.859 369 | c 528.828 272.938 528.828 272.984 528.953 273.273 c 533.629 285.496 l 528.953 370 | 297.656 l 528.828 297.945 528.828 297.992 528.828 298.121 c 528.828 298.41 371 | 529.059 298.645 529.348 298.645 c 529.699 298.645 529.805 298.387 529.91 372 | 298.121 c h 373 | 534.57 285.867 m f* 374 | BT 375 | 25.91501 0 0 -25.91501 665.161007 293.756317 Tm 376 | /f-0-0 1 Tf 377 | (wait)Tj 378 | ET 379 | 661.66 273.27 m 661.66 273.098 l 661.648 273 l 661.648 272.875 l 661.637 380 | 272.84 l 661.637 272.793 l 661.629 272.758 l 661.629 272.727 l 661.617 381 | 272.688 l 661.617 272.652 l 661.594 272.586 l 661.57 272.562 l 661.559 272.523 382 | l 661.547 272.504 l 661.523 272.469 l 661.477 272.422 l 661.441 272.398 383 | l 661.43 272.398 l 661.418 272.387 l 661.395 272.375 l 661.387 272.375 384 | l 661.375 272.363 l 661.348 272.352 l 661.312 272.352 l 661.289 272.34 l 385 | 661.258 272.34 l 661.234 272.328 l 661.129 272.328 l 660.605 272.328 660.605 386 | 272.793 660.605 273.27 c 660.605 297.695 l 660.605 298.172 660.605 298.648 387 | 661.129 298.648 c 661.66 298.648 661.66 298.172 661.66 297.695 c h 388 | 661.66 273.27 m f* 389 | 720.953 285.867 m 720.953 285.855 l 720.965 285.844 l 720.965 285.832 l 390 | 720.977 285.82 l 720.977 285.809 l 720.988 285.797 l 720.988 285.785 l 391 | 721 285.773 l 721 285.762 l 721.012 285.762 l 721.012 285.738 l 721.023 392 | 285.727 l 721.023 285.703 l 721.035 285.68 l 721.035 285.668 l 721.043 285.656 393 | l 721.043 285.648 l 721.055 285.621 l 721.055 285.598 l 721.066 285.598 394 | l 721.066 285.551 l 721.078 285.539 l 721.078 285.496 l 721.078 285.41 395 | 721.078 285.355 720.949 285.039 c 716.332 272.938 l 716.184 272.484 716.02 396 | 272.336 715.73 272.336 c 715.441 272.336 715.207 272.566 715.207 272.859 397 | c 715.207 272.938 715.207 272.984 715.332 273.273 c 720.008 285.496 l 715.332 398 | 297.656 l 715.207 297.945 715.207 297.992 715.207 298.121 c 715.207 298.41 399 | 715.441 298.645 715.73 298.645 c 716.078 298.645 716.184 298.387 716.289 400 | 298.121 c h 401 | 720.953 285.867 m f* 402 | BT 403 | 47.618186 0 0 -47.618186 15.647336 469.875747 Tm 404 | /f-0-0 1 Tf 405 | (0)Tj 406 | 47.618182 0 0 -47.618182 109.679835 469.875747 Tm 407 | [(0)-3485(0)-5459(0)]TJ 408 | 11.822626 0 Td 409 | (0)Tj 410 | -9.839376 -0.00350017 Td 411 | [(1)-3484(1)-1503(1)]TJ 412 | ET 413 | 0.501961 g 414 | BT 415 | 23.809093 0 0 -23.809093 10.055905 505.699827 Tm 416 | /f-0-0 1 Tf 417 | (000)Tj 418 | 23.809091 0 0 -23.809091 105.112208 505.699827 Tm 419 | [(001)-2512(010)-2597(011)-2477(100)]TJ 420 | 15.749753 0 Td 421 | [(101)-2525(110)]TJ 422 | 7.861001 -0.00350049 Td 423 | (111)Tj 424 | ET 425 | 0 g 426 | 64.711 276.809 17.363 17.363 re f 427 | 2.235618 w 428 | q 1 0 0 1 0 0 cm 429 | 64.711 276.809 17.363 17.363 re S Q 430 | 252.535 276.809 17.359 17.363 re f 431 | q 1 0 0 1 0 0 cm 432 | 252.535 276.809 17.359 17.363 re S Q 433 | 438.777 276.809 17.363 17.363 re f 434 | q 1 0 0 1 0 0 cm 435 | 438.777 276.809 17.363 17.363 re S Q 436 | 626.082 276.809 17.359 17.363 re f 437 | q 1 0 0 1 0 0 cm 438 | 626.082 276.809 17.359 17.363 re S Q 439 | 532.418 143.438 17.359 17.363 re f 440 | q 1 0 0 1 0 0 cm 441 | 532.418 143.438 17.359 17.363 re S Q 442 | 158.621 143.438 17.363 17.363 re f 443 | q 1 0 0 1 0 0 cm 444 | 158.621 143.438 17.363 17.363 re S Q 445 | 344.867 8.223 17.359 17.359 re f 446 | q 1 0 0 1 0 0 cm 447 | 344.867 8.223 17.359 17.359 re S Q 448 | Q Q 449 | showpage 450 | %%Trailer 451 | end 452 | %%EOF 453 | -------------------------------------------------------------------------------- /docs/images/bb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/bb.gif -------------------------------------------------------------------------------- /docs/images/ccz.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-3.0 2 | %%Creator: cairo 1.16.0 (https://cairographics.org) 3 | %%CreationDate: Wed Jul 8 11:33:54 2020 4 | %%Pages: 1 5 | %%DocumentData: Clean7Bit 6 | %%LanguageLevel: 2 7 | %%BoundingBox: 0 0 80 32 8 | %%EndComments 9 | %%BeginProlog 10 | 50 dict begin 11 | /q { gsave } bind def 12 | /Q { grestore } bind def 13 | /cm { 6 array astore concat } bind def 14 | /w { setlinewidth } bind def 15 | /J { setlinecap } bind def 16 | /j { setlinejoin } bind def 17 | /M { setmiterlimit } bind def 18 | /d { setdash } bind def 19 | /m { moveto } bind def 20 | /l { lineto } bind def 21 | /c { curveto } bind def 22 | /h { closepath } bind def 23 | /re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto 24 | 0 exch rlineto 0 rlineto closepath } bind def 25 | /S { stroke } bind def 26 | /f { fill } bind def 27 | /f* { eofill } bind def 28 | /n { newpath } bind def 29 | /W { clip } bind def 30 | /W* { eoclip } bind def 31 | /BT { } bind def 32 | /ET { } bind def 33 | /BDC { mark 3 1 roll /BDC pdfmark } bind def 34 | /EMC { mark /EMC pdfmark } bind def 35 | /cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def 36 | /Tj { show currentpoint cairo_store_point } bind def 37 | /TJ { 38 | { 39 | dup 40 | type /stringtype eq 41 | { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse 42 | } forall 43 | currentpoint cairo_store_point 44 | } bind def 45 | /cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore 46 | cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def 47 | /Tf { pop /cairo_font exch def /cairo_font_matrix where 48 | { pop cairo_selectfont } if } bind def 49 | /Td { matrix translate cairo_font_matrix matrix concatmatrix dup 50 | /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point 51 | /cairo_font where { pop cairo_selectfont } if } bind def 52 | /Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def 53 | cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def 54 | /g { setgray } bind def 55 | /rg { setrgbcolor } bind def 56 | /d1 { setcachedevice } bind def 57 | /cairo_data_source { 58 | CairoDataIndex CairoData length lt 59 | { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } 60 | { () } ifelse 61 | } def 62 | /cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def 63 | /cairo_image { image cairo_flush_ascii85_file } def 64 | /cairo_imagemask { imagemask cairo_flush_ascii85_file } def 65 | %%EndProlog 66 | %%BeginSetup 67 | %%EndSetup 68 | %%Page: 1 1 69 | %%BeginPageSetup 70 | %%PageBoundingBox: 0 0 80 32 71 | %%EndPageSetup 72 | q 0 0 80 32 rectclip 73 | 1 0 0 -1 0 32 cm q 74 | 0 g 75 | 0.75 w 76 | 0 J 77 | 0 j 78 | [] 0.0 d 79 | 4 M q 1 0 0 1 0 0 cm 80 | 42.258 1.547 m 79.375 1.547 l S Q 81 | q 1 0 0 1 0 0 cm 82 | 42.258 14.02 m 79.375 14.02 l S Q 83 | q 1 0 0 1 0 0 cm 84 | 42.258 26.488 m 79.375 26.488 l S Q 85 | 1 g 86 | 46.355 22.07 8.836 8.836 re f 87 | 0 g 88 | 0.618575 w 89 | q 1 0 0 1 0 0 cm 90 | 46.355 22.07 8.836 8.836 re S Q 91 | 52.875 24.656 m 52.879 24.633 l 52.887 24.613 l 52.891 24.59 l 52.895 24.57 92 | l 52.902 24.551 l 52.906 24.535 l 52.914 24.516 l 52.918 24.5 l 52.926 93 | 24.484 l 52.934 24.473 l 52.941 24.457 l 52.953 24.445 l 52.961 24.434 l 94 | 52.973 24.422 l 52.984 24.414 l 52.996 24.402 l 53.027 24.387 l 53.066 95 | 24.371 l 53.086 24.367 l 53.109 24.359 l 53.121 24.359 l 53.133 24.355 l 96 | 53.148 24.355 l 53.16 24.352 l 53.176 24.352 l 53.188 24.348 l 53.203 24.348 97 | l 53.219 24.344 l 53.254 24.344 l 53.27 24.34 l 53.344 24.34 l 53.367 24.336 98 | l 53.457 24.336 l 53.637 24.336 53.691 24.336 53.691 24.199 c 53.691 24.121 99 | 53.613 24.121 53.594 24.121 c 53.398 24.121 52.902 24.145 52.707 24.145 100 | c 52.504 24.145 52.012 24.121 51.812 24.121 c 51.758 24.121 51.68 24.121 101 | 51.68 24.262 c 51.68 24.336 51.742 24.336 51.875 24.336 c 51.891 24.336 102 | 52.02 24.336 52.137 24.352 c 52.262 24.367 52.324 24.371 52.324 24.461 103 | c 52.324 24.488 52.32 24.504 52.297 24.594 c 51.883 26.285 l 49.77 26.285 104 | l 50.18 24.656 l 50.238 24.406 50.262 24.336 50.758 24.336 c 50.938 24.336 105 | 50.996 24.336 50.996 24.199 c 50.996 24.121 50.918 24.121 50.898 24.121 106 | c 50.703 24.121 50.203 24.145 50.012 24.145 c 49.812 24.145 49.316 24.121 107 | 49.117 24.121 c 49.062 24.121 48.984 24.121 48.984 24.262 c 48.984 24.336 108 | 49.051 24.336 49.18 24.336 c 49.195 24.336 49.324 24.336 49.445 24.352 109 | c 49.566 24.367 49.629 24.371 49.629 24.461 c 49.629 24.488 49.621 24.512 110 | 49.602 24.594 c 48.676 28.312 l 48.605 28.586 48.59 28.641 48.043 28.641 111 | c 47.918 28.641 47.855 28.641 47.855 28.777 c 47.855 28.855 47.941 28.855 112 | 47.953 28.855 c 48.148 28.855 48.641 28.832 48.832 28.832 c 48.98 28.832 113 | 49.133 28.844 49.277 28.844 c 49.43 28.844 49.582 28.855 49.727 28.855 114 | c 49.785 28.855 49.867 28.855 49.867 28.715 c 49.867 28.641 49.805 28.641 115 | 49.672 28.641 c 49.418 28.641 49.223 28.641 49.223 28.516 c 49.223 28.477 116 | 49.234 28.441 49.242 28.398 c 49.715 26.5 l 51.824 26.5 l 51.535 27.648 117 | 51.375 28.309 51.348 28.41 c 51.281 28.633 51.148 28.641 50.719 28.641 118 | c 50.613 28.641 50.551 28.641 50.551 28.777 c 50.551 28.855 50.633 28.855 119 | 50.648 28.855 c 50.844 28.855 51.336 28.832 51.527 28.832 c 51.672 28.832 120 | 51.824 28.844 51.973 28.844 c 52.125 28.844 52.277 28.855 52.422 28.855 121 | c 52.477 28.855 52.562 28.855 52.562 28.715 c 52.562 28.641 52.5 28.641 122 | 52.367 28.641 c 52.109 28.641 51.918 28.641 51.918 28.516 c 51.918 28.477 123 | 51.93 28.441 51.938 28.398 c h 124 | 52.875 24.656 m f* 125 | 0.75 w 126 | q 1 0 0 1 0 0 cm 127 | 60.816 0.242 m 60.816 27.207 l S Q 128 | 62.324 14.016 m 62.324 13.18 61.648 12.508 60.816 12.508 c 59.984 12.508 129 | 59.309 13.18 59.309 14.016 c 59.309 14.855 59.984 15.531 60.816 15.531 130 | c 61.648 15.531 62.324 14.855 62.324 14.016 c f 131 | 0.0677129 w 132 | q 1 0 0 1 0 0 cm 133 | 62.324 14.016 m 62.324 13.18 61.648 12.508 60.816 12.508 c 59.984 12.508 134 | 59.309 13.18 59.309 14.016 c 59.309 14.855 59.984 15.531 60.816 15.531 135 | c 61.648 15.531 62.324 14.855 62.324 14.016 c S Q 136 | 62.324 1.543 m 62.324 0.707 61.648 0.035 60.816 0.035 c 59.984 0.035 59.309 137 | 0.707 59.309 1.543 c 59.309 2.383 59.984 3.059 60.816 3.059 c 61.648 3.059 138 | 62.324 2.383 62.324 1.543 c f 139 | q 1 0 0 1 0 0 cm 140 | 62.324 1.543 m 62.324 0.707 61.648 0.035 60.816 0.035 c 59.984 0.035 59.309 141 | 0.707 59.309 1.543 c 59.309 2.383 59.984 3.059 60.816 3.059 c 61.648 3.059 142 | 62.324 2.383 62.324 1.543 c S Q 143 | 62.324 26.484 m 62.324 25.652 61.648 24.977 60.816 24.977 c 59.984 24.977 144 | 59.309 25.652 59.309 26.484 c 59.309 27.324 59.984 28 60.816 28 c 61.648 145 | 28 62.324 27.324 62.324 26.484 c f 146 | q 1 0 0 1 0 0 cm 147 | 62.324 26.484 m 62.324 25.652 61.648 24.977 60.816 24.977 c 59.984 24.977 148 | 59.309 25.652 59.309 26.484 c 59.309 27.324 59.984 28 60.816 28 c 61.648 149 | 28 62.324 27.324 62.324 26.484 c S Q 150 | 1 g 151 | 66.441 21.938 8.836 8.836 re f 152 | 0 g 153 | 0.618575 w 154 | q 1 0 0 1 0 0 cm 155 | 66.441 21.938 8.836 8.836 re S Q 156 | 72.961 24.523 m 72.965 24.5 l 72.973 24.477 l 72.977 24.457 l 72.984 24.438 157 | l 72.992 24.398 l 73.008 24.367 l 73.012 24.352 l 73.02 24.336 l 73.027 158 | 24.324 l 73.039 24.312 l 73.047 24.301 l 73.07 24.277 l 73.102 24.262 l 159 | 73.113 24.254 l 73.152 24.238 l 73.172 24.234 l 73.207 24.223 l 73.223 160 | 24.223 l 73.234 24.219 l 73.246 24.219 l 73.262 24.215 l 73.273 24.215 l 161 | 73.289 24.211 l 73.34 24.211 l 73.355 24.207 l 73.375 24.207 l 73.395 24.203 162 | l 73.543 24.203 l 73.723 24.203 73.777 24.203 73.777 24.062 c 73.777 23.988 163 | 73.699 23.988 73.68 23.988 c 73.488 23.988 72.988 24.012 72.793 24.012 164 | c 72.594 24.012 72.102 23.988 71.898 23.988 c 71.844 23.988 71.766 23.988 165 | 71.766 24.129 c 71.766 24.203 71.828 24.203 71.961 24.203 c 71.977 24.203 166 | 72.109 24.203 72.227 24.215 c 72.348 24.23 72.414 24.238 72.414 24.328 167 | c 72.414 24.355 72.406 24.371 72.383 24.461 c 71.969 26.152 l 69.855 26.152 168 | l 70.266 24.523 l 70.328 24.273 70.348 24.203 70.844 24.203 c 71.027 24.203 169 | 71.082 24.203 71.082 24.062 c 71.082 23.988 71.008 23.988 70.984 23.988 170 | c 70.789 23.988 70.293 24.012 70.098 24.012 c 69.898 24.012 69.406 23.988 171 | 69.207 23.988 c 69.148 23.988 69.07 23.988 69.07 24.129 c 69.07 24.203 172 | 69.137 24.203 69.266 24.203 c 69.281 24.203 69.41 24.203 69.531 24.215 c 173 | 69.656 24.23 69.719 24.238 69.719 24.328 c 69.719 24.355 69.707 24.379 174 | 69.688 24.461 c 68.762 28.18 l 68.691 28.449 68.676 28.504 68.129 28.504 175 | c 68.004 28.504 67.941 28.504 67.941 28.645 c 67.941 28.723 68.027 28.723 176 | 68.039 28.723 c 68.234 28.723 68.727 28.699 68.922 28.699 c 69.066 28.699 177 | 69.219 28.707 69.363 28.707 c 69.516 28.707 69.668 28.723 69.812 28.723 178 | c 69.871 28.723 69.953 28.723 69.953 28.582 c 69.953 28.504 69.891 28.504 179 | 69.758 28.504 c 69.504 28.504 69.309 28.504 69.309 28.383 c 69.309 28.34 180 | 69.324 28.305 69.328 28.266 c 69.801 26.363 l 71.91 26.363 l 71.621 27.516 181 | 71.461 28.172 71.434 28.277 c 71.367 28.5 71.234 28.504 70.805 28.504 c 182 | 70.699 28.504 70.641 28.504 70.641 28.645 c 70.641 28.723 70.723 28.723 183 | 70.734 28.723 c 70.93 28.723 71.422 28.699 71.613 28.699 c 71.762 28.699 184 | 71.91 28.707 72.059 28.707 c 72.211 28.707 72.363 28.723 72.512 28.723 185 | c 72.562 28.723 72.648 28.723 72.648 28.582 c 72.648 28.504 72.586 28.504 186 | 72.453 28.504 c 72.195 28.504 72.004 28.504 72.004 28.383 c 72.004 28.34 187 | 72.016 28.305 72.023 28.266 c h 188 | 72.961 24.523 m f* 189 | 0.75 w 190 | q 1 0 0 1 0 0 cm 191 | 0 1.547 m 21.848 1.547 l S Q 192 | q 1 0 0 1 0 0 cm 193 | 0 14.02 m 21.848 14.02 l S Q 194 | q 1 0 0 1 0 0 cm 195 | 0 26.488 m 21.848 26.488 l S Q 196 | 0.804807 w 197 | q 1 0 0 1 0 0 cm 198 | 11.055 0.242 m 11.055 31.293 l S Q 199 | 12.566 14.016 m 12.566 13.18 11.887 12.508 11.055 12.508 c 10.223 12.508 200 | 9.547 13.18 9.547 14.016 c 9.547 14.855 10.223 15.531 11.055 15.531 c 11.887 201 | 15.531 12.566 14.855 12.566 14.016 c f 202 | 0.0677129 w 203 | q 1 0 0 1 0 0 cm 204 | 12.566 14.016 m 12.566 13.18 11.887 12.508 11.055 12.508 c 10.223 12.508 205 | 9.547 13.18 9.547 14.016 c 9.547 14.855 10.223 15.531 11.055 15.531 c 11.887 206 | 15.531 12.566 14.855 12.566 14.016 c S Q 207 | 12.566 1.543 m 12.566 0.707 11.887 0.035 11.055 0.035 c 10.223 0.035 9.547 208 | 0.707 9.547 1.543 c 9.547 2.383 10.223 3.059 11.055 3.059 c 11.887 3.059 209 | 12.566 2.383 12.566 1.543 c f 210 | q 1 0 0 1 0 0 cm 211 | 12.566 1.543 m 12.566 0.707 11.887 0.035 11.055 0.035 c 10.223 0.035 9.547 212 | 0.707 9.547 1.543 c 9.547 2.383 10.223 3.059 11.055 3.059 c 11.887 3.059 213 | 12.566 2.383 12.566 1.543 c S Q 214 | 0.75 w 215 | q 1 0 0 1 0 0 cm 216 | 15.816 26.488 m 15.816 23.859 13.684 21.73 11.055 21.73 c 8.426 21.73 6.293 217 | 23.859 6.293 26.488 c 6.293 29.117 8.426 31.246 11.055 31.246 c 13.684 218 | 31.246 15.816 29.117 15.816 26.488 c S Q 219 | 35.133 13.336 m 35.254 13.336 l 35.266 13.332 l 35.281 13.332 l 35.297 220 | 13.328 l 35.312 13.328 l 35.336 13.32 l 35.352 13.316 l 35.375 13.309 l 221 | 35.391 13.301 l 35.402 13.297 l 35.414 13.289 l 35.449 13.254 l 35.457 13.238 222 | l 35.465 13.23 l 35.465 13.223 l 35.473 13.207 l 35.473 13.199 l 35.477 223 | 13.195 l 35.477 13.176 l 35.48 13.168 l 35.48 13.16 l 35.484 13.152 l 35.484 224 | 13.133 l 35.484 12.926 35.285 12.926 35.145 12.926 c 28.961 12.926 l 28.812 225 | 12.926 28.621 12.926 28.621 13.133 c 28.621 13.336 28.812 13.336 28.969 226 | 13.336 c h 227 | 35.133 13.336 m f* 228 | 35.145 15.344 m 35.168 15.344 l 35.199 15.34 l 35.258 15.34 l 35.27 15.336 229 | l 35.297 15.336 l 35.328 15.328 l 35.34 15.324 l 35.355 15.32 l 35.379 230 | 15.312 l 35.391 15.305 l 35.402 15.301 l 35.422 15.281 l 35.434 15.273 l 231 | 35.441 15.266 l 35.445 15.258 l 35.453 15.25 l 35.457 15.242 l 35.461 15.238 232 | l 35.465 15.23 l 35.465 15.223 l 35.469 15.219 l 35.473 15.211 l 35.473 233 | 15.203 l 35.477 15.195 l 35.477 15.18 l 35.48 15.172 l 35.48 15.164 l 35.484 234 | 15.152 l 35.484 15.137 l 35.484 14.93 35.285 14.93 35.133 14.93 c 28.969 235 | 14.93 l 28.812 14.93 28.621 14.93 28.621 15.137 c 28.621 15.344 28.812 236 | 15.344 28.961 15.344 c h 237 | 35.145 15.344 m f* 238 | Q Q 239 | showpage 240 | %%Trailer 241 | end 242 | %%EOF 243 | -------------------------------------------------------------------------------- /docs/images/constant-bb-useful-identities.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-3.0 2 | %%Creator: cairo 1.16.0 (https://cairographics.org) 3 | %%CreationDate: Mon Jul 13 12:20:15 2020 4 | %%Pages: 1 5 | %%DocumentData: Clean7Bit 6 | %%LanguageLevel: 2 7 | %%BoundingBox: 0 0 184 32 8 | %%EndComments 9 | %%BeginProlog 10 | 50 dict begin 11 | /q { gsave } bind def 12 | /Q { grestore } bind def 13 | /cm { 6 array astore concat } bind def 14 | /w { setlinewidth } bind def 15 | /J { setlinecap } bind def 16 | /j { setlinejoin } bind def 17 | /M { setmiterlimit } bind def 18 | /d { setdash } bind def 19 | /m { moveto } bind def 20 | /l { lineto } bind def 21 | /c { curveto } bind def 22 | /h { closepath } bind def 23 | /re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto 24 | 0 exch rlineto 0 rlineto closepath } bind def 25 | /S { stroke } bind def 26 | /f { fill } bind def 27 | /f* { eofill } bind def 28 | /n { newpath } bind def 29 | /W { clip } bind def 30 | /W* { eoclip } bind def 31 | /BT { } bind def 32 | /ET { } bind def 33 | /BDC { mark 3 1 roll /BDC pdfmark } bind def 34 | /EMC { mark /EMC pdfmark } bind def 35 | /cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def 36 | /Tj { show currentpoint cairo_store_point } bind def 37 | /TJ { 38 | { 39 | dup 40 | type /stringtype eq 41 | { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse 42 | } forall 43 | currentpoint cairo_store_point 44 | } bind def 45 | /cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore 46 | cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def 47 | /Tf { pop /cairo_font exch def /cairo_font_matrix where 48 | { pop cairo_selectfont } if } bind def 49 | /Td { matrix translate cairo_font_matrix matrix concatmatrix dup 50 | /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point 51 | /cairo_font where { pop cairo_selectfont } if } bind def 52 | /Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def 53 | cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def 54 | /g { setgray } bind def 55 | /rg { setrgbcolor } bind def 56 | /d1 { setcachedevice } bind def 57 | /cairo_data_source { 58 | CairoDataIndex CairoData length lt 59 | { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } 60 | { () } ifelse 61 | } def 62 | /cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def 63 | /cairo_image { image cairo_flush_ascii85_file } def 64 | /cairo_imagemask { imagemask cairo_flush_ascii85_file } def 65 | %%EndProlog 66 | %%BeginSetup 67 | %%EndSetup 68 | %%Page: 1 1 69 | %%BeginPageSetup 70 | %%PageBoundingBox: 0 0 184 32 71 | %%EndPageSetup 72 | q 0 0 184 32 rectclip 73 | 1 0 0 -1 0 32 cm q 74 | 0 g 75 | 26.289 8.223 m 26.289 9.055 25.613 9.73 24.781 9.73 c 23.949 9.73 23.273 76 | 9.055 23.273 8.223 c 23.273 7.383 23.949 6.707 24.781 6.707 c 25.613 6.707 77 | 26.289 7.383 26.289 8.223 c f 78 | 0.0677129 w 79 | 0 J 80 | 0 j 81 | [] 0.0 d 82 | 4 M q 1 0 0 1 0 0 cm 83 | 26.289 8.223 m 26.289 9.055 25.613 9.73 24.781 9.73 c 23.949 9.73 23.273 84 | 9.055 23.273 8.223 c 23.273 7.383 23.949 6.707 24.781 6.707 c 25.613 6.707 85 | 26.289 7.383 26.289 8.223 c S Q 86 | 0.75 w 87 | q 1 0 0 1 0 0 cm 88 | 29.543 20.688 m 29.543 23.316 27.414 25.449 24.781 25.449 c 22.152 25.449 89 | 20.02 23.316 20.02 20.688 c 20.02 18.059 22.152 15.93 24.781 15.93 c 27.414 90 | 15.93 29.543 18.059 29.543 20.688 c S Q 91 | 0.722776 w 92 | q 1 0 0 1 0 0 cm 93 | 24.781 25.449 m 24.781 8.176 l S Q 94 | 0.75 w 95 | q 1 0 0 1 0 0 cm 96 | 0 8.219 m 38.012 8.219 l S Q 97 | 1 g 98 | 6.176 3.961 8.836 8.836 re f 99 | 0 g 100 | 0.618575 w 101 | q 1 0 0 1 0 0 cm 102 | 6.176 3.961 8.836 8.836 re S Q 103 | 10.973 6.789 m 10.977 6.781 l 10.977 6.773 l 10.98 6.762 l 10.984 6.746 104 | l 10.988 6.734 l 10.988 6.719 l 10.992 6.711 l 10.996 6.699 l 10.996 6.688 105 | l 11 6.676 l 11.008 6.66 l 11.008 6.652 l 11.02 6.629 l 11.02 6.625 l 11.023 106 | 6.617 l 11.031 6.609 l 11.035 6.602 l 11.043 6.594 l 11.051 6.59 l 11.055 107 | 6.586 l 11.059 6.586 l 11.066 6.582 l 11.07 6.578 l 11.078 6.578 l 11.082 108 | 6.574 l 11.09 6.574 l 11.098 6.57 l 11.102 6.57 l 11.156 6.555 11.352 6.555 109 | 11.477 6.555 c 12.074 6.555 12.34 6.582 12.34 7.043 c 12.34 7.129 12.316 110 | 7.363 12.293 7.516 c 12.289 7.539 12.273 7.613 12.273 7.629 c 12.273 7.664 111 | 12.293 7.707 12.344 7.707 c 12.41 7.707 12.422 7.656 12.434 7.57 c 12.594 112 | 6.539 l 12.602 6.516 12.605 6.457 12.605 6.438 c 12.605 6.375 12.547 6.375 113 | 12.445 6.375 c 9.16 6.375 l 9.016 6.375 9.012 6.379 8.969 6.492 c 8.617 114 | 7.535 l 8.609 7.547 8.582 7.629 8.582 7.641 c 8.582 7.676 8.609 7.707 8.652 115 | 7.707 c 8.711 7.707 8.715 7.676 8.75 7.582 c 9.07 6.664 9.227 6.555 10.102 116 | 6.555 c 10.332 6.555 l 10.5 6.555 10.5 6.582 10.5 6.629 c 10.5 6.664 10.48 117 | 6.734 10.477 6.75 c 9.684 9.914 l 9.629 10.133 9.609 10.199 8.977 10.199 118 | c 8.762 10.199 8.73 10.199 8.73 10.312 c 8.73 10.383 8.793 10.383 8.828 119 | 10.383 c 8.992 10.383 9.156 10.371 9.316 10.371 c 9.48 10.371 9.652 10.363 120 | 9.82 10.363 c 9.984 10.363 10.148 10.371 10.312 10.371 c 10.48 10.371 10.66 121 | 10.383 10.824 10.383 c 10.887 10.383 10.953 10.383 10.953 10.262 c 10.953 122 | 10.199 10.91 10.199 10.754 10.199 c 10.605 10.199 10.531 10.199 10.375 123 | 10.188 c 10.203 10.168 10.156 10.152 10.156 10.059 c 10.156 10.051 10.156 124 | 10.02 10.18 9.934 c h 125 | 10.973 6.789 m f* 126 | 0.75 w 127 | q 1 0 0 1 0 0 cm 128 | 0 20.688 m 38.012 20.688 l S Q 129 | 65.965 8.223 m 65.965 9.055 66.645 9.73 67.477 9.73 c 68.309 9.73 68.984 130 | 9.055 68.984 8.223 c 68.984 7.383 68.309 6.707 67.477 6.707 c 66.645 6.707 131 | 65.965 7.383 65.965 8.223 c f 132 | 0.0677129 w 133 | q 1 0 0 1 0 0 cm 134 | 65.965 8.223 m 65.965 9.055 66.645 9.73 67.477 9.73 c 68.309 9.73 68.984 135 | 9.055 68.984 8.223 c 68.984 7.383 68.309 6.707 67.477 6.707 c 66.645 6.707 136 | 65.965 7.383 65.965 8.223 c S Q 137 | 0.75 w 138 | q 1 0 0 1 0 0 cm 139 | 62.711 20.688 m 62.711 23.316 64.844 25.449 67.473 25.449 c 70.105 25.449 140 | 72.238 23.316 72.238 20.688 c 72.238 18.059 70.105 15.93 67.473 15.93 c 141 | 64.844 15.93 62.711 18.059 62.711 20.688 c S Q 142 | 0.722776 w 143 | q 1 0 0 1 0 0 cm 144 | 67.477 25.449 m 67.477 8.176 l S Q 145 | 0.75 w 146 | q 1 0 0 1 0 0 cm 147 | 92.258 8.219 m 54.242 8.219 l S Q 148 | 1 g 149 | 77.246 3.961 8.836 8.836 re f 150 | 0 g 151 | 0.618575 w 152 | q 1 0 0 1 0 0 cm 153 | 77.246 3.961 8.836 8.836 re S Q 154 | 82.043 6.789 m 82.047 6.781 l 82.047 6.773 l 82.051 6.762 l 82.051 6.746 155 | l 82.055 6.734 l 82.059 6.719 l 82.062 6.711 l 82.062 6.699 l 82.07 6.676 156 | l 82.074 6.668 l 82.074 6.66 l 82.082 6.645 l 82.082 6.637 l 82.086 6.629 157 | l 82.09 6.625 l 82.094 6.617 l 82.094 6.613 l 82.102 6.609 l 82.105 6.602 158 | l 82.117 6.59 l 82.125 6.586 l 82.129 6.586 l 82.133 6.582 l 82.141 6.578 159 | l 82.145 6.578 l 82.152 6.574 l 82.156 6.574 l 82.164 6.57 l 82.172 6.57 160 | l 82.227 6.555 82.422 6.555 82.543 6.555 c 83.141 6.555 83.41 6.582 83.41 161 | 7.043 c 83.41 7.129 83.387 7.363 83.363 7.516 c 83.355 7.539 83.344 7.613 162 | 83.344 7.629 c 83.344 7.664 83.363 7.707 83.414 7.707 c 83.48 7.707 83.492 163 | 7.656 83.5 7.57 c 83.66 6.539 l 83.672 6.516 83.676 6.457 83.676 6.438 164 | c 83.676 6.375 83.617 6.375 83.516 6.375 c 80.23 6.375 l 80.086 6.375 80.082 165 | 6.379 80.039 6.492 c 79.684 7.535 l 79.676 7.547 79.648 7.629 79.648 7.641 166 | c 79.648 7.676 79.68 7.707 79.723 7.707 c 79.781 7.707 79.785 7.676 79.82 167 | 7.582 c 80.141 6.664 80.293 6.555 81.172 6.555 c 81.402 6.555 l 81.566 168 | 6.555 81.566 6.582 81.566 6.629 c 81.566 6.664 81.551 6.734 81.543 6.75 169 | c 80.754 9.914 l 80.699 10.133 80.68 10.199 80.047 10.199 c 79.832 10.199 170 | 79.797 10.199 79.797 10.312 c 79.797 10.383 79.863 10.383 79.898 10.383 171 | c 80.059 10.383 80.223 10.371 80.383 10.371 c 80.551 10.371 80.723 10.363 172 | 80.887 10.363 c 81.055 10.363 81.219 10.371 81.379 10.371 c 81.551 10.371 173 | 81.73 10.383 81.895 10.383 c 81.953 10.383 82.023 10.383 82.023 10.262 174 | c 82.023 10.199 81.977 10.199 81.824 10.199 c 81.676 10.199 81.598 10.199 175 | 81.445 10.188 c 81.27 10.168 81.227 10.152 81.227 10.059 c 81.227 10.051 176 | 81.227 10.02 81.246 9.934 c h 177 | 82.043 6.789 m f* 178 | 0.75 w 179 | q 1 0 0 1 0 0 cm 180 | 92.258 20.688 m 54.242 20.688 l S Q 181 | 49.207 13.938 m 49.328 13.938 l 49.344 13.934 l 49.359 13.934 l 49.371 182 | 13.93 l 49.387 13.93 l 49.402 13.926 l 49.414 13.922 l 49.43 13.918 l 49.453 183 | 13.91 l 49.465 13.902 l 49.477 13.898 l 49.5 13.883 l 49.508 13.871 l 49.52 184 | 13.863 l 49.527 13.855 l 49.535 13.84 l 49.535 13.836 l 49.539 13.832 l 185 | 49.547 13.816 l 49.547 13.812 l 49.551 13.801 l 49.555 13.797 l 49.555 186 | 13.781 l 49.559 13.77 l 49.559 13.734 l 49.559 13.527 49.363 13.527 49.219 187 | 13.527 c 43.039 13.527 l 42.891 13.527 42.699 13.527 42.699 13.734 c 42.699 188 | 13.938 42.891 13.938 43.047 13.938 c h 189 | 49.207 13.938 m f* 190 | 49.219 15.945 m 49.246 15.945 l 49.273 15.941 l 49.332 15.941 l 49.348 191 | 15.938 l 49.375 15.938 l 49.391 15.934 l 49.402 15.93 l 49.418 15.926 l 192 | 49.441 15.918 l 49.457 15.914 l 49.469 15.906 l 49.477 15.902 l 49.488 15.895 193 | l 49.508 15.875 l 49.52 15.867 l 49.523 15.863 l 49.527 15.855 l 49.531 194 | 15.852 l 49.535 15.844 l 49.535 15.84 l 49.539 15.832 l 49.543 15.828 l 195 | 49.547 15.82 l 49.547 15.812 l 49.555 15.797 l 49.555 15.781 l 49.559 15.773 196 | l 49.559 15.738 l 49.559 15.531 49.363 15.531 49.207 15.531 c 43.047 15.531 197 | l 42.891 15.531 42.699 15.531 42.699 15.738 c 42.699 15.945 42.891 15.945 198 | 43.039 15.945 c h 199 | 49.219 15.945 m f* 200 | q 1 0 0 1 0 0 cm 201 | 109.16 1.547 m 130.922 1.547 l S Q 202 | q 1 0 0 1 0 0 cm 203 | 109.16 14.016 m 130.922 14.016 l S Q 204 | q 1 0 0 1 0 0 cm 205 | 109.16 26.488 m 130.922 26.488 l S Q 206 | 121.09 1.543 m 121.09 0.707 120.414 0.035 119.582 0.035 c 118.75 0.035 207 | 118.074 0.707 118.074 1.543 c 118.074 2.383 118.75 3.059 119.582 3.059 c 208 | 120.414 3.059 121.09 2.383 121.09 1.543 c f 209 | 0.0677129 w 210 | q 1 0 0 1 0 0 cm 211 | 121.09 1.543 m 121.09 0.707 120.414 0.035 119.582 0.035 c 118.75 0.035 212 | 118.074 0.707 118.074 1.543 c 118.074 2.383 118.75 3.059 119.582 3.059 c 213 | 120.414 3.059 121.09 2.383 121.09 1.543 c S Q 214 | 0.75 w 215 | q 1 0 0 1 0 0 cm 216 | 124.344 26.488 m 124.344 23.859 122.211 21.727 119.582 21.727 c 116.953 217 | 21.727 114.82 23.859 114.82 26.488 c 114.82 29.117 116.953 31.246 119.582 218 | 31.246 c 122.211 31.246 124.344 29.117 124.344 26.488 c S Q 219 | q 1 0 0 1 0 0 cm 220 | 124.344 14.02 m 124.344 11.387 122.211 9.258 119.582 9.258 c 116.953 9.258 221 | 114.82 11.387 114.82 14.02 c 114.82 16.648 116.953 18.777 119.582 18.777 222 | c 122.211 18.777 124.344 16.648 124.344 14.02 c S Q 223 | q 1 0 0 1 0 0 cm 224 | 119.582 1.277 m 119.582 31.434 l S Q 225 | 144.711 13.137 m 144.801 13.137 l 144.812 13.133 l 144.844 13.133 l 144.859 226 | 13.129 l 144.875 13.129 l 144.887 13.125 l 144.902 13.125 l 144.914 13.121 227 | l 144.93 13.117 l 144.941 13.113 l 144.953 13.105 l 144.969 13.102 l 144.98 228 | 13.094 l 144.988 13.086 l 145 13.082 l 145.02 13.062 l 145.027 13.051 l 229 | 145.031 13.047 l 145.035 13.039 l 145.039 13.035 l 145.043 13.027 l 145.043 230 | 13.023 l 145.051 13.008 l 145.051 13 l 145.055 12.992 l 145.055 12.977 231 | l 145.059 12.969 l 145.059 12.934 l 145.059 12.727 144.863 12.727 144.719 232 | 12.727 c 138.539 12.727 l 138.391 12.727 138.199 12.727 138.199 12.934 233 | c 138.199 13.137 138.391 13.137 138.547 13.137 c h 234 | 144.711 13.137 m f* 235 | 144.719 15.141 m 144.82 15.141 l 144.836 15.137 l 144.863 15.137 l 144.875 236 | 15.133 l 144.891 15.129 l 144.906 15.129 l 144.918 15.121 l 144.93 15.117 237 | l 144.945 15.113 l 144.969 15.105 l 144.98 15.098 l 144.988 15.09 l 145.012 238 | 15.074 l 145.02 15.062 l 145.023 15.059 l 145.027 15.051 l 145.035 15.043 239 | l 145.039 15.035 l 145.043 15.031 l 145.043 15.023 l 145.051 15.008 l 145.051 240 | 15.004 l 145.055 14.996 l 145.055 14.977 l 145.059 14.969 l 145.059 14.934 241 | l 145.059 14.727 144.863 14.727 144.711 14.727 c 138.547 14.727 l 138.391 242 | 14.727 138.199 14.727 138.199 14.934 c 138.199 15.141 138.391 15.141 138.539 243 | 15.141 c h 244 | 144.719 15.141 m f* 245 | q 1 0 0 1 0 0 cm 246 | 151.965 1.68 m 183.816 1.68 l S Q 247 | q 1 0 0 1 0 0 cm 248 | 151.965 14.148 m 183.816 14.148 l S Q 249 | q 1 0 0 1 0 0 cm 250 | 151.965 26.621 m 183.816 26.621 l S Q 251 | 163.895 1.676 m 163.895 0.844 163.219 0.168 162.383 0.168 c 161.555 0.168 252 | 160.875 0.844 160.875 1.676 c 160.875 2.516 161.555 3.191 162.383 3.191 253 | c 163.219 3.191 163.895 2.516 163.895 1.676 c f 254 | 0.0677129 w 255 | q 1 0 0 1 0 0 cm 256 | 163.895 1.676 m 163.895 0.844 163.219 0.168 162.383 0.168 c 161.555 0.168 257 | 160.875 0.844 160.875 1.676 c 160.875 2.516 161.555 3.191 162.383 3.191 258 | c 163.219 3.191 163.895 2.516 163.895 1.676 c S Q 259 | 0.75 w 260 | q 1 0 0 1 0 0 cm 261 | 167.148 14.152 m 167.148 11.523 165.016 9.391 162.387 9.391 c 159.754 9.391 262 | 157.621 11.523 157.621 14.152 c 157.621 16.781 159.754 18.91 162.387 18.91 263 | c 165.016 18.91 167.148 16.781 167.148 14.152 c S Q 264 | q 1 0 0 1 0 0 cm 265 | 162.387 1.414 m 162.387 18.605 l S Q 266 | q 1 0 0 1 0 0 cm 267 | 178.402 26.621 m 178.402 23.992 176.27 21.863 173.641 21.863 c 171.008 268 | 21.863 168.875 23.992 168.875 26.621 c 168.875 29.25 171.008 31.379 173.641 269 | 31.379 c 176.27 31.379 178.402 29.25 178.402 26.621 c S Q 270 | q 1 0 0 1 0 0 cm 271 | 173.637 0.699 m 173.637 31.422 l S Q 272 | 175.148 1.676 m 175.148 0.844 174.469 0.168 173.637 0.168 c 172.805 0.168 273 | 172.129 0.844 172.129 1.676 c 172.129 2.516 172.805 3.191 173.637 3.191 274 | c 174.469 3.191 175.148 2.516 175.148 1.676 c f 275 | 0.0677129 w 276 | q 1 0 0 1 0 0 cm 277 | 175.148 1.676 m 175.148 0.844 174.469 0.168 173.637 0.168 c 172.805 0.168 278 | 172.129 0.844 172.129 1.676 c 172.129 2.516 172.805 3.191 173.637 3.191 279 | c 174.469 3.191 175.148 2.516 175.148 1.676 c S Q 280 | Q Q 281 | showpage 282 | %%Trailer 283 | end 284 | %%EOF 285 | -------------------------------------------------------------------------------- /docs/images/docs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/docs.png -------------------------------------------------------------------------------- /docs/images/exorcism-t-count.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/exorcism-t-count.pdf -------------------------------------------------------------------------------- /docs/images/exorcism-t-depth.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/exorcism-t-depth.pdf -------------------------------------------------------------------------------- /docs/images/github-screencap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/github-screencap.png -------------------------------------------------------------------------------- /docs/images/intellisense.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/intellisense.png -------------------------------------------------------------------------------- /docs/images/kaiser-bio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/kaiser-bio.png -------------------------------------------------------------------------------- /docs/images/matt-toffoli-decomp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/matt-toffoli-decomp.png -------------------------------------------------------------------------------- /docs/images/milestones.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/milestones.png -------------------------------------------------------------------------------- /docs/images/olivia-talk-title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/olivia-talk-title.png -------------------------------------------------------------------------------- /docs/images/qram-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/qram-cover.png -------------------------------------------------------------------------------- /docs/images/qrom-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/qrom-code.png -------------------------------------------------------------------------------- /docs/images/qsc-projects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/qsc-projects.png -------------------------------------------------------------------------------- /docs/images/sarah-twitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/sarah-twitch.png -------------------------------------------------------------------------------- /docs/images/src-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/src-screenshot.png -------------------------------------------------------------------------------- /docs/images/superposition-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/superposition-query.png -------------------------------------------------------------------------------- /docs/images/tests-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/tests-screenshot.png -------------------------------------------------------------------------------- /docs/images/tests-vs-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/images/tests-vs-screenshot.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # This is the **HOMEPAGE**. 2 | Refer to [Markdown](http://daringfireball.net/projects/markdown/) for how to write markdown files. 3 | ## Quick Start Notes: 4 | 1. Add images to the *images* folder if the file is referencing an image. 5 | -------------------------------------------------------------------------------- /docs/primer.bib: -------------------------------------------------------------------------------- 1 | 2 | 3 | @ARTICLE{Vadym2018, 4 | author = {{Hao Low}, Guang and {Kliuchnikov}, Vadym and {Schaeffer}, Luke}, 5 | title = "{Trading T-gates for dirty qubits in state preparation and unitary synthesis}", 6 | journal = {arXiv e-prints}, 7 | keywords = {Quantum Physics}, 8 | year = "2018", 9 | month = "Dec", 10 | eid = {arXiv:1812.00954}, 11 | pages = {arXiv:1812.00954}, 12 | archivePrefix = {arXiv}, 13 | eprint = {1812.00954}, 14 | primaryClass = {quant-ph}, 15 | adsurl = {https://ui.adsabs.harvard.edu/\#abs/2018arXiv181200954H}, 16 | adsnote = {Provided by the SAO/NASA Astrophysics Data System} 17 | } 18 | 19 | @misc{Alexandru2020, 20 | title={Constant Depth Bucket Brigade Quantum RAM Circuits Without Introducing Ancillae}, 21 | author={Alexandru Paler and Oumarou Oumarou and Robert Basmadjian}, 22 | year={2020}, 23 | eprint={2002.09340}, 24 | archivePrefix={arXiv}, 25 | primaryClass={quant-ph} 26 | } 27 | @ARTICLE{MITM, 28 | author={M. {Amy} and D. {Maslov} and M. {Mosca} and M. {Roetteler}}, 29 | journal={IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems}, 30 | title={A Meet-in-the-Middle Algorithm for Fast Synthesis of Depth-Optimal Quantum Circuits}, 31 | year={2013}, 32 | volume={32}, 33 | number={6}, 34 | pages={818-830},} 35 | 36 | @article{tpar, 37 | author={M. {Amy} and D. {Maslov} and M. {Mosca}}, 38 | journal={IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems}, 39 | title={Polynomial-Time T-Depth Optimization of Clifford+T Circuits Via Matroid Partitioning}, 40 | year={2014}, 41 | volume={33}, 42 | number={10}, 43 | pages={1476-1489},} 44 | 45 | @article{Selinger2013, 46 | title = {Quantum circuits of $T$-depth one}, 47 | author = {Selinger, Peter}, 48 | journal = {Phys. Rev. A}, 49 | volume = {87}, 50 | issue = {4}, 51 | pages = {042302}, 52 | numpages = {4}, 53 | year = {2013}, 54 | month = {Apr}, 55 | publisher = {American Physical Society}, 56 | doi = {10.1103/PhysRevA.87.042302}, 57 | url = {https://link.aps.org/doi/10.1103/PhysRevA.87.042302} 58 | } 59 | 60 | @inproceedings{Regev2008, 61 | title={Impossibility of a Quantum Speed-Up with a Faulty Oracle}, 62 | author={Oded Regev and Liron Schiff}, 63 | booktitle={ICALP}, 64 | year={2008} 65 | } 66 | 67 | @phdthesis{DiMatteo2018, 68 | author = "Di Matteo, Olivia", 69 | title = "Methods for parallel quantum circuit synthesis, fault-tolerant quantum RAM, and quantum state tomography", 70 | school = "University of Waterloo", 71 | year = 2019, 72 | address = "Waterloo ON", 73 | month = jan 74 | } 75 | 76 | @article{DiMatteo2020, 77 | author={O. {Di Matteo} and V. {Gheorghiu} and M. {Mosca}}, 78 | journal={IEEE Transactions on Quantum Engineering}, 79 | title={Fault-Tolerant Resource Estimation of Quantum Random-Access Memories}, 80 | year={2020}, 81 | volume={1}, 82 | number={}, 83 | pages={1-13}} 84 | 85 | @article{Babbush2018, 86 | title = {Encoding {Electronic} {Spectra} in {Quantum} {Circuits} with {Linear} {T} {Complexity}}, 87 | url = {http://arxiv.org/abs/1805.03662}, 88 | abstract = {We construct quantum circuits which exactly encode the spectra of correlated electron models up to errors from rotation synthesis. By invoking these circuits as oracles within the recently introduced "qubitization" framework, one can use quantum phase estimation to sample states in the Hamiltonian eigenbasis with optimal query complexity \$O({\textbackslash}lambda / {\textbackslash}epsilon)\$ where \${\textbackslash}lambda\$ is an absolute sum of Hamiltonian coefficients and \${\textbackslash}epsilon\$ is target precision. For both the Hubbard model and electronic structure Hamiltonian in a second quantized basis diagonalizing the Coulomb operator, our circuits have T gate complexity \$O(\{N + {\textbackslash}log (1/{\textbackslash}epsilon\}))\$ where \$N\$ is number of orbitals in the basis. Compared to prior approaches, our algorithms are asymptotically more efficient in gate complexity and require fewer T gates near the classically intractable regime. Compiling to surface code fault-tolerant gates and assuming per gate error rates of one part in a thousand reveals that one can error correct phase estimation on interesting instances of these problems beyond the current capabilities of classical methods using only about one million superconducting qubits in a matter of hours.}, 89 | urldate = {2018-05-31}, 90 | journal = {arXiv:1805.03662 [cond-mat, physics:physics, physics:quant-ph]}, 91 | author = {Babbush, Ryan and Gidney, Craig and Berry, Dominic W. and Wiebe, Nathan and McClean, Jarrod and Paler, Alexandru and Fowler, Austin and Neven, Hartmut}, 92 | month = may, 93 | year = {2018}, 94 | note = {arXiv: 1805.03662}, 95 | keywords = {read}, 96 | file = {arXiv\:1805.03662 PDF:/Users/oliviadimatteo/Zotero/storage/NZ6YI3BU/Babbush et al. - 2018 - Encoding Electronic Spectra in Quantum Circuits wi.pdf:application/pdf;arXiv.org Snapshot:/Users/oliviadimatteo/Zotero/storage/UTFGCCMT/1805.html:text/html} 97 | } 98 | 99 | 100 | 101 | @article{Barenco1995, 102 | title = {Elementary gates for quantum computation}, 103 | author = {Barenco, Adriano and Bennett, Charles H. and Cleve, Richard and DiVincenzo, David P. and Margolus, Norman and Shor, Peter and Sleator, Tycho and Smolin, John A. and Weinfurter, Harald}, 104 | journal = {Phys. Rev. A}, 105 | volume = {52}, 106 | issue = {5}, 107 | pages = {3457--3467}, 108 | numpages = {0}, 109 | year = {1995}, 110 | month = {Nov}, 111 | publisher = {American Physical Society}, 112 | doi = {10.1103/PhysRevA.52.3457}, 113 | url = {https://link.aps.org/doi/10.1103/PhysRevA.52.3457} 114 | } 115 | 116 | @ARTICLE{Kerenidis2016, 117 | author = {{Kerenidis}, I. and {Prakash}, A.}, 118 | title = "{Quantum Recommendation Systems}", 119 | journal = {ArXiv e-prints}, 120 | archivePrefix = "arXiv", 121 | eprint = {1603.08675}, 122 | primaryClass = "quant-ph", 123 | keywords = {Quantum Physics, Computer Science - Data Structures and Algorithms, Computer Science - Information Retrieval}, 124 | year = 2016, 125 | month = mar, 126 | adsurl = {http://adsabs.harvard.edu/abs/2016arXiv160308675K}, 127 | adsnote = {Provided by the SAO/NASA Astrophysics Data System} 128 | } 129 | 130 | 131 | @article{Mishchenko2001, 132 | author = {Mishchenko, Alan and Perkowski, Marek}, 133 | year = {2001}, 134 | month = {09}, 135 | pages = {}, 136 | title = {Fast Heuristic Minimization of Exclusive-Sums-of-Products}, 137 | booktitle = {5th International Reed-Muller Workshop} 138 | } 139 | 140 | @article{Arunachalam2015, 141 | author={Srinivasan Arunachalam and Vlad Gheorghiu and Tomas Jochym-O’Connor and Michele Mosca and Priyaa Varshinee 142 | Srinivasan}, 143 | title={On the robustness of bucket brigade quantum RAM}, 144 | journal={New Journal of Physics}, 145 | volume={17}, 146 | number={12}, 147 | pages={123010}, 148 | url={http://stacks.iop.org/1367-2630/17/i=12/a=123010}, 149 | year={2015} 150 | } 151 | 152 | @misc{OurLibrary, 153 | title = {{qRAM library for Q\#}}, 154 | howpublished = "\url{https://github.com/qsharp-community/qram}" 155 | } 156 | 157 | @misc{abc, 158 | title = {{ABC: System for Sequential Logic Synthesis and Formal Verification}}, 159 | howpublished = "\url{https://github.com/berkeley-abc/abc}" 160 | } 161 | 162 | @article{Giovannetti2008, 163 | title = {Quantum Random Access Memory}, 164 | author = {Giovannetti, Vittorio and Lloyd, Seth and Maccone, Lorenzo}, 165 | journal = {Phys. Rev. Lett.}, 166 | volume = {100}, 167 | issue = {16}, 168 | pages = {160501}, 169 | numpages = {4}, 170 | year = {2008}, 171 | month = {Apr}, 172 | publisher = {American Physical Society}, 173 | doi = {10.1103/PhysRevLett.100.160501}, 174 | url = {https://link.aps.org/doi/10.1103/PhysRevLett.100.160501} 175 | } 176 | 177 | @article{Giovannetti2008b, 178 | title = {Architectures for a quantum random access memory}, 179 | author = {Giovannetti, Vittorio and Lloyd, Seth and Maccone, Lorenzo}, 180 | journal = {Phys. Rev. A}, 181 | volume = {78}, 182 | issue = {5}, 183 | pages = {052310}, 184 | numpages = {9}, 185 | year = {2008}, 186 | month = {Nov}, 187 | publisher = {American Physical Society}, 188 | doi = {10.1103/PhysRevA.78.052310}, 189 | url = {https://link.aps.org/doi/10.1103/PhysRevA.78.052310} 190 | } 191 | 192 | 193 | @article{PhysRevLett.79.325, 194 | Author = {Grover, Lov K.}, 195 | Date-Added = {2016-04-01 15:18:35 +0000}, 196 | Date-Modified = {2016-04-01 15:18:35 +0000}, 197 | Doi = {10.1103/PhysRevLett.79.325}, 198 | Issue = {2}, 199 | Journal = {Phys. Rev. Lett.}, 200 | Month = {Jul}, 201 | Numpages = {0}, 202 | Pages = {325--328}, 203 | Publisher = {American Physical Society}, 204 | Title = {Quantum Mechanics Helps in Searching for a Needle in a Haystack}, 205 | Url = {http://link.aps.org/doi/10.1103/PhysRevLett.79.325}, 206 | Volume = {79}, 207 | Year = {1997}, 208 | Bdsk-Url-1 = {http://link.aps.org/doi/10.1103/PhysRevLett.79.325}, 209 | Bdsk-Url-2 = {http://dx.doi.org/10.1103/PhysRevLett.79.325}} 210 | 211 | @article{HHL, 212 | title = {Quantum Algorithm for Linear Systems of Equations}, 213 | author = {Harrow, Aram W. and Hassidim, Avinatan and Lloyd, Seth}, 214 | journal = {Phys. Rev. Lett.}, 215 | volume = {103}, 216 | issue = {15}, 217 | pages = {150502}, 218 | numpages = {4}, 219 | year = {2009}, 220 | month = {Oct}, 221 | publisher = {American Physical Society}, 222 | doi = {10.1103/PhysRevLett.103.150502}, 223 | url = {https://link.aps.org/doi/10.1103/PhysRevLett.103.150502} 224 | } 225 | 226 | @book{Schuld2018, 227 | address = {Cham}, 228 | author = {Schuld, Maria and Petruccione, Francesco}, 229 | booktitle = {Quantum Science and Technology}, 230 | doi = {10.1007/978-3-319-96424-9}, 231 | file = {:home/olivia/.local/share/data/Mendeley Ltd./Mendeley Desktop/Downloaded/Schuld, Petruccione - 2018 - Supervised Learning with Quantum Computers.pdf:pdf}, 232 | isbn = {978-3-319-96423-2 978-3-319-96424-9}, 233 | language = {en}, 234 | mendeley-groups = {Quantum machine learning}, 235 | month = {apr}, 236 | publisher = {Springer International Publishing}, 237 | series = {Quantum Science and Technology}, 238 | title = {{Supervised Learning with Quantum Computers}}, 239 | url = {http://link.springer.com/10.1007/978-3-319-96424-9 http://files/2097/Schuld and Petruccione - 2018 - Supervised Learning with Quantum Computers.pdf https://link-springer-com.ezproxy.library.ubc.ca/content/pdf/10.1007%2F978-3-319-96424-9.pdf}, 240 | year = {2018} 241 | } 242 | 243 | -------------------------------------------------------------------------------- /docs/primer.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qsharp-community/qram/32cf46af5d95d8184b060d95f4ef895f1abe5725/docs/primer.pdf -------------------------------------------------------------------------------- /docs/project_plan.md: -------------------------------------------------------------------------------- 1 | ## General project goals 2 | 3 | - Proficiency with Q# as a programming language 4 | - Understanding the role of qRAM in quantum computing, its benefits, and costs 5 | - Describe the different memory paradigms in quantum machine learning 6 | 7 | ### Bonus goals 8 | 9 | - Actually run a small qRAM on a quantum machine; how well does it work? 10 | - Describe the different types of classical RAM 11 | - Describe how one might implement a qRAM in hardware 12 | 13 | ## Key Deliverables 14 | 15 | - Q# Library, to be released open-source 16 | - Implementations: 17 | - [ ] Bucket-brigade (original circuit model, and updated constant-depth model) 18 | - [ ] Various qROMs 19 | - [ ] Quantum state preparation ("select/SWAP" oracles) 20 | - [ ] Application-specific qROMs 21 | - Samples: 22 | - [ ] Instantiation and querying all implemented qRAMs/qROMs 23 | - [ ] Resource estimation 24 | - Written report about the different methods used 25 | 26 | ### Pre-reading 27 | 28 | - Learn about how classical RAMs work (bitlines, wordlines, capacitors, structure, etc.) 29 | 30 | ### Step 1 31 | - Set up QDK and Python development environments 32 | - Get acquainted with Q#. Set up QDK and Python 33 | - Work through some of the quantum katas (on-going) 34 | - Read original bucket-brigade qRAM papers (https://arxiv.org/abs/0708.1879, https://arxiv.org/pdf/0807.4994) 35 | 36 | ### Step 2 37 | - Read through work with basic qROM circuits (https://arxiv.org/abs/1902.01329) 38 | - Implement basic large-depth large-width circuits in Q# 39 | - Set up framework for random-generation of such circuits (on-going; should do for these, and all future types) 40 | 41 | ### Step 3 42 | - Implement bucket brigade circuits (https://arxiv.org/abs/1502.03450) 43 | - Implement Alexandru's constant-depth bucket-brigade circuits (https://arxiv.org/abs/2002.09340) 44 | - Start running circuits in the resources estimator and Toffoli simulator machines (on-going) - with random versions of these circuits, how do the gate counts compare to the ones from our paper? 45 | 46 | ### Step 4 47 | - Implement Vadym and Guang-How's state preparation circuits (select/SWAP) (https://arxiv.org/abs/1812.00954) 48 | - Get an idea of the actual constants in the runtime 49 | - Implement qROM from "encoding electronic spectra" paper (https://arxiv.org/abs/1805.03662) 50 | 51 | ### Step 5 52 | - Writing up findings, documenting code, and getting ready for release 53 | - Publish on Blog etc. -------------------------------------------------------------------------------- /docs/rise.css: -------------------------------------------------------------------------------- 1 | /* :root { 2 | --text-color: #FF0072; 3 | } 4 | 5 | body .reveal { 6 | background: black; 7 | font-family: "Source Sans Pro"; 8 | } 9 | /* .reveal p, div.rendered_html */ 10 | /* .reveal h1,.reveal h2,.reveal h3,.reveal h4,.reveal h5,.reveal h6 { 11 | color: var(--text-color); 12 | font-family: "Source Sans Pro" !important; 13 | } */ 14 | -------------------------------------------------------------------------------- /docs/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Articles 2 | href: articles/ 3 | - name: Api Documentation 4 | href: api/ 5 | homepage: api/index.md 6 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: qsharpcommunity-qram 2 | channels: 3 | - conda-forge 4 | - quantum-engineering 5 | dependencies: 6 | - notebook 7 | - numpy 8 | - ipykernel 9 | - qsharp==0.15.2101.125897 10 | - pip 11 | - matplotlib 12 | - pip: 13 | - RISE -------------------------------------------------------------------------------- /samples/BucketBrigade/BucketBrigadeSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/BucketBrigade/BucketBrigadeSample.qs: -------------------------------------------------------------------------------- 1 | namespace BucketBrigadeSample { 2 | 3 | open Microsoft.Quantum.Arrays; 4 | open Microsoft.Quantum.Diagnostics; 5 | open Microsoft.Quantum.Arithmetic; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Convert; 8 | open Microsoft.Quantum.Intrinsic; 9 | open Microsoft.Quantum.Measurement; 10 | 11 | open QsharpCommunity.Qram; 12 | 13 | /// # Summary 14 | /// Generates a Bucket Brigade Qram and looks up the data 15 | /// stored at queryAddress. 16 | /// # Input 17 | /// ## queryAddress 18 | /// Address of the data you want to look up. The data is currently 19 | /// hardcoded below in GenerateMemoryData. 20 | /// # Output 21 | /// The data as an Int that is stored at queryAddress. 22 | /// # Remarks 23 | /// ## Example 24 | /// ```ps 25 | /// dotnet run -- --query-address 2 26 | /// ``` 27 | @EntryPoint() 28 | operation BBBitEncodingSample(queryAddress : Int) : Int { 29 | // Generate a (Int, Bool[]) array of data. 30 | let data = GenerateMemoryData(); 31 | // Create the QRAM. 32 | use flatMemoryRegister = Qubit[(2^data::AddressSize) * data::DataSize]; 33 | let memoryRegister = Most( 34 | Partitioned( 35 | ConstantArray(2^data::AddressSize, data::DataSize), 36 | flatMemoryRegister 37 | ) 38 | ); 39 | 40 | let memory = BucketBrigadeQRAMOracle( 41 | data::DataSet, 42 | MemoryRegister(memoryRegister) 43 | ); 44 | // Measure and return the data value stored at `queryAddress`. 45 | let value = QueryAndMeasureQRAM(memory, MemoryRegister(memoryRegister), queryAddress); 46 | ResetAll(flatMemoryRegister); 47 | return value; 48 | } 49 | 50 | /// # Summary 51 | /// Looks up the data in a memory at a specific address, queryAddress by 52 | /// querying the memory and then measuring the result. 53 | /// # Input 54 | /// ## memory 55 | /// The Qram describing the memory. 56 | /// ## memoryRegister 57 | /// The qubit register holding the data of the Qram. 58 | /// ## queryAddress 59 | /// The address you want to look up the data at. 60 | /// # Output 61 | /// The value in the memory stored at queryAddress as an Int. 62 | operation QueryAndMeasureQRAM( 63 | memory : QRAM, 64 | memoryRegister : MemoryRegister, 65 | queryAddress : Int 66 | ) 67 | : Int { 68 | use (addressRegister, targetRegister) = 69 | (Qubit[memory::AddressSize], Qubit[memory::DataSize]); 70 | ApplyPauliFromBitString(PauliX, true, 71 | IntAsBoolArray(queryAddress, memory::AddressSize), 72 | addressRegister 73 | ); 74 | memory::QueryBit(AddressRegister(addressRegister), 75 | memoryRegister, targetRegister 76 | ); 77 | ResetAll(addressRegister); 78 | return ResultArrayAsInt(MultiM(targetRegister)); 79 | } 80 | 81 | /// # Summary 82 | /// Generates sample data of the form (address, dataValue), here the 83 | /// hardcoded data being [(5, 3), (4, 1), (2, 2)]. 84 | /// # Output 85 | /// Hardcoded data. 86 | function GenerateMemoryData() : MemoryBank { 87 | let numDataBits = 2; 88 | let data = [ 89 | (5, IntAsBoolArray(3, numDataBits)), 90 | (4, IntAsBoolArray(1, numDataBits)), 91 | (2, IntAsBoolArray(2, numDataBits)) 92 | ]; 93 | return GeneratedMemoryBank(Mapped(MemoryCell, data)); 94 | } 95 | } -------------------------------------------------------------------------------- /samples/Grover/Grover.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/Grover/Grover.qs: -------------------------------------------------------------------------------- 1 | namespace GroverSample { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Convert; 4 | open Microsoft.Quantum.Math; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Measurement; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Diagnostics; 9 | open Microsoft.Quantum.Arithmetic; 10 | 11 | open QsharpCommunity.Qram; 12 | 13 | /// # Summary 14 | /// This sample is an adaptation of the Grover sample in the QDK documentation 15 | /// that uses a BucketBrigadeQRAM as an oracle, rather than the usual reflection 16 | /// about marked states. 17 | /// https://github.com/microsoft/Quantum/tree/master/samples/algorithms/simple-grover 18 | /// # Input 19 | /// ## addressSize 20 | /// How many bits to use for your address. 21 | /// ## markedElements 22 | /// The index of the element you want to search for. 23 | /// # Output 24 | /// The index of the marked element. 25 | /// # Remarks 26 | /// ## Example 27 | /// ```ps 28 | /// dotnet run -- --address-size 3 --marked-elements 4 29 | /// ``` 30 | @EntryPoint() 31 | operation GroverSearch(addressSize : Int, markedElements : Int[]) : Int { 32 | // First, set up a qRAM with marked elements set to 1. 33 | let nMarkedElements = Length(markedElements); 34 | mutable groverMemoryContents = Mapped(MemoryCell(_, [false]), RangeAsIntArray(0..2^addressSize - 1)); 35 | 36 | // Set the data value to true for each marked address. 37 | for markedElement in markedElements { 38 | set groverMemoryContents w/= markedElement <- MemoryCell(markedElement, [true]); 39 | } 40 | 41 | use (groverQubits, targetQubit, flatMemoryRegister) = 42 | (Qubit[addressSize], Qubit[1], Qubit[2^addressSize]); 43 | // Create a structured register to make indexing through the memory easier. 44 | let memoryRegister = PartitionMemoryRegister( 45 | flatMemoryRegister, 46 | GeneratedMemoryBank(groverMemoryContents) 47 | ); 48 | // Prepare the memory register with the initial data. 49 | let memory = BucketBrigadeQRAMOracle(groverMemoryContents, memoryRegister); 50 | 51 | // Initialize a uniform superposition over all possible inputs. 52 | PrepareUniform(groverQubits); 53 | 54 | // Grover iterations - the reflection about the marked element is implemented 55 | // as a QRAM phase query. Only the memory cells storing a 1 will produce a phase. 56 | for idxIteration in 0..NIterations(nMarkedElements, addressSize) - 1 { 57 | 58 | memory::QueryPhase(AddressRegister(groverQubits), memoryRegister, targetQubit); 59 | ReflectAboutUniform(groverQubits); 60 | 61 | // It's necessary to remove phase since QueryPhase only sets phase 62 | // on the specific address instead of inverting like traditional Grover's. 63 | ApplyToEach(Z, targetQubit); 64 | ResetAll(targetQubit); 65 | } 66 | ResetAll(flatMemoryRegister); 67 | 68 | // Measure and return the answer. 69 | ResetAll(targetQubit); 70 | return MeasureInteger(LittleEndian(groverQubits)); 71 | } 72 | 73 | /// # Summary 74 | /// Returns the number of Grover iterations needed to find a single marked 75 | /// item, given the number of qubits in a register. 76 | function NIterations(nMarkedElements : Int, nQubits : Int) : Int { 77 | let nItems = 1 <<< nQubits; // 2^numQubits 78 | // compute number of iterations: 79 | let angle = ArcSin(Sqrt(IntAsDouble(nMarkedElements)) / Sqrt(IntAsDouble(nItems))); 80 | let nIterations = Round(0.25 * PI() / angle - 0.5); 81 | return nIterations; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /samples/Grover/Reflections.qs: -------------------------------------------------------------------------------- 1 | namespace GroverSample { 2 | open Microsoft.Quantum.Intrinsic; 3 | open Microsoft.Quantum.Convert; 4 | open Microsoft.Quantum.Math; 5 | open Microsoft.Quantum.Canon; 6 | open Microsoft.Quantum.Arrays; 7 | open Microsoft.Quantum.Measurement; 8 | 9 | /// This sample is an adaptation of the Grover sample in the QDK documentation 10 | /// that uses a BucketBrigadeQRAM as an oracle, rather than the usual reflection 11 | /// about marked states. 12 | /// https://github.com/microsoft/Quantum/tree/master/samples/algorithms/simple-grover 13 | 14 | /// # Summary 15 | /// Reflects about the basis state marked by alternating zeros and ones. 16 | /// This operation defines what input we are trying to find in the main 17 | /// search. 18 | operation ReflectAboutMarked(inputQubits : Qubit[], idxMarkedItem : Int) : Unit { 19 | Message("Reflecting about marked state..."); 20 | use outputQubit = Qubit(); 21 | within { 22 | // We initialize the outputQubit to (|0⟩ - |1⟩) / √2, 23 | // so that toggling it results in a (-1) phase. 24 | X(outputQubit); 25 | H(outputQubit); 26 | // Flip the outputQubit for marked states. 27 | // Here, we get the state with alternating 0s and 1s by using 28 | // the X instruction on every other qubit. 29 | //ApplyToEachA(X, inputQubits[...2...]); 30 | } apply { 31 | (ControlledOnInt(idxMarkedItem, X))(inputQubits, outputQubit); 32 | } 33 | } 34 | 35 | /// # Summary 36 | /// Reflects about the uniform superposition state. 37 | operation ReflectAboutUniform(inputQubits : Qubit[]) : Unit { 38 | within { 39 | // Transform the uniform superposition to all-zero. 40 | Adjoint PrepareUniform(inputQubits); 41 | // Transform the all-zero state to all-ones 42 | PrepareAllOnes(inputQubits); 43 | } apply { 44 | // Now that we've transformed the uniform superposition to the 45 | // all-ones state, reflect about the all-ones state, then let 46 | // the within/apply block transform us back. 47 | ReflectAboutAllOnes(inputQubits); 48 | } 49 | } 50 | 51 | /// # Summary 52 | /// Reflects about the all-ones state. 53 | operation ReflectAboutAllOnes(inputQubits : Qubit[]) : Unit { 54 | Controlled Z(Most(inputQubits), Tail(inputQubits)); 55 | } 56 | 57 | /// # Summary 58 | /// Given a register in the all-zeros state, prepares a uniform 59 | /// superposition over all basis states. 60 | operation PrepareUniform(inputQubits : Qubit[]) : Unit is Adj + Ctl { 61 | ApplyToEachCA(H, inputQubits); 62 | } 63 | 64 | /// # Summary 65 | /// Given a register in the all-zeros state, prepares an all-ones state 66 | /// by flipping every qubit. 67 | operation PrepareAllOnes(inputQubits : Qubit[]) : Unit is Adj + Ctl { 68 | ApplyToEachCA(X, inputQubits); 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/abc.md: -------------------------------------------------------------------------------- 1 | # Command for running exorcism-4 with abc 2 | abc -q "read_pla -x /tmp/test.pla; &get; &exorcism /dev/stdout” 3 | -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/analysis.py: -------------------------------------------------------------------------------- 1 | #/usr/bin/python 2 | 3 | import numpy as np 4 | import os 5 | 6 | from parse_pla import * 7 | from mpmct_resources import * 8 | 9 | # How many random qROMs to generate? 10 | n_random_qroms = 1000 11 | 12 | # Number of address bits 13 | n_min = 5 14 | n_max = 15 15 | 16 | header = ["n", "q", "width", "depth", "tc", "td", "h", "cnot"] 17 | 18 | guessed_filename = "guessed_resources.csv" 19 | exorcised_filename = "exorcised_resources.csv" 20 | 21 | 22 | with open(guessed_filename, "w") as guess_file: 23 | guess_file.write(",".join(header) + "\n") 24 | for n in range(n_min, n_max+1): 25 | # For now 26 | q = n - 1 27 | 28 | guess_resources = [ 29 | n, 30 | q, 31 | 2*n, # width 32 | (2**q) * mpmct_depth(n), 33 | (2**q) * mpmct_t_c(n), 34 | (2**q) * mpmct_t_d(n), 35 | (2**q) * mpmct_h_c(n), 36 | (2**q) * mpmct_cnot_c(n) 37 | ] 38 | 39 | guess_file.write(",".join([str(x) for x in guess_resources]) + "\n") 40 | 41 | 42 | with open(exorcised_filename, "w") as exorcised_file: 43 | exorcised_file.write(",".join(header) + "\n") 44 | for n in range(n_min, n_max+1): 45 | print(f"Working on n={n}") 46 | q = n - 1 47 | for qrom_idx in range(n_random_qroms): 48 | file_string = f"exorcised/n{n}-q{q}-qrom_idx{qrom_idx}" 49 | addresses = np.random.choice(2 ** n, 2 ** q, replace=False) 50 | qrom_to_pla(n, addresses, file_string) 51 | 52 | # Run through EXORCISM-4 53 | cli_string = f"./abc -q \"read_pla -x {file_string}.pla; &get; &exorcism /dev/stdout\" >> {file_string}.exorcised" 54 | os.system(cli_string) 55 | 56 | resources = pla_to_resource_counts(f"{file_string}.exorcised") 57 | 58 | combined_resources = [ 59 | n, 60 | q, 61 | resources["WIDTH"], # width 62 | resources["D"], 63 | resources["TC"], 64 | resources["TD"], 65 | resources["H"], 66 | resources["CNOT"] 67 | ] 68 | 69 | exorcised_file.write(",".join([str(x) for x in combined_resources]) + "\n") 70 | 71 | # print("Guess for resources: ") 72 | # print(guess_resources) 73 | # print("Resources after optimization") 74 | # print(resources) 75 | # print() 76 | -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/guessed_resources.csv: -------------------------------------------------------------------------------- 1 | n,q,width,depth,tc,td,h,cnot 2 | 5,4,10,1280,640,192,224,1280 3 | 6,5,12,3456,1664,512,576,3328 4 | 7,6,14,8704,4096,1280,1408,8192 5 | 8,7,16,20992,9728,3072,3328,19456 6 | 9,8,18,49152,22528,7168,7680,45056 7 | 10,9,20,112640,51200,16384,17408,102400 8 | 11,10,22,253952,114688,36864,38912,229376 9 | 12,11,24,565248,253952,81920,86016,507904 10 | 13,12,26,1245184,557056,180224,188416,1114112 11 | -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/mpmct_resources.py: -------------------------------------------------------------------------------- 1 | # Resources for an MPMCT with n controls 2 | def mpmct_depth(n): 3 | return 28*n - 60 4 | 5 | def mpmct_t_c(n): 6 | return 12*n - 20 7 | 8 | def mpmct_t_d(n): 9 | return 4*(n-2) 10 | 11 | def mpmct_h_c(n): 12 | return 4*n - 6 13 | 14 | def mpmct_cnot_c(n): 15 | return 24*n - 40 16 | -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/parse_pla.py: -------------------------------------------------------------------------------- 1 | from mpmct_resources import * 2 | 3 | def qrom_to_pla(n, ones_addresses, filename): 4 | """ 5 | Translate an n-bit qROM that contains a 1 at multiple addresses to a .pla file. 6 | 7 | Parameters: 8 | n (int): Number of address bits 9 | ones_addresses (list(int))): Locations of 1s in the memory 10 | filename (str): Name prefix for the output file 11 | 12 | Outputs: 13 | A .pla file of the circuit representation of the specified qROM. 14 | """ 15 | 16 | with open(f"{filename}.pla", "w") as pla_file: 17 | # Preamble - specify number of bits, and type 18 | pla_file.write(f".i {n}\n") 19 | pla_file.write(f".o 1\n") 20 | pla_file.write(".type esop\n") 21 | 22 | for address in ones_addresses: 23 | # Get n-bit binary representation 24 | binary_rep = format(address, f"0{n}b") 25 | pla_file.write(f"{binary_rep} 1\n") 26 | 27 | pla_file.write(".e\n") 28 | 29 | 30 | def count_mpmcts(filename): 31 | """ 32 | Given a .pla file with a list of MPMCT gates, tally up the number 33 | of gates with each different number of controls 34 | 35 | Parameters: 36 | filename (str): Name of a .pla-formatted file 37 | 38 | Outputs: 39 | num_total_controls (int): the maximum number of control bits 40 | mpmct_tally (dict[int, int])): A dictionary with keys as the number of control bits 41 | and values as the number of occurences of that many controls in the .pla file. 42 | """ 43 | 44 | mpmct_tally = {} 45 | num_total_controls = -1 46 | 47 | # Use the output PLA file to determine how many MPMCTs with each 48 | # different number of possible controls 49 | with open(filename, "r") as exorcised_file: 50 | gate_lines = exorcised_file.readlines()[11:-1] 51 | 52 | for line in gate_lines: 53 | control_string = line.strip().split(" ")[0] 54 | num_controls = len(control_string) - control_string.count("-") 55 | 56 | if num_total_controls == -1: 57 | num_total_controls = len(control_string) 58 | 59 | if num_controls not in mpmct_tally: 60 | mpmct_tally[num_controls] = 1 61 | else: 62 | mpmct_tally[num_controls] += 1 63 | 64 | return num_total_controls, mpmct_tally 65 | 66 | 67 | def pla_to_resource_counts(filename): 68 | """ 69 | Given a .pla file, determine the amount of Clifford+T resources required. 70 | 71 | Resources are a worst-case estimate obtained by counting the number of MPMCTs with 72 | each different number of controls, and adding the number of resources required for each. 73 | (No further simplification is done.) 74 | 75 | Parameters: 76 | filename (str): Name prefix for the output file 77 | 78 | Outputs: 79 | resources (dict[string, int]): A dictionary indicating estimated resources and their 80 | quantity for the Boolean circuit in the input file. 81 | "WIDTH" -> number of qubits 82 | "D" -> circuit depth 83 | "TC" -> T-count (includes both T and its inverse) 84 | "TD" -> T-depth (number of layers of depth containing T and/or its inverse) 85 | "H" -> Hadamard count 86 | "CNOT" -> CNOT count 87 | """ 88 | 89 | resources = { 90 | "WIDTH" : 0, # TODO 91 | "D" : 0, 92 | "TC" : 0, 93 | "TD" : 0, 94 | "H" : 0, 95 | "CNOT" : 0 96 | } 97 | 98 | num_total_controls, mpmct_tally = count_mpmcts(filename) 99 | 100 | # Number of aux qubits needed; it is at most n - 1, but depends on the 101 | # largest MPMCT after optimization. Suppose that has c controls, then we can 102 | # use the idle n - c as aux qubits as well, so total is 2*c - n - 1 103 | largest_num_controls = max(list(mpmct_tally.keys())) 104 | num_aux_required = max(0, 2 * largest_num_controls - num_total_controls - 1) 105 | 106 | # Total qubits required is n + 1 + aux 107 | resources["WIDTH"] = num_total_controls + 1 + num_aux_required 108 | 109 | # Go through the dictionary now and get resource counts for everything 110 | for num_controls, num_occs in mpmct_tally.items(): 111 | # Special case: CNOT 112 | if num_controls == 1: 113 | resources["D"] += 1 114 | resources["CNOT"] += num_occs 115 | # Special case: Toffoli; use the one in the primer 116 | # TODO: update to add T-depth 1 version 117 | elif num_controls == 2: 118 | resources["D"] += num_occs * 10 119 | resources["TC"] += num_occs * 7 120 | resources["TD"] += num_occs * 3 121 | resources["H"] += num_occs * 2 122 | resources["CNOT"] += num_occs * 7 123 | # TODO: get a more optimized version of this circuit that's not just 124 | # the three Toffolis stacked together 125 | elif num_controls == 3: 126 | resources["D"] += num_occs * 27 127 | resources["TC"] += num_occs * 21 128 | resources["TD"] += num_occs * 9 129 | resources["H"] += num_occs * 6 130 | resources["CNOT"] += num_occs * 21 131 | # For k >= 4, can use the formulas from 1902.01329O 132 | # TODO: add explicit resource counts for 3 controls; also look into whether 133 | # we can do the larger ones without any aux qubits 134 | else: 135 | resources["D"] += num_occs * mpmct_depth(num_controls) 136 | resources["TC"] += num_occs * mpmct_t_c(num_controls) 137 | resources["TD"] += num_occs * mpmct_t_d(num_controls) 138 | resources["H"] += num_occs * mpmct_h_c(num_controls) 139 | resources["CNOT"] += num_occs * mpmct_cnot_c(num_controls) 140 | 141 | return resources -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/test_exorcisms/all_max.exorcised: -------------------------------------------------------------------------------- 1 | # EXORCISM-4 output for command line arguments: "-Q 2 -V 0" 2 | # Minimization performed Mon Aug 24 09:45:08 2020 3 | # Initial statistics: Cubes = 10 Literals = 44 QCost = 260 4 | # Final statistics: Cubes = 6 Literals = 19 QCost = 86 5 | # File reading and reordering time = 0.00 sec 6 | # Starting cover generation time = 0.00 sec 7 | # Pure ESOP minimization time = 0.00 sec 8 | .i 5 9 | .o 1 10 | .p 6 11 | .type esop 12 | 00001 1 13 | 00011 1 14 | 10000 1 15 | 01111 1 16 | 10100 1 17 | 11100 1 18 | .e 19 | -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/test_exorcisms/all_min.exorcised: -------------------------------------------------------------------------------- 1 | # EXORCISM-4 output for command line arguments: "-Q 2 -V 0" 2 | # Minimization performed Mon Aug 24 09:45:08 2020 3 | # Initial statistics: Cubes = 10 Literals = 44 QCost = 260 4 | # Final statistics: Cubes = 6 Literals = 19 QCost = 86 5 | # File reading and reordering time = 0.00 sec 6 | # Starting cover generation time = 0.00 sec 7 | # Pure ESOP minimization time = 0.00 sec 8 | .i 4 9 | .o 1 10 | .p 4 11 | .type esop 12 | ---1 1 13 | --1- 1 14 | -1-- 1 15 | 1--- 1 16 | .e 17 | -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/test_exorcisms/one_each.exorcised: -------------------------------------------------------------------------------- 1 | # EXORCISM-4 output for command line arguments: "-Q 2 -V 0" 2 | # Minimization performed Mon Aug 24 09:45:08 2020 3 | # Initial statistics: Cubes = 10 Literals = 44 QCost = 260 4 | # Final statistics: Cubes = 6 Literals = 19 QCost = 86 5 | # File reading and reordering time = 0.00 sec 6 | # Starting cover generation time = 0.00 sec 7 | # Pure ESOP minimization time = 0.00 sec 8 | .i 8 9 | .o 1 10 | .p 8 11 | .type esop 12 | 11111111 1 13 | -1111111 1 14 | --111111 1 15 | ---11111 1 16 | ----1111 1 17 | -----111 1 18 | ------11 1 19 | -------1 1 20 | .e 21 | -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/test_exorcisms/random.exorcised: -------------------------------------------------------------------------------- 1 | # EXORCISM-4 output for command line arguments: "-Q 2 -V 0" 2 | # Minimization performed Mon Aug 24 09:45:08 2020 3 | # Initial statistics: Cubes = 10 Literals = 44 QCost = 260 4 | # Final statistics: Cubes = 6 Literals = 19 QCost = 86 5 | # File reading and reordering time = 0.00 sec 6 | # Starting cover generation time = 0.00 sec 7 | # Pure ESOP minimization time = 0.00 sec 8 | .i 7 9 | .o 1 10 | .p 15 11 | .type esop 12 | ---10-1 1 13 | -0--111 1 14 | -1---11 1 15 | -0----1 1 16 | -----01 1 17 | 10--0-- 1 18 | 11-1111 1 19 | -11-011 1 20 | 1-01111 1 21 | ---1111 1 22 | 0000011 1 23 | 0100-11 1 24 | -101--1 1 25 | 1-----1 1 26 | 10---1- 1 27 | .e 28 | -------------------------------------------------------------------------------- /samples/Python-ResourceEstimation/test_parse_pla.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from parse_pla import * 4 | 5 | class TestMPMCTTally: 6 | def test_all_max(self): 7 | expected_num_total_controls = 5 8 | expected_mpmct_tally = {5 : 6} 9 | 10 | num_total_controls, mpmct_tally = count_mpmcts("test_exorcisms/all_max.exorcised") 11 | 12 | assert num_total_controls == expected_num_total_controls 13 | assert mpmct_tally == expected_mpmct_tally 14 | 15 | def test_all_min(self): 16 | expected_num_total_controls = 4 17 | expected_mpmct_tally = {1 : 4} 18 | 19 | num_total_controls, mpmct_tally = count_mpmcts("test_exorcisms/all_min.exorcised") 20 | 21 | assert num_total_controls == expected_num_total_controls 22 | assert mpmct_tally == expected_mpmct_tally 23 | 24 | def test_one_each(self): 25 | expected_num_total_controls = 8 26 | expected_mpmct_tally = {x : 1 for x in range(1, expected_num_total_controls + 1)} 27 | 28 | num_total_controls, mpmct_tally = count_mpmcts("test_exorcisms/one_each.exorcised") 29 | 30 | assert num_total_controls == expected_num_total_controls 31 | assert mpmct_tally == expected_mpmct_tally 32 | 33 | def test_random(self): 34 | expected_num_total_controls = 7 35 | expected_mpmct_tally = {2 : 3, 3 : 4, 4 : 3, 5 : 1, 6 : 3, 7 : 1} 36 | 37 | num_total_controls, mpmct_tally = count_mpmcts("test_exorcisms/random.exorcised") 38 | 39 | assert num_total_controls == expected_num_total_controls 40 | assert mpmct_tally == expected_mpmct_tally -------------------------------------------------------------------------------- /samples/Qrom/QromSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Exe 9 | netcoreapp3.1 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/Qrom/QromSample.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "application/json": "{\"LastUpdated\":\"2020-08-19T20:43:06.5847603+00:00\",\"IsCompleted\":true,\"Description\":\"Adding package QSharpCommunity.Libraries.Qram::1.0.0\",\"Subtask\":\"done\"}", 11 | "text/plain": [ 12 | "Adding package QSharpCommunity.Libraries.Qram::1.0.0: done!" 13 | ] 14 | }, 15 | "metadata": {}, 16 | "output_type": "display_data" 17 | }, 18 | { 19 | "data": { 20 | "application/json": "[\"Microsoft.Quantum.Standard::0.13.20102604\",\"QSharpCommunity.Libraries.Qram::1.0.0\"]", 21 | "text/html": [ 22 | "" 23 | ], 24 | "text/plain": [ 25 | "Microsoft.Quantum.Standard::0.13.20102604, QSharpCommunity.Libraries.Qram::1.0.0" 26 | ] 27 | }, 28 | "execution_count": 1, 29 | "metadata": {}, 30 | "output_type": "execute_result" 31 | } 32 | ], 33 | "source": [ 34 | "%package QSharpCommunity.Libraries.Qram::1.0.0" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 5, 40 | "metadata": {}, 41 | "outputs": [ 42 | { 43 | "data": { 44 | "application/json": "[\"QromSample.GenerateMemoryData\",\"QromSample.QromQuerySample\",\"QromSample.QueryAndMeasureQROM\"]", 45 | "text/html": [ 46 | "" 47 | ], 48 | "text/plain": [ 49 | "QromSample.GenerateMemoryData, QromSample.QromQuerySample, QromSample.QueryAndMeasureQROM" 50 | ] 51 | }, 52 | "execution_count": 5, 53 | "metadata": {}, 54 | "output_type": "execute_result" 55 | } 56 | ], 57 | "source": [ 58 | "%workspace reload" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 6, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "data": { 68 | "application/json": "5", 69 | "text/plain": [ 70 | "5" 71 | ] 72 | }, 73 | "execution_count": 6, 74 | "metadata": {}, 75 | "output_type": "execute_result" 76 | } 77 | ], 78 | "source": [ 79 | "%simulate QromSample.QromQuerySample queryAddress=2" 80 | ] 81 | } 82 | ], 83 | "metadata": { 84 | "kernelspec": { 85 | "display_name": "Q#", 86 | "language": "qsharp", 87 | "name": "iqsharp" 88 | }, 89 | "language_info": { 90 | "file_extension": ".qs", 91 | "mimetype": "text/x-qsharp", 92 | "name": "qsharp", 93 | "version": "0.12" 94 | } 95 | }, 96 | "nbformat": 4, 97 | "nbformat_minor": 4 98 | } 99 | -------------------------------------------------------------------------------- /samples/Qrom/QromSample.qs: -------------------------------------------------------------------------------- 1 | namespace QromSample { 2 | 3 | open Microsoft.Quantum.Arrays; 4 | open Microsoft.Quantum.Diagnostics; 5 | open Microsoft.Quantum.Arithmetic; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Convert; 8 | open Microsoft.Quantum.Intrinsic; 9 | open Microsoft.Quantum.Measurement; 10 | 11 | open QsharpCommunity.Qram; 12 | 13 | /// # Summary 14 | /// Does a quick test of creating an implicit QRAM and then looks up a 15 | /// specific data value stored in it. 16 | /// # Input 17 | /// ## queryAddress 18 | /// The address you want to lookup. 19 | /// # Output 20 | /// The data value stored at `queryAddress`. 21 | /// # Remarks 22 | /// ## Example 23 | /// ```ps 24 | /// dotnet run -- --query-address 2 25 | /// ``` 26 | @EntryPoint() 27 | operation QromQuerySample(queryAddress : Int) : Int { 28 | // Generate a (Int, Bool[]) array of data. 29 | let data = GenerateMemoryData(); 30 | // Create the QRAM. 31 | let memory = QromOracle(data::DataSet); 32 | // Measure and return the data value stored at `queryAddress`. 33 | return QueryAndMeasureQROM(memory, queryAddress); 34 | } 35 | 36 | /// # Summary 37 | /// Takes a QRAM and tells you what data is stored at a single address. 38 | /// # Input 39 | /// ## memory 40 | /// A QRAM to query. 41 | /// ## queryAddress 42 | /// The address you want to look up. 43 | /// # Output 44 | /// The data stored at `queryAddress` expressed as a human readable integer. 45 | operation QueryAndMeasureQROM(memory : QROM, queryAddress : Int) : Int { 46 | use (addressRegister, targetRegister) = (Qubit[memory::AddressSize], Qubit[memory::DataSize]); 47 | ApplyPauliFromBitString (PauliX, true, IntAsBoolArray(queryAddress, memory::AddressSize), addressRegister); 48 | memory::Read(LittleEndian(addressRegister), targetRegister); 49 | ResetAll(addressRegister); 50 | return MeasureInteger(LittleEndian(targetRegister)); 51 | } 52 | 53 | /// # Summary 54 | /// Generates sample data of the form (address, dataValue), here the 55 | /// hardcoded data being [(5, 3), (4, 2), (0, 0), (2, 5)]. 56 | /// # Output 57 | /// Hardcoded data. 58 | function GenerateMemoryData() : MemoryBank { 59 | let numDataBits = 3; 60 | let data = [(5, IntAsBoolArray(3, numDataBits)), 61 | (4, IntAsBoolArray(2, numDataBits)), 62 | (0, IntAsBoolArray(0, numDataBits)), 63 | (2, IntAsBoolArray(5, numDataBits))]; 64 | return GeneratedMemoryBank(Mapped(MemoryCell, data)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /samples/ResourceEstimation/Operations.qs: -------------------------------------------------------------------------------- 1 | namespace ResourceEstimation { 2 | open Microsoft.Quantum.Arrays; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Arithmetic; 5 | open Microsoft.Quantum.Canon; 6 | open Microsoft.Quantum.Convert; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Measurement; 9 | open QsharpCommunity.Qram; 10 | 11 | operation QromQuerySample(rawData : (Int, Bool[])[], queryAddress : Int) : Int { 12 | // Generate a (Int, Bool[]) array of data. 13 | let data = ParseMemoryData(rawData); 14 | // Create the QRAM. 15 | let memory = QromOracle(data::DataSet); 16 | // Measure and return the data value stored at `queryAddress`. 17 | return QueryAndMeasureQROM(memory, queryAddress); 18 | } 19 | 20 | operation QueryAndMeasureQROM(memory : QROM, queryAddress : Int) : Int { 21 | use (addressRegister, targetRegister) = (Qubit[memory::AddressSize], Qubit[memory::DataSize]); 22 | ApplyPauliFromBitString (PauliX, true, IntAsBoolArray(queryAddress, memory::AddressSize), addressRegister); 23 | memory::Read(LittleEndian(addressRegister), targetRegister); 24 | ResetAll(addressRegister); 25 | return MeasureInteger(LittleEndian(targetRegister)); 26 | } 27 | 28 | function ParseMemoryData(data : (Int, Bool[])[]) : MemoryBank{ 29 | return GeneratedMemoryBank(Mapped(MemoryCell, data)); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /samples/ResourceEstimation/QromEstimation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "Adding package QSharpCommunity.Libraries.Qram." 13 | ] 14 | } 15 | ], 16 | "source": [ 17 | "import numpy as np\n", 18 | "import collections, functools, operator\n", 19 | "import qsharp\n", 20 | "qsharp.packages.add(\"QSharpCommunity.Libraries.Qram\")\n", 21 | "from ResourceEstimation import QromQuerySample" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 2, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "qsharp.reload()" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 3, 36 | "metadata": {}, 37 | "outputs": [ 38 | { 39 | "data": { 40 | "text/plain": [ 41 | "['ResourceEstimation.ParseMemoryData',\n", 42 | " 'ResourceEstimation.QromQuerySample',\n", 43 | " 'ResourceEstimation.QueryAndMeasureQROM']" 44 | ] 45 | }, 46 | "execution_count": 3, 47 | "metadata": {}, 48 | "output_type": "execute_result" 49 | } 50 | ], 51 | "source": [ 52 | "qsharp.get_available_operations()" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 4, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "# Memory parameters\n", 62 | "n_address_bits = 5 \n", 63 | "n_output_bits = 2\n", 64 | "n_ones_addresses = 4\n", 65 | "# Number of memories to test\n", 66 | "n_random_memories = 10" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": 5, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [ 75 | "# Can't have more addresses with ones than there are addresses\n", 76 | "assert(n_ones_addresses < 2**n_address_bits)\n", 77 | "\n", 78 | "# Random memory generation\n", 79 | "resource_estimates = []\n", 80 | "\n", 81 | "for sample_memory in range(n_random_memories):\n", 82 | " \n", 83 | " # Generate random address \n", 84 | " random_addresses = list(map(int, np.random.choice(range(2**n_address_bits), size=(n_ones_addresses, ), replace=False)))\n", 85 | " \n", 86 | " # Generate random values\n", 87 | " random_values = [list(map(bool, np.random.choice([False, True], n_output_bits, replace=True))) \n", 88 | " for _ in range(len(random_addresses))]\n", 89 | " \n", 90 | " # Combine for MemoryCell-Like structure\n", 91 | " raw_data = list(Zipped(random_addresses, random_values))\n", 92 | " \n", 93 | " # Print the memory contents if you want\n", 94 | " #or memory_cell in data\n", 95 | " # print(f\"Address: {memory_cell[0]}\\t Contents: {memory_cell[1]}\")\n", 96 | " \n", 97 | " estimate = QromQuerySample.estimate_resources(rawData = raw_data, queryAddress=0)\n", 98 | " \n", 99 | " resource_estimates.append(estimate)\n", 100 | " \n", 101 | "resource_estimate_total = dict(functools.reduce(operator.add, map(collections.Counter, resource_estimates)))\n", 102 | "resource_estimate_ave = {k:v/n_random_memories for k, v, in resource_estimate_total.items()}" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 6, 108 | "metadata": {}, 109 | "outputs": [ 110 | { 111 | "data": { 112 | "text/plain": [ 113 | "{'CNOT': 2800,\n", 114 | " 'QubitClifford': 780,\n", 115 | " 'Measure': 70,\n", 116 | " 'T': 1960,\n", 117 | " 'Depth': 1280,\n", 118 | " 'Width': 100}" 119 | ] 120 | }, 121 | "execution_count": 6, 122 | "metadata": {}, 123 | "output_type": "execute_result" 124 | } 125 | ], 126 | "source": [ 127 | "resource_estimate_total" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": 7, 133 | "metadata": {}, 134 | "outputs": [ 135 | { 136 | "data": { 137 | "text/plain": [ 138 | "{'CNOT': 280.0,\n", 139 | " 'QubitClifford': 78.0,\n", 140 | " 'Measure': 7.0,\n", 141 | " 'T': 196.0,\n", 142 | " 'Depth': 128.0,\n", 143 | " 'Width': 10.0}" 144 | ] 145 | }, 146 | "execution_count": 7, 147 | "metadata": {}, 148 | "output_type": "execute_result" 149 | } 150 | ], 151 | "source": [ 152 | "resource_estimate_ave" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": 8, 158 | "metadata": {}, 159 | "outputs": [ 160 | { 161 | "data": { 162 | "text/plain": [ 163 | "{'iqsharp': LooseVersion ('0.13.20102604'),\n", 164 | " 'Jupyter Core': LooseVersion ('1.4.0.0'),\n", 165 | " '.NET Runtime': LooseVersion ('.NETCoreApp,Version=v3.1'),\n", 166 | " 'qsharp': LooseVersion ('0.12.2008.2513')}" 167 | ] 168 | }, 169 | "execution_count": 8, 170 | "metadata": {}, 171 | "output_type": "execute_result" 172 | } 173 | ], 174 | "source": [ 175 | "qsharp.component_versions()" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [] 184 | } 185 | ], 186 | "metadata": { 187 | "kernelspec": { 188 | "display_name": "Python 3", 189 | "language": "python", 190 | "name": "python3" 191 | }, 192 | "language_info": { 193 | "codemirror_mode": { 194 | "name": "ipython", 195 | "version": 3 196 | }, 197 | "file_extension": ".py", 198 | "mimetype": "text/x-python", 199 | "name": "python", 200 | "nbconvert_exporter": "python", 201 | "pygments_lexer": "ipython3", 202 | "version": "3.7.8" 203 | } 204 | }, 205 | "nbformat": 4, 206 | "nbformat_minor": 4 207 | } 208 | -------------------------------------------------------------------------------- /samples/ResourceEstimation/ResourceEstimation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.Quantum.Simulation.Simulators; 4 | using Microsoft.Quantum.Simulation.Core; 5 | 6 | namespace QromSample 7 | { 8 | class Program 9 | { 10 | static async Task Main(string[] args) 11 | { 12 | var rng = new System.Random(); 13 | var queryAddress = rng.Next(0, 7); 14 | var estimator = new ResourcesEstimator(); 15 | var output = await QromQuerySample.Run(estimator, queryAddress); 16 | 17 | // Print out a table of required resources, using the 18 | // ToTSV method of the ResourcesEstimator. 19 | Console.WriteLine(estimator.ToTSV()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /samples/ResourceEstimation/ResourceEstimation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Exe 9 | netcoreapp3.1 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/SelectSwap/SelectSwapSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Exe 9 | netcoreapp3.1 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/SelectSwap/SelectSwapSample.qs: -------------------------------------------------------------------------------- 1 | namespace SelectSwapSample { 2 | 3 | open Microsoft.Quantum.Arrays; 4 | open Microsoft.Quantum.Diagnostics; 5 | open Microsoft.Quantum.Arithmetic; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Convert; 8 | open Microsoft.Quantum.Intrinsic; 9 | open Microsoft.Quantum.Measurement; 10 | 11 | open QsharpCommunity.Qram; 12 | 13 | /// # Summary 14 | /// Does a quick test of creating an implicit QRAM and then looks up a 15 | /// specific data value stored in it. 16 | /// # Input 17 | /// ## tradeoffParameter 18 | /// VALID VALUES HERE ARE {1, 2, 3} 19 | /// # Output 20 | /// The data value stored at `queryAddress`. 21 | /// # Remarks 22 | /// ## Example 23 | /// ```ps 24 | /// dotnet run -- --tradeoff-parameter 2 25 | /// ``` 26 | @EntryPoint() 27 | operation QromQuerySample(tradeoffParameter : Int) : Int[] { 28 | // Generate a (Int, Bool[]) array of data. 29 | let data = GenerateMemoryData(); 30 | // Create the QRAM. 31 | let memory = SelectSwapQromOracle(data::DataSet, tradeoffParameter); 32 | // Measure and return the data value stored at `queryAddress`. 33 | mutable results = new Int[2^data::AddressSize]; 34 | for (address in 0..2^data::AddressSize-1) { 35 | set results w/= address <- QueryAndMeasureQROM(memory, address); 36 | } 37 | 38 | return results; 39 | } 40 | 41 | /// # Summary 42 | /// Takes a QRAM and tells you what data is stored at a single address. 43 | /// # Input 44 | /// ## memory 45 | /// A QRAM to query. 46 | /// ## queryAddress 47 | /// The address you want to look up. 48 | /// # Outputs 49 | /// The data stored at `queryAddress` expressed as a human readable integer. 50 | operation QueryAndMeasureQROM(memory : QROM, queryAddress : Int) : Int { 51 | using ((addressRegister, targetRegister) = 52 | (Qubit[memory::AddressSize], Qubit[memory::DataSize]) 53 | ) { 54 | ApplyPauliFromBitString (PauliX, true, IntAsBoolArray(queryAddress, memory::AddressSize), addressRegister); 55 | memory::Read(LittleEndian(addressRegister), targetRegister); 56 | ResetAll(addressRegister); 57 | return MeasureInteger(LittleEndian(targetRegister)); 58 | } 59 | } 60 | 61 | /// # Summary 62 | /// Generates sample data of the form (address, dataValue), here the 63 | /// hardcoded data being [(5, 3), (4, 2), (0, 0), (2, 5)]. 64 | /// # Output 65 | /// Hardcoded data. 66 | function GenerateMemoryData() : MemoryBank { 67 | let numDataBits = 2; 68 | let data = [ 69 | (0, IntAsBoolArray(0, numDataBits)), 70 | (1, IntAsBoolArray(1, numDataBits)), 71 | (2, IntAsBoolArray(2, numDataBits)), 72 | (3, IntAsBoolArray(3, numDataBits)), 73 | (4, IntAsBoolArray(0, numDataBits)), 74 | (5, IntAsBoolArray(1, numDataBits)), 75 | (6, IntAsBoolArray(2, numDataBits)), 76 | (7, IntAsBoolArray(3, numDataBits)), 77 | (8, IntAsBoolArray(0, numDataBits)), 78 | (9, IntAsBoolArray(1, numDataBits)), 79 | (10, IntAsBoolArray(2, numDataBits)), 80 | (11, IntAsBoolArray(3, numDataBits)), 81 | (12, IntAsBoolArray(0, numDataBits)), 82 | (13, IntAsBoolArray(1, numDataBits)), 83 | (14, IntAsBoolArray(2, numDataBits)), 84 | (15, IntAsBoolArray(3, numDataBits)) 85 | ]; 86 | return GeneratedMemoryBank(Mapped(MemoryCell, data)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/BucketBrigade.qs: -------------------------------------------------------------------------------- 1 | namespace QsharpCommunity.Qram{ 2 | 3 | open Microsoft.Quantum.Math; 4 | open Microsoft.Quantum.Convert; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Arithmetic; 9 | open Microsoft.Quantum.Measurement; 10 | open Microsoft.Quantum.Diagnostics; 11 | 12 | /////////////////////////////////////////////////////////////////////////// 13 | // PUBLIC API 14 | /////////////////////////////////////////////////////////////////////////// 15 | 16 | /// # Summary 17 | /// Creates a QRAM type corresponding to a bit encoded Bucket Brigade scheme. 18 | /// # Input 19 | /// ## dataValues 20 | /// The data to be stored in the memory. 21 | /// ## memoryRegister 22 | /// The register that you want to be initialized with the provided data. 23 | /// # Output 24 | /// An instance of the QRAM type that will allow you to use the memory. 25 | operation BucketBrigadeQRAMOracle(dataValues : MemoryCell[], memoryRegister : MemoryRegister) : QRAM { 26 | let bank = GeneratedMemoryBank(dataValues); 27 | 28 | for cell in bank::DataSet { 29 | BucketBrigadeWrite(memoryRegister, cell); 30 | } 31 | 32 | return Default() 33 | w/ QueryPhase <- BucketBrigadeReadPhase(_, _, _) 34 | w/ QueryBit <- BucketBrigadeReadBit(_, _, _) 35 | w/ Write <- BucketBrigadeWrite(_, _) 36 | w/ AddressSize <- bank::AddressSize 37 | w/ DataSize <- bank::DataSize; 38 | } 39 | 40 | 41 | 42 | /////////////////////////////////////////////////////////////////////////// 43 | // INTERNAL IMPLEMENTATION 44 | /////////////////////////////////////////////////////////////////////////// 45 | 46 | /// # Summary 47 | /// Writes a single bit of data to the memory. 48 | /// # Input 49 | /// ## memoryRegister 50 | /// Register that represents the memory you are writing to. 51 | /// ## dataCell 52 | /// The tuple of (address, data) that you want written to the memory. 53 | operation BucketBrigadeWrite( 54 | memoryRegister : MemoryRegister, 55 | dataCell : MemoryCell 56 | ) 57 | : Unit { 58 | let (address, data) = (dataCell::Address, dataCell::Value); 59 | 60 | ResetAll((memoryRegister!)[address]); 61 | ApplyPauliFromBitString(PauliX, true, data, (memoryRegister!)[address]); 62 | } 63 | 64 | /// # Summary 65 | /// Reads out a value from a MemoryRegister to a target qubit given an address. 66 | /// # Input 67 | /// ## addressRegister 68 | /// The qubit register that represents the address to be queried. 69 | /// ## memoryRegister 70 | /// The qubit register that represents the memory you are reading from. 71 | /// ## targetRegister 72 | /// The register that will have the memory value transferred to. 73 | operation BucketBrigadeReadBit( 74 | addressRegister : AddressRegister, 75 | memoryRegister : MemoryRegister, 76 | targetRegister : Qubit[] 77 | ) 78 | : Unit is Adj + Ctl { 79 | use auxRegister = Qubit[2^Length(addressRegister!)]; 80 | within { 81 | X(Head(auxRegister)); 82 | ApplyAddressFanout(addressRegister, auxRegister); 83 | } 84 | apply { 85 | ReadoutMemoryBit(memoryRegister, auxRegister, targetRegister); 86 | } 87 | } 88 | 89 | 90 | /// # Summary 91 | /// Reads out a value from a MemoryRegister to a target qubit given an address. 92 | /// # Input 93 | /// ## addressRegister 94 | /// The qubit register that represents the address to be queried. 95 | /// ## memoryRegister 96 | /// The qubit register that represents the memory you are reading from. 97 | /// ## targetRegister 98 | /// The register that will have the memory value transferred to. 99 | operation BucketBrigadeReadPhase( 100 | addressRegister : AddressRegister, 101 | memoryRegister : MemoryRegister, 102 | targetRegister : Qubit[] 103 | ) 104 | : Unit is Adj + Ctl { 105 | use auxRegister = Qubit[2^Length(addressRegister!)]; 106 | within { 107 | X(Head(auxRegister)); 108 | ApplyAddressFanout(addressRegister, auxRegister); 109 | } 110 | apply { 111 | ReadoutMemoryPhase(memoryRegister, auxRegister, targetRegister); 112 | } 113 | } 114 | 115 | /// # Summary 116 | /// Takes a register with a binary representation of an address and 117 | /// converts it to a one-hot encoding in the aux register. 118 | /// # Input 119 | /// ## addressRegister 120 | /// Qubit register that uses binary encoding. 121 | /// ## auxRegister 122 | /// Qubit register that will have the same address as addressRegister, but 123 | /// as a one-hot encoding. 124 | operation ApplyAddressFanout( 125 | addressRegister : AddressRegister, 126 | auxRegister : Qubit[] 127 | ) 128 | : Unit is Adj + Ctl { 129 | for (idx, addressBit) in Enumerated(addressRegister!) { 130 | if idx == 0 { 131 | Controlled X([addressRegister![0]],auxRegister[1]); 132 | Controlled X([auxRegister[1]],auxRegister[0]); 133 | } 134 | else { 135 | for n in 0..(2^idx-1) { 136 | Controlled X([addressRegister![idx], auxRegister[n]],auxRegister[n+2^idx]); 137 | Controlled X([auxRegister[n+2^idx]],auxRegister[n]); 138 | } 139 | } 140 | } 141 | } 142 | 143 | /// # Summary 144 | /// Transfers the memory register values onto the target register. 145 | /// # Input 146 | /// ## memoryRegister 147 | /// The qubit register that represents the memory you are reading from. 148 | /// ## auxRegister 149 | /// Qubit register that will have the same address as addressRegister, but 150 | /// as a one-hot encoding. 151 | /// ## targetRegister 152 | /// The register that will have the memory value transferred to. 153 | operation ReadoutMemoryBit( 154 | memoryRegister : MemoryRegister, 155 | auxRegister : Qubit[], 156 | targetRegister : Qubit[] 157 | ) 158 | : Unit is Adj + Ctl { 159 | for (idx, aux) in Enumerated(auxRegister) { 160 | let valuePairs = Zipped((memoryRegister!)[idx], targetRegister); 161 | ApplyToEachCA(CCNOT(aux, _, _), valuePairs); 162 | } 163 | 164 | } 165 | 166 | /// # Summary 167 | /// Transfers the memory register values onto the target register. 168 | /// # Input 169 | /// ## memoryRegister 170 | /// The qubit register that represents the memory you are reading from. 171 | /// ## auxRegister 172 | /// Qubit register that will have the same address as addressRegister, but 173 | /// as a one-hot encoding. 174 | /// ## targetRegister 175 | /// The register that will have the memory value transferred to. 176 | operation ReadoutMemoryPhase( 177 | memoryRegister : MemoryRegister, 178 | auxRegister : Qubit[], 179 | targetRegister : Qubit[] 180 | ) 181 | : Unit is Adj + Ctl { 182 | within { 183 | ApplyToEachCA(X, targetRegister); 184 | ApplyToEachCA(H, targetRegister); 185 | } 186 | apply { 187 | ReadoutMemoryBit(memoryRegister, auxRegister, targetRegister); 188 | } 189 | 190 | } 191 | } -------------------------------------------------------------------------------- /src/Common.qs: -------------------------------------------------------------------------------- 1 | namespace QsharpCommunity.Qram{ 2 | open Microsoft.Quantum.Intrinsic; 3 | open Microsoft.Quantum.Canon; 4 | open Microsoft.Quantum.Logical; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Math; 7 | open Microsoft.Quantum.Arithmetic; 8 | open Microsoft.Quantum.Diagnostics; 9 | open Microsoft.Quantum.Convert; 10 | 11 | /// # Summary 12 | /// Type representing a generic QROM type. 13 | /// # Input 14 | /// ## Read 15 | /// The named operation that will look up data from the QROM. 16 | /// ## AddressSize 17 | /// The size (number of bits) needed to represent an address for the QROM. 18 | /// ## DataSize 19 | /// The size (number of bits) needed to represent a data value for the QROM. 20 | newtype QROM = ( 21 | Read : ((LittleEndian, Qubit[]) => Unit is Adj + Ctl), 22 | AddressSize : Int, 23 | DataSize : Int 24 | ); 25 | 26 | /// # Summary 27 | /// Type representing a generic QRAM type. 28 | /// # Named Items 29 | /// ## QueryPhase 30 | /// Takes an address, memory, and target qubit to perform the lookup. 31 | /// ## QueryBit 32 | /// Takes an address, memory, and target qubit to perform the lookup. 33 | /// ## Write 34 | /// Writes a data value at address Int, with the value Bool[] to a MemoryRegister. 35 | /// ## AddressSize 36 | /// The size (number of bits) needed to represent an address for the QRAM. 37 | /// ## DataSize 38 | /// The size (number of bits) needed to represent a data value for the QRAM. 39 | newtype QRAM = ( 40 | QueryPhase : ((AddressRegister, MemoryRegister, Qubit[]) => Unit is Adj + Ctl), 41 | QueryBit : ((AddressRegister, MemoryRegister, Qubit[]) => Unit is Adj + Ctl), 42 | Write : ((MemoryRegister, MemoryCell) => Unit), 43 | AddressSize : Int, 44 | DataSize : Int 45 | ); 46 | 47 | /// # Summary 48 | /// Wrapper for registers that represent a quantum memory. 49 | newtype MemoryRegister = (Qubit[][]); 50 | 51 | /// # Summary 52 | /// Takes a flat qubit register and groups the qubits by the number of addresses it represents 53 | /// # Input 54 | /// ## flatRegister 55 | /// 56 | /// ## numAddressBits 57 | /// 58 | /// # Output 59 | /// 60 | function PartitionMemoryRegister(flatRegister : Qubit[], memoryBank : MemoryBank) : MemoryRegister { 61 | return MemoryRegister( 62 | // Partitioned always returns the rest of the list as an additional array, 63 | // dropping it here as it should be empty. 64 | Most( 65 | Partitioned( 66 | ConstantArray(2^memoryBank::AddressSize, memoryBank::DataSize), 67 | flatRegister 68 | ) 69 | ) 70 | ); 71 | } 72 | 73 | /// # Summary 74 | /// Takes a tuple of nested arrays and returns the $idx^{th}$ item from 75 | /// each array. 76 | /// 77 | /// # Input 78 | /// ## dataArrayArray 79 | /// Array of arrays that you want to take the $idx^{th}$ item from. 80 | /// 81 | /// # Output 82 | /// An array of the $idx^{th}$ item from each nested array in dataArrayArray. 83 | function ElementsAt<'T>(dataArrayArray : 'T[][], idx : Int) : 'T[] { 84 | return Mapped(ElementAt<'T>(_, idx), dataArrayArray); 85 | } 86 | 87 | /// # Summary 88 | /// Returns the $n^{th}$ item of an array. Basically a workaround for not 89 | /// having lambdas yet in Q#. 90 | /// # Input 91 | /// ## array 92 | /// An array of type `'T` 93 | /// # Output 94 | /// The $idx^{th}$ item from `array`. 95 | function ElementAt<'T>(array : 'T[], idx : Int) : 'T { 96 | return array[idx]; 97 | } 98 | 99 | /// # Summary 100 | /// Wrapper for registers that represent addresses. 101 | newtype AddressRegister = (Qubit[]); 102 | 103 | /// # Summary 104 | /// Describes a single data point in a memory. 105 | /// # Input 106 | /// ## Address 107 | /// The address in the memory that the MemoryCell describes. 108 | /// ## Value 109 | /// The value in the memory that the MemoryCell describes. 110 | newtype MemoryCell = (Address : Int, Value : Bool[]); 111 | 112 | /// # Summary 113 | /// Describes a dataset as well as metadata about the data. 114 | /// # Input 115 | /// ## DataSet 116 | /// The data explicitly stored in the memory. 117 | /// ## AddressSize 118 | /// The number of bits required to represent the largest explicit address 119 | /// in the DataSet. 120 | /// ## DataSize 121 | /// The number of bits required to represent the largest data valueS 122 | /// in the DataSet. 123 | newtype MemoryBank = (DataSet : MemoryCell[], AddressSize : Int, DataSize : Int); 124 | 125 | /// # Summary 126 | /// Helper function that returns the address of a particular MemoryCell. 127 | /// Basically a lambda function for the unwrapping. 128 | /// # Input 129 | /// ## cell 130 | /// The memory cell you want to know about. 131 | /// # Output 132 | /// The address of that MemoryCell. 133 | function AddressLookup(cell : MemoryCell) : Int { 134 | return cell::Address; 135 | } 136 | 137 | /// # Summary 138 | /// Helper function that returns the Value of a particular MemoryCell. 139 | /// Basically a lambda function for the unwrapping. 140 | /// # Input 141 | /// ## cell 142 | /// The memory cell you want to know about. 143 | /// # Output 144 | /// The Value of that MemoryCell. 145 | function ValueLookup(cell : MemoryCell) : Bool[] { 146 | return cell::Value; 147 | } 148 | 149 | /// # Summary 150 | /// Easy way to get all of the addresses specified in a MemoryBank. 151 | /// # Input 152 | /// ## bank 153 | /// The MemoryBank you want to know about. 154 | /// # Output 155 | /// A list of addresses given by each MemoryCell in the DataSet. 156 | function AddressList(bank : MemoryBank) : Int[] { 157 | return Mapped(AddressLookup, bank::DataSet); 158 | } 159 | 160 | /// # Summary 161 | /// Easy way to get all of the values specified in a MemoryBank. 162 | /// # Input 163 | /// ## bank 164 | /// The MemoryBank you want to know about. 165 | /// # Output 166 | /// A list of values given by each MemoryCell in the DataSet. 167 | function DataList(bank : MemoryBank) : Bool[][] { 168 | return Mapped(ValueLookup, bank::DataSet); 169 | } 170 | 171 | /// # Summary 172 | /// Given a MemoryBank, it looks up the Value stored at queryAddress. 173 | /// If the address is not explicitly in the DataSet, the returned value is 174 | /// 0. 175 | /// # Input 176 | /// ## bank 177 | /// The MemoryBank you want to know about. 178 | /// ## queryAddress 179 | /// The address you want to learn the value for. 180 | /// # Output 181 | /// The Value as a Bool[] at the queryAddress in the MemoryBank. 182 | function DataAtAddress( 183 | bank : MemoryBank, 184 | queryAddress : Int 185 | ) 186 | : Bool[] { 187 | let addressFound = IndexOf(EqualI(_, queryAddress), AddressList(bank)); 188 | 189 | if (not EqualI(addressFound, -1)){ 190 | // Look up the actual data value at the correct address index 191 | return ValueLookup((LookupFunction(bank::DataSet))(addressFound)); 192 | } 193 | // The address you are looking for may not have been explicitly given, 194 | // we assume that the data value there is 0. 195 | else { 196 | return ConstantArray(bank::DataSize, false); 197 | } 198 | } 199 | 200 | /// # Summary 201 | /// Takes a DataSet, generates the necessary metadata and wraps it as a 202 | /// MemoryBank. 203 | /// # Input 204 | /// ## dataSet 205 | /// The list of MemoryCells that makes up the data for the bank. 206 | /// # Output 207 | /// The wrapped MemoryBank. 208 | function GeneratedMemoryBank(dataSet : MemoryCell[]) : MemoryBank { 209 | let largestAddress = Max(Mapped(AddressLookup, dataSet)); 210 | mutable valueSize = 0; 211 | 212 | // Determine largest size of stored value to set output qubit register size 213 | for cell in dataSet { 214 | if Length(cell::Value) > valueSize { 215 | set valueSize = Length(cell::Value); 216 | } 217 | } 218 | return Default() 219 | w/ DataSet <- dataSet 220 | w/ AddressSize <- BitSizeI(largestAddress) 221 | w/ DataSize <- valueSize; 222 | } 223 | 224 | 225 | operation ApplyCNOTCascade(controls : Qubit[], targets : Qubit[]) : Unit is Adj + Ctl 226 | { 227 | for control in controls { 228 | ApplyToEachCA(CNOT(control, _), targets); 229 | } 230 | } 231 | 232 | operation ApplyMultiTargetCNOT(control : Qubit, targets : Qubit[]) : Unit is Adj + Ctl 233 | { 234 | ApplyToEachCA(CNOT(control, _), targets); 235 | } 236 | 237 | 238 | /// # Summary 239 | /// Swap qubits at the level of registers 240 | /// # Input 241 | /// ## registerA 242 | /// The first register to swap. 243 | /// ## registerB 244 | /// The second register to swap. 245 | operation SwapFullRegisters(registerA : Qubit[], registerB : Qubit[]) 246 | : Unit is Adj + Ctl { 247 | EqualityFactB(Length(registerA) == Length(registerB), true, "Cannot SWAP registers of unequal size."); 248 | 249 | // TODO: find a way to do this in one line with ApplyToEach 250 | for qubitIndex in RangeAsIntArray(0..Length(registerA)-1) { 251 | SWAP(registerA[qubitIndex], registerB[qubitIndex]); 252 | } 253 | } 254 | 255 | } -------------------------------------------------------------------------------- /src/Qrom.qs: -------------------------------------------------------------------------------- 1 | namespace QsharpCommunity.Qram{ 2 | 3 | open Microsoft.Quantum.Math; 4 | open Microsoft.Quantum.Convert; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Arithmetic; 9 | 10 | /////////////////////////////////////////////////////////////////////////// 11 | // PUBLIC API 12 | /////////////////////////////////////////////////////////////////////////// 13 | 14 | /// # Summary 15 | /// Creates an instance of an implicit QROM given the data it needs to store. 16 | /// # Input 17 | /// ## dataValues 18 | /// An array of memory cells where the address is an Int and the 19 | /// data is a boolean array representing the user data. 20 | /// # Output 21 | /// A `QROM` type. 22 | function QromOracle(dataValues : MemoryCell[]) : QROM { 23 | let bank = GeneratedMemoryBank(dataValues); 24 | let qroms = BoundCA(Mapped(SingleValueWriter, dataValues)); 25 | 26 | return Default() 27 | w/ Read <- qroms 28 | w/ AddressSize <- bank::AddressSize 29 | w/ DataSize <- bank::DataSize; 30 | } 31 | 32 | /////////////////////////////////////////////////////////////////////////// 33 | // INTERNAL IMPLEMENTATION 34 | /////////////////////////////////////////////////////////////////////////// 35 | 36 | /// # Summary 37 | /// Returns an operation that represents a QROM with one non-zero data value. 38 | /// # Input 39 | /// ## cell 40 | /// A memory cell which contains the data value and the address to write. 41 | /// # Output 42 | /// An operation that can be used to look up data `value` at `address`. 43 | internal function SingleValueWriter(cell : MemoryCell) 44 | : ((LittleEndian, Qubit[]) => Unit is Adj + Ctl) { 45 | return WriteSingleValue(cell::Address, cell::Value, _, _); 46 | } 47 | 48 | /// # Summary 49 | /// Constructs an operation that will when given a specific address, 50 | /// apply a value to a target register. 51 | /// # Input 52 | /// ## address 53 | /// The address where the data is non-zero. 54 | /// ## value 55 | /// The value (as a Bool[]) representing the data at `address 56 | /// ## addressRegister 57 | /// The qubit register that represents the address you are querying. 58 | /// ## targetRegister 59 | /// The qubit register that will have the QROM value written to. 60 | internal operation WriteSingleValue( 61 | address : Int, 62 | value : Bool[], 63 | addressRegister : LittleEndian, 64 | targetRegister : Qubit[] 65 | ) 66 | : Unit is Adj + Ctl { 67 | (ControlledOnInt(address, ApplyPauliFromBitString(PauliX, true, value, _))) 68 | (addressRegister!, targetRegister); 69 | } 70 | } -------------------------------------------------------------------------------- /src/Select.qs: -------------------------------------------------------------------------------- 1 | namespace QsharpCommunity.Qram { 2 | open Microsoft.Quantum.Arithmetic; 3 | open Microsoft.Quantum.Arrays; 4 | open Microsoft.Quantum.Canon; 5 | open Microsoft.Quantum.Convert; 6 | open Microsoft.Quantum.Diagnostics; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Math; 9 | 10 | /////////////////////////////////////////////////////////////////////////// 11 | // PUBLIC API 12 | /////////////////////////////////////////////////////////////////////////// 13 | 14 | /// # Summary 15 | /// Creates an instance of a QROM based on unary iteration given the data it needs to store. 16 | /// Source: https://arxiv.org/abs/1805.03662. 17 | /// # Input 18 | /// ## dataValues 19 | /// An array of memory cells where the address is an Int and the 20 | /// data is a boolean array representing the user data. 21 | /// # Output 22 | /// A `QROM` type. 23 | function SelectQromOracle(dataValues : MemoryCell[]) : QROM { 24 | let memoryBank = GeneratedMemoryBank(dataValues); 25 | let largestAddress = Max(Mapped(AddressLookup, dataValues)); 26 | let data = MappedOverRange(DataAtAddress(memoryBank, _), 0..largestAddress); 27 | 28 | return Default() 29 | w/ Read <- ApplySelectNetwork(data, _, _) 30 | w/ AddressSize <- memoryBank::AddressSize 31 | w/ DataSize <- memoryBank::DataSize; 32 | } 33 | 34 | 35 | /////////////////////////////////////////////////////////////////////////// 36 | // INTERNAL IMPLEMENTATION 37 | /////////////////////////////////////////////////////////////////////////// 38 | 39 | /// # Summary 40 | /// Recursive implementation of QROM. 41 | /// 42 | /// # Description 43 | /// The controlled variant of this operation allows for a recursive 44 | /// decomposition into two parts that splits `data` into a lower part 45 | /// of length $2^{n-1}$ and an upper part of length $N-2^{n-1}$, where 46 | /// $N$ is the length of `data` and $n$ is the number of bits in the 47 | /// `address` register. 48 | /// 49 | /// The operation requires one additional helper qubit for each recursion 50 | /// level. 51 | /// 52 | /// # Input 53 | /// ## data 54 | /// The bit strings of the memory bank. 55 | /// ## address 56 | /// The address register. 57 | /// ## target 58 | /// The target register. 59 | internal operation ApplySelectNetwork(data : Bool[][], address : LittleEndian, target : Qubit[]) : Unit is Adj + Ctl { 60 | body (...) { 61 | let (N, n) = DimensionsForSelect(data, address); 62 | 63 | if N == 1 { // base case 64 | WriteMemoryContents(Head(data), target); 65 | } else { 66 | let (most, tail) = MostAndTail(address![...n - 1]); 67 | let parts = Partitioned([2^(n - 1)], data); 68 | 69 | within { 70 | X(tail); 71 | } apply { 72 | Controlled ApplySelectNetwork([tail], (parts[0], LittleEndian(most), target)); 73 | } 74 | 75 | Controlled ApplySelectNetwork([tail], (parts[1], LittleEndian(most), target)); 76 | } 77 | } 78 | adjoint auto; 79 | 80 | controlled (ctls, ...) { 81 | let (N, n) = DimensionsForSelect(data, address); 82 | 83 | Fact(Length(ctls) == 1, "table lookup can only be controlled with single control line"); 84 | let ctl = Head(ctls); 85 | 86 | if N == 1 { // base case 87 | Controlled WriteMemoryContents(ctls, (Head(data), target)); 88 | } else { 89 | use helper = Qubit(); 90 | 91 | let (most, tail) = MostAndTail(address![...n - 1]); 92 | let parts = Partitioned([2^(n - 1)], data); 93 | 94 | within { 95 | X(tail); 96 | } apply { 97 | ApplyAnd(ctl, tail, helper); 98 | } 99 | 100 | Controlled ApplySelectNetwork([helper], (parts[0], LittleEndian(most), target)); 101 | 102 | CNOT(ctl, helper); 103 | 104 | Controlled ApplySelectNetwork([helper], (parts[1], LittleEndian(most), target)); 105 | 106 | Adjoint ApplyAnd(ctl, tail, helper); 107 | } 108 | } 109 | controlled adjoint auto; 110 | } 111 | 112 | /// # Summary 113 | /// Validates and adjusts dimensions for address register 114 | /// 115 | /// # Description 116 | /// Given $N$ bit strings in `data` and an address register of length $n'$, 117 | /// this function first checks whether $N \neq 0$ and $\lceil\log_2 N\rceil = n \le n'$, 118 | /// and then returns the tuple $(N, n)$. 119 | /// 120 | /// # Input 121 | /// ## data 122 | /// The bit strings of the memory bank. 123 | /// ## address 124 | /// The address register. 125 | internal function DimensionsForSelect(data : Bool[][], address : LittleEndian) : (Int, Int) { 126 | let N = Length(data); 127 | Fact(N > 0, "data cannot be empty"); 128 | 129 | let n = Ceiling(Lg(IntAsDouble(N))); 130 | Fact(Length(address!) >= n, $"address register is too small, requires at least {n} qubits"); 131 | 132 | return (N, n); 133 | } 134 | 135 | /// # Summary 136 | /// Writes out memory contents of a single bit string 137 | /// 138 | /// # Input 139 | /// ## value 140 | /// Single bit string. 141 | /// ## target 142 | /// Target register. 143 | internal operation WriteMemoryContents(value : Bool[], target : Qubit[]) : Unit is Adj + Ctl { 144 | EqualityFactI(Length(value), Length(target), "number of data bits must equal number of target qubits"); 145 | 146 | ApplyPauliFromBitString(PauliX, true, value, target); 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /src/SelectSwapQrom.qs: -------------------------------------------------------------------------------- 1 | namespace QsharpCommunity.Qram{ 2 | 3 | open Microsoft.Quantum.Math; 4 | open Microsoft.Quantum.Convert; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Arithmetic; 9 | 10 | /////////////////////////////////////////////////////////////////////////// 11 | // PUBLIC API 12 | /////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | /// # Summary 16 | /// Creates an instance of a SelectSWAP QROM given the data it needs to store. 17 | /// Source: https://arxiv.org/abs/1812.00954. 18 | /// SelectSWAP qROMs consist of two parts: 19 | /// 1) a "select" part in which the memory contents are specified and written 20 | /// out to auxiliary registers 21 | /// 2) a "SWAP" part, where the memory contents at the queried address are 22 | /// transferred to the target register. 23 | /// A tradeoff can be made between the sizes of the two parts. 24 | /// # Input 25 | /// ## dataValues 26 | /// An array of memory cells where the address is an Int and the 27 | /// data is a boolean array representing the user data. 28 | /// ## tradeoffParameter 29 | /// An integer representing the number of address bits that will be "split off" 30 | /// to perform the mixed-polarity gates that detail the memory contents. This also 31 | /// affects the size of the auxiliary registers, making 2^(addressBits - tradeoffParameter). 32 | /// copies. Valid tradeoff parameters are integers from 1 to addressBits - 1. 33 | /// Example 1: 34 | /// A memory has 4 address bits. Rather than doing mixed-polarity gates with 4 controls, 35 | /// and holding a single copy of the target register, we can make a tradeoff. Setting 36 | /// tradeoffParameter = 1 will "splinter off" 1 address bit from the rest, and make 37 | /// 2^(4-1) = 8 copies of the auxiliary register. The select portion will be controlled on 38 | /// that first address bits, whereas the swap network is controlled on the remaining 3. 39 | /// Example 2: (as shown in the paper) 40 | /// Setting tradeoffParameter = 2 partitions the address space such 2^(4-2) = 4 copies 41 | /// of the auxiliary register are created. The select portion uses the first 2 address bits 42 | /// as controls, and the swap network uses the remaining 2. 43 | /// (Note: the original paper uses a different definition of the tradeoffParameter in which 44 | /// the number of auxiliary copies does not need to be a power of 2, however this complicates 45 | /// the implementation. Here we consider only the more straightforward case.) 46 | /// # Output 47 | /// A `QROM` type. 48 | function SelectSwapQromOracle(dataValues : MemoryCell[], tradeoffParameter : Int) : QROM { 49 | let memoryBank = GeneratedMemoryBank(dataValues); 50 | 51 | return Default() 52 | w/ Read <- selectSwap(memoryBank, tradeoffParameter, _, _) 53 | w/ AddressSize <- memoryBank::AddressSize 54 | w/ DataSize <- memoryBank::DataSize; 55 | // Add tradeoffFraction? 56 | } 57 | 58 | /////////////////////////////////////////////////////////////////////////// 59 | // INTERNAL IMPLEMENTATION 60 | /////////////////////////////////////////////////////////////////////////// 61 | 62 | /// # Summary 63 | /// Creates circuitry for SelectSWAP qROM in two parts. 64 | /// # Input 65 | /// ## memoryBank 66 | /// A MemoryBank contained the addresses and contents of the memory 67 | /// ## tradeoffParameter 68 | /// An integer representing the number of address bits that will be "split off" 69 | /// to perform the mixed-polarity gates that detail the memory contents. This also 70 | /// affects the size of the auxiliary registers, making 2^(addressBits - tradeoffParameter). 71 | /// copies. Valid tradeoff parameters are integers from 1 to addressBits - 1. 72 | /// Example 1: 73 | /// A memory has 4 address bits. Rather than doing mixed-polarity gates with 4 controls, 74 | /// and holding a single copy of the target register, we can make a tradeoff. Setting 75 | /// tradeoffParameter = 1 will "splinter off" 1 address bit from the rest, and make 76 | /// 2^(4-1) = 8 copies of the auxiliary register. The select portion will be controlled on 77 | /// that first address bits, whereas the swap network is controlled on the remaining 3. 78 | /// Example 2: (as shown in the paper) 79 | /// Setting tradeoffParameter = 2 partitions the address space such 2^(4-2) = 4 copies 80 | /// of the auxiliary register are created. The select portion uses the first 2 address bits 81 | /// as controls, and the swap network uses the remaining 2. 82 | /// (Note: the original paper uses a different definition of the tradeoffParameter in which 83 | /// the number of auxiliary copies does not need to be a power of 2, however this complicates 84 | /// the implementation. Here we consider only the more straightforward case.) 85 | /// ## addressRegister 86 | /// Memory address that we want to look up. 87 | /// ## targetRegister 88 | /// Where we want the data we look up to be transferer to. 89 | internal operation selectSwap( 90 | memoryBank : MemoryBank, 91 | tradeoffParameter : Int, 92 | addressRegister : LittleEndian, 93 | targetRegister : Qubit[] 94 | ) 95 | : Unit is Adj + Ctl { 96 | // A tradeoff parameter controls the relative size of an aux register 97 | let numAuxQubits = memoryBank::DataSize * 2^(memoryBank::AddressSize - tradeoffParameter); 98 | 99 | // Partition the auxiliary register into chunks of the right size; can't use 100 | // the PartitionMemoryBank operation because aux register size depends on the tradeoffParameter 101 | use auxRegister = Qubit[numAuxQubits]; 102 | let partitionedAuxRegister = Chunks(memoryBank::DataSize, auxRegister); 103 | let partitionedAddressRegister = Partitioned([tradeoffParameter], Reversed(addressRegister!)); 104 | 105 | within { 106 | // Perform the select operation that "writes" memory contents to the aux register 107 | // using the first tradeoffParameter address bits 108 | ApplySelect(partitionedAddressRegister[0], partitionedAuxRegister, memoryBank); 109 | // Apply the swap network controlled on the remaining address qubits 110 | ApplySwapNetwork(partitionedAddressRegister[1], partitionedAuxRegister); 111 | } 112 | apply { 113 | // Copy the memory contents from the topmost auxiliary register to a target register 114 | ApplyToEachCA(CNOT, Zipped(partitionedAuxRegister[0],targetRegister)); 115 | } 116 | } 117 | 118 | /// # Summary 119 | /// Applies the `Select` operation. This operation applies specific gates to 120 | /// a qubit register controlled on the different number state $\ket{j}$. 121 | /// 122 | /// $U = \sum^{N-1}_{j=0}\ket{j}\bra{j}\otimes V_j$. 123 | /// 124 | /// For the SelectSWAP qROMs, the $V_j$ operations are $X^{a_j}$ where $a_j$ is 125 | /// the bit string of memory contents stored in cell $j$. 126 | /// 127 | /// # Input 128 | /// ## addressSubRegister 129 | /// A qubit register holding the part of the address to be queried, as 130 | /// determined by the algorithm. 131 | /// ## auxRegister 132 | /// A qubit register on which the contents of the memory will be written to 133 | /// enable further processing. 134 | /// ## bank 135 | /// A `MemoryBank` that comprises a qROM. 136 | internal operation ApplySelect( 137 | addressSubRegister : Qubit[], 138 | auxRegister : Qubit[][], 139 | bank : MemoryBank 140 | ) 141 | : Unit is Adj + Ctl { 142 | for subAddress in 0..2^Length(addressSubRegister)-1 { 143 | ApplyControlledOnInt( 144 | subAddress, 145 | FanoutMemoryContents(bank, _, subAddress), 146 | Reversed(addressSubRegister), 147 | auxRegister 148 | ); 149 | } 150 | } 151 | 152 | /// # Summary 153 | /// Copy memory contents onto an auxiliary register in appropriately 154 | /// sized chunks, based on the SelectSWAP tradeoffParameter. 155 | /// # Input 156 | /// ## bank 157 | /// A memory bank with the contents of the qROM. 158 | /// ## auxRegister 159 | /// The auxiliary register of the qROM onto which the data will be "written". 160 | /// ## subAddress 161 | /// Indexes which chunk of memory to write to the `auxRegister`. This will be 162 | /// a contiguous subset of the memory, the size of which depends on the initial 163 | /// tradeoffParameter. 164 | /// Example: 165 | /// For a 4-bit address and tradeoffParameter = 2, we create an auxRegister with 166 | /// 4 chunks. For each subaddress controlled on the first two address bits, we write 167 | /// 4 consecutive memory cells to the auxRegister. For subAddress = 0, this is memory 168 | /// elements stored at cells 0-3, for subAddress = 1, this is cells 4-7, and so on. 169 | internal operation FanoutMemoryContents( 170 | bank : MemoryBank, 171 | auxRegister : Qubit[][], 172 | subAddress : Int 173 | ) 174 | : Unit is Adj + Ctl { 175 | let multiplexSize = Length(auxRegister); 176 | let addressSubspace = (Chunks(multiplexSize, RangeAsIntArray(0..2^bank::AddressSize-1)))[subAddress]; 177 | let dataSubspace = Mapped(DataAtAddress(bank, _), addressSubspace); 178 | 179 | for (value, aux) in Zipped(dataSubspace, auxRegister) { 180 | ApplyPauliFromBitString(PauliX, true, value, aux); 181 | } 182 | } 183 | 184 | 185 | /// # Summary 186 | /// SwapNetwork 187 | /// # Input 188 | /// ## addressSubregister 189 | /// A (sub)register of address bits that will be used to control a swap network. 190 | /// ## auxRegister 191 | /// A register of qubits, organized into memory chunks, that will be swapped. 192 | internal operation ApplySwapNetwork( 193 | addressSubregister : Qubit[], 194 | auxRegister : Qubit[][] 195 | ) 196 | : Unit is Adj + Ctl { 197 | // For convenience 198 | let numAddressBits = Length(addressSubregister); 199 | 200 | // Determine how many full registers we have to swap (should be 2^(Length(addressSubregister))) 201 | let auxCopies = Length(auxRegister); 202 | 203 | for (idx, addressBit) in Enumerated(Reversed(addressSubregister)) { 204 | let stride = 2^(idx); 205 | let registerPairs = Chunks(2, RangeAsIntArray(0..stride..auxCopies-1)); 206 | 207 | ApplyToEachCA(SwapRegistersByIndex(addressBit, auxRegister, _), registerPairs); 208 | } 209 | } 210 | 211 | /// # Summary 212 | /// Perform a controlled-SWAP on the full contents of two specified subregisters. 213 | /// # Input 214 | /// ## control 215 | /// A qubit from which a controlled-SWAP will be performed. 216 | /// ## auxRegister 217 | /// A register of qubits, organized into memory chunks, that will be swapped. 218 | /// ## swapIndices 219 | /// An array of 2 integers indexing the two subregisters of `auxRegister` that 220 | /// will be acted on by the controlled swap. 221 | internal operation SwapRegistersByIndex( 222 | control : Qubit, 223 | auxRegister : Qubit[][], 224 | swapIndices : Int[] 225 | ) 226 | : Unit is Adj + Ctl { 227 | Controlled SwapFullRegisters( 228 | [control], 229 | (auxRegister[swapIndices[0]], 230 | auxRegister[swapIndices[1]]) 231 | ); 232 | } 233 | } -------------------------------------------------------------------------------- /src/qram.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | 6 | 7 | 8 | 9 | QSharpCommunity.Libraries.Qram 10 | Library that implements a variety of quantum RAM proposals in Q#. 11 | 2020 QSharpCommunity 12 | MIT 13 | https://github.com/qsharp-community/qram.git 14 | git 15 | true 16 | ../docs/apidoc/ 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/BucketBrigadeBit.qs: -------------------------------------------------------------------------------- 1 | namespace Tests { 2 | 3 | open Microsoft.Quantum.Math; 4 | open Microsoft.Quantum.Convert; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Arithmetic; 9 | open Microsoft.Quantum.Diagnostics; 10 | open Microsoft.Quantum.Measurement; 11 | open Microsoft.Quantum.Logical; 12 | open QsharpCommunity.Qram; 13 | 14 | // NB: Much better extensible approach 15 | // AssertOperationEqualsReferenced(Memory that prepares bell state, BellState) 16 | 17 | // Verify empty qRAMs are empty 18 | @Test("QuantumSimulator") 19 | operation BucketBrigadeOracleBitEmptyMatchResults() : Unit { 20 | for addressSize in 1..3 { 21 | let expectedValue = ConstantArray(2^addressSize, [false]); 22 | let data = EmptyQRAM(addressSize); 23 | let result = CreateBitQueryMeasureAllQRAM(data); 24 | let pairs = Zipped(result, expectedValue); 25 | Ignore(Mapped( 26 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 27 | pairs 28 | )); 29 | } 30 | } 31 | 32 | // Verify full qRAMs are full 33 | @Test("QuantumSimulator") 34 | operation BucketBrigadeOracleBitFullMatchResults() : Unit { 35 | for addressSize in 1..3 { 36 | let expectedValue = ConstantArray(2^addressSize, [true]); 37 | let data = FullQRAM(addressSize); 38 | let result = CreateBitQueryMeasureAllQRAM(data); 39 | let pairs = Zipped(result, expectedValue); 40 | Ignore(Mapped( 41 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 42 | pairs 43 | )); 44 | } 45 | } 46 | 47 | // Verify things work when only the first cell is full 48 | @Test("QuantumSimulator") 49 | operation BucketBrigadeOracleBitFirstCellFullMatchResults() : Unit { 50 | for addressSize in 1..3 { 51 | let expectedValue = [[true]] + ConstantArray(2^addressSize-1, [false]); 52 | let data = FirstCellFullQRAM(); 53 | let result = CreateBitQueryMeasureAllQRAM(data); 54 | let pairs = Zipped(result, expectedValue); 55 | Ignore(Mapped( 56 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 57 | pairs 58 | )); 59 | } 60 | } 61 | 62 | // Verify things work when only the second cell is full 63 | @Test("QuantumSimulator") 64 | operation BucketBrigadeOracleBitSecondCellFullMatchResults() : Unit { 65 | for addressSize in 1..3 { 66 | let expectedValue = [[false], [true]] + ConstantArray(2^addressSize-2, [false]); 67 | let data = SecondCellFullQRAM(); 68 | let result = CreateBitQueryMeasureAllQRAM(data); 69 | let pairs = Zipped(result, expectedValue); 70 | Ignore(Mapped( 71 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 72 | pairs 73 | )); 74 | } 75 | } 76 | 77 | // Verify things work when only the last cell is full 78 | @Test("QuantumSimulator") 79 | operation BucketBrigadeOracleBitLastCellFullMatchResults() : Unit { 80 | for addressSize in 1..3 { 81 | let expectedValue = ConstantArray(2^addressSize-1, [false]) + [[true]]; 82 | let data = LastCellFullQRAM(addressSize); 83 | let result = CreateBitQueryMeasureAllQRAM(data); 84 | let pairs = Zipped(result, expectedValue); 85 | Ignore(Mapped( 86 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 87 | pairs 88 | )); 89 | } 90 | } 91 | 92 | // Operation that creates a qRAM, and returns the contents for 93 | // each address queried individually 94 | internal operation CreateBitQueryMeasureAllQRAM(bank : MemoryBank) : Bool[][] { 95 | mutable result = new Bool[][2^bank::AddressSize]; 96 | 97 | use (addressRegister, flatMemoryRegister, targetRegister) = 98 | (Qubit[bank::AddressSize], 99 | Qubit[bank::DataSize*(2^bank::AddressSize)], 100 | Qubit[bank::DataSize]); 101 | let memoryRegister = Most(Partitioned(ConstantArray(2^bank::AddressSize, bank::DataSize), flatMemoryRegister)); 102 | let memory = BucketBrigadeQRAMOracle(bank::DataSet, MemoryRegister(memoryRegister)); 103 | 104 | // Query each address sequentially and store in results array 105 | for queryAddress in 0..2^bank::AddressSize-1 { 106 | // Prepare the address register for the lookup 107 | PrepareIntAddressRegister(queryAddress, addressRegister); 108 | // Read out the memory at that address 109 | memory::QueryBit(AddressRegister(addressRegister), MemoryRegister(memoryRegister), targetRegister); 110 | // Measure the target register and log the results 111 | set result w/= queryAddress <- ResultArrayAsBoolArray(MultiM(targetRegister)); 112 | ResetAll(addressRegister + targetRegister); 113 | } 114 | // Done with the memory register now 115 | ResetAll(flatMemoryRegister); 116 | return result; 117 | } 118 | 119 | } -------------------------------------------------------------------------------- /tests/BucketBrigadePhase.qs: -------------------------------------------------------------------------------- 1 | namespace Tests { 2 | 3 | open Microsoft.Quantum.Math; 4 | open Microsoft.Quantum.Convert; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Arithmetic; 9 | open Microsoft.Quantum.Diagnostics; 10 | open Microsoft.Quantum.Measurement; 11 | open Microsoft.Quantum.Logical; 12 | open QsharpCommunity.Qram; 13 | 14 | // Verify empty qRAMs are empty 15 | @Test("QuantumSimulator") 16 | operation BucketBrigadeOraclePhaseEmptyMatchResults() : Unit { 17 | for addressSize in 1..3 { 18 | let expectedValue = ConstantArray(2^addressSize, [false]); 19 | let data = EmptyQRAM(addressSize); 20 | let result = CreateBitQueryMeasureAllQRAM(data); 21 | let pairs = Zipped(result, expectedValue); 22 | Ignore(Mapped( 23 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 24 | pairs 25 | )); 26 | } 27 | } 28 | 29 | // Verify full qRAMs are full 30 | @Test("QuantumSimulator") 31 | operation BucketBrigadeOraclePhaseFullMatchResults() : Unit { 32 | for addressSize in 1..3 { 33 | let expectedValue = ConstantArray(2^addressSize, [true]); 34 | let data = FullQRAM(addressSize); 35 | let result = CreateBitQueryMeasureAllQRAM(data); 36 | let pairs = Zipped(result, expectedValue); 37 | Ignore(Mapped( 38 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 39 | pairs 40 | )); 41 | } 42 | } 43 | 44 | // Verify things work when only the first cell is full 45 | @Test("QuantumSimulator") 46 | operation BucketBrigadeOraclePhaseFirstCellFullMatchResults() : Unit { 47 | for addressSize in 1..3 { 48 | let expectedValue = [[true]] + ConstantArray(2^addressSize-1, [false]); 49 | let data = FirstCellFullQRAM(); 50 | let result = CreateBitQueryMeasureAllQRAM(data); 51 | let pairs = Zipped(result, expectedValue); 52 | Ignore(Mapped( 53 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 54 | pairs 55 | )); 56 | } 57 | } 58 | 59 | // Verify things work when only the second cell is full 60 | @Test("QuantumSimulator") 61 | operation BucketBrigadeOraclePhaseSecondCellFullMatchResults() : Unit { 62 | for addressSize in 1..3 { 63 | let expectedValue = [[false], [true]] + ConstantArray(2^addressSize-2, [false]); 64 | let data = SecondCellFullQRAM(); 65 | let result = CreateBitQueryMeasureAllQRAM(data); 66 | let pairs = Zipped(result, expectedValue); 67 | Ignore(Mapped( 68 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 69 | pairs 70 | )); 71 | } 72 | } 73 | 74 | // Verify things work when only the last cell is full 75 | @Test("QuantumSimulator") 76 | operation BucketBrigadeOraclePhaseLastCellFullMatchResults() : Unit { 77 | for addressSize in 1..3 { 78 | let expectedValue = ConstantArray(2^addressSize-1, [false]) + [[true]]; 79 | let data = LastCellFullQRAM(addressSize); 80 | let result = CreateBitQueryMeasureAllQRAM(data); 81 | let pairs = Zipped(result, expectedValue); 82 | Ignore(Mapped( 83 | AllEqualityFactB(_, _, $"Expecting memory contents {expectedValue}, got {result}."), 84 | pairs 85 | )); 86 | } 87 | } 88 | 89 | // Operation that creates a qRAM, and returns the contents for 90 | // each address queried individually 91 | internal operation CreatePhaseQueryMeasureAllQRAM(bank : MemoryBank) : Bool[][] { 92 | mutable result = new Bool[][2^bank::AddressSize]; 93 | 94 | use (addressRegister, flatMemoryRegister, targetRegister) = 95 | (Qubit[bank::AddressSize], 96 | Qubit[bank::DataSize*(2^bank::AddressSize)], 97 | Qubit[bank::DataSize]); 98 | let memoryRegister = Most(Partitioned(ConstantArray(2^bank::AddressSize, bank::DataSize), flatMemoryRegister)); 99 | let memory = BucketBrigadeQRAMOracle(bank::DataSet, MemoryRegister(memoryRegister)); 100 | 101 | // Query each address sequentially and store in results array 102 | for queryAddress in 0..2^bank::AddressSize-1 { 103 | // Prepare the address register for the lookup 104 | PrepareIntAddressRegister(queryAddress, addressRegister); 105 | // Read out the memory at that address 106 | memory::QueryPhase(AddressRegister(addressRegister), MemoryRegister(memoryRegister), targetRegister); 107 | // Measure the target register and log the results 108 | set result w/= queryAddress <- ResultArrayAsBoolArray(MultiM(targetRegister)); 109 | ResetAll(addressRegister + targetRegister); 110 | } 111 | // Done with the memory register now 112 | ResetAll(flatMemoryRegister); 113 | 114 | return result; 115 | } 116 | 117 | } -------------------------------------------------------------------------------- /tests/CommonTest.qs: -------------------------------------------------------------------------------- 1 | namespace Tests { 2 | 3 | open Microsoft.Quantum.Math; 4 | open Microsoft.Quantum.Convert; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Arithmetic; 9 | open Microsoft.Quantum.Diagnostics; 10 | open Microsoft.Quantum.Measurement; 11 | open Microsoft.Quantum.Logical; 12 | open Microsoft.Quantum.Random; 13 | open QsharpCommunity.Qram; 14 | 15 | // Hardcoded data set 16 | internal function SingleBitData() : MemoryBank { 17 | let data = [(5, [true]), (4, [true]), (1, [false]), (2, [false])]; 18 | return GeneratedMemoryBank(Mapped(MemoryCell, data)); 19 | } 20 | 21 | // Hardcoded data set for a multi-bit output situation 22 | internal function MultiBitData() : MemoryBank { 23 | let numDataBits = 3; 24 | let data = [ 25 | (5, IntAsBoolArray(3, numDataBits)), 26 | (4, IntAsBoolArray(2, numDataBits)), 27 | (0, IntAsBoolArray(0, numDataBits)), 28 | (2, IntAsBoolArray(5, numDataBits))]; 29 | return GeneratedMemoryBank(Mapped(MemoryCell, data)); 30 | } 31 | 32 | // TODO: parameterize data values as w 33 | // QRAM where every memory cell contains a 0 34 | internal function EmptyQRAM(addressSize : Int) : MemoryBank { 35 | let addresses = SequenceI(0, 2^addressSize - 1); 36 | let data = ConstantArray(2^addressSize, [false]); 37 | return GeneratedMemoryBank(Mapped(MemoryCell,Zipped(addresses, data))); 38 | } 39 | 40 | // QRAM where every memory cell contains a 1 41 | internal function FullQRAM(addressSize : Int) : MemoryBank { 42 | let addresses = SequenceI(0, 2^addressSize - 1); 43 | let data = ConstantArray(2^addressSize, [true]); 44 | return GeneratedMemoryBank(Mapped(MemoryCell,Zipped(addresses, data))); 45 | } 46 | 47 | // QRAM where only the first memory cell contains a 1 48 | internal function FirstCellFullQRAM() : MemoryBank { 49 | return GeneratedMemoryBank([MemoryCell(0, [true])]); 50 | } 51 | 52 | // QRAM where only the second memory cell contains a 1 53 | internal function SecondCellFullQRAM() : MemoryBank { 54 | return GeneratedMemoryBank([MemoryCell(1, [true])]); 55 | } 56 | 57 | // QRAM where only the last memory cell contains a 1 58 | internal function LastCellFullQRAM(addressSize : Int) : MemoryBank { 59 | return GeneratedMemoryBank([MemoryCell(2^addressSize - 1, [true])]); 60 | } 61 | 62 | internal operation PrepareIntAddressRegister(address : Int, register : Qubit[]) 63 | : Unit is Adj + Ctl { 64 | let queryAddressAsBoolArray = IntAsBoolArray(address, Length(register)); 65 | ApplyPauliFromBitString(PauliX, true, queryAddressAsBoolArray, register); 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /tests/QromTest.qs: -------------------------------------------------------------------------------- 1 | namespace Tests { 2 | 3 | open Microsoft.Quantum.Math; 4 | open Microsoft.Quantum.Convert; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Arithmetic; 9 | open Microsoft.Quantum.Diagnostics; 10 | open Microsoft.Quantum.Measurement; 11 | open Microsoft.Quantum.Logical; 12 | open QsharpCommunity.Qram; 13 | 14 | // Basic lookup with all addresses checked for single-bit data 15 | @Test("QuantumSimulator") 16 | operation QROMOracleSingleBitSingleLookupMatchResults() : Unit { 17 | let data = SingleBitData(); 18 | for i in 0..7 { 19 | CreateQueryMeasureOneAddressQROM(data, i); 20 | } 21 | } 22 | 23 | // Basic lookup with all addresses checked for multi-bit data 24 | @Test("QuantumSimulator") 25 | operation QROMOracleMultiBitSingleLookupMatchResults() : Unit { 26 | let data = MultiBitData(); 27 | for i in 0..7 { 28 | CreateQueryMeasureOneAddressQROM(data, i); 29 | } 30 | } 31 | 32 | internal operation CreateQueryMeasureOneAddressQROM( 33 | data : MemoryBank, 34 | queryAddress : Int 35 | ) 36 | : Unit { 37 | // Get the data value you expect to find at queryAddress 38 | let expectedValue = DataAtAddress(data, queryAddress); 39 | // Setup the var to hold the result of the measurement 40 | mutable result = new Bool[0]; 41 | 42 | // Create the new Qrom oracle 43 | let memory = QromOracle(data::DataSet); 44 | 45 | use (addressRegister, targetRegister) = 46 | (Qubit[memory::AddressSize], Qubit[memory::DataSize]); 47 | // Convert the address Int to a Bool[] 48 | let queryAddressAsBool = IntAsBoolArray(queryAddress, BitSizeI(queryAddress)); 49 | // Prepare the address register 50 | ApplyPauliFromBitString (PauliX, true, queryAddressAsBool, addressRegister); 51 | // Perform the lookup 52 | memory::Read(LittleEndian(addressRegister), targetRegister); 53 | // Get results and make sure its the same format as the data provided i.e. Bool[]. 54 | set result = ResultArrayAsBoolArray(MultiM(targetRegister)); 55 | // Reset all the qubits before returning them 56 | ResetAll(addressRegister+targetRegister); 57 | 58 | AllEqualityFactB(result, expectedValue, 59 | $"Expecting value {expectedValue} at address {queryAddress}, got {result}."); 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /tests/SelectSwapTest.qs: -------------------------------------------------------------------------------- 1 | namespace Tests { 2 | 3 | open Microsoft.Quantum.Math; 4 | open Microsoft.Quantum.Convert; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Arithmetic; 9 | open Microsoft.Quantum.Diagnostics; 10 | open Microsoft.Quantum.Measurement; 11 | open Microsoft.Quantum.Logical; 12 | open QsharpCommunity.Qram; 13 | 14 | 15 | // Basic lookup with all addresses checked, all valid tradeoff parameters tested 16 | // for single-bit data. 17 | @Test("QuantumSimulator") 18 | operation SelectSwapOracleSingleBitSingleLookupMatchResults() : Unit { 19 | let data = SingleBitData(); 20 | for i in 0..2^data::AddressSize-1 { 21 | for t in 1..data::AddressSize { 22 | CreateQueryMeasureOneAddressSelectSwap(data, i, t); 23 | } 24 | } 25 | } 26 | 27 | // Basic lookup with all addresses checked, all valid tradeoff parameters tested 28 | // for multi-bit data. 29 | @Test("QuantumSimulator") 30 | operation SelectSwapOracleMultiBitSingleLookupMatchResults() : Unit { 31 | let data = MultiBitData(); 32 | for i in 0..2^data::AddressSize-1 { 33 | for t in 1..data::AddressSize { 34 | CreateQueryMeasureOneAddressSelectSwap(data, i, t); 35 | } 36 | } 37 | } 38 | 39 | internal operation CreateQueryMeasureOneAddressSelectSwap( 40 | data : MemoryBank, 41 | queryAddress : Int, 42 | tradeoffParameter : Int 43 | ) 44 | : Unit { 45 | // Get the data value you expect to find at queryAddress 46 | let expectedValue = DataAtAddress(data, queryAddress); 47 | 48 | // Create the new Qrom oracle 49 | let memory = SelectSwapQromOracle(data::DataSet, tradeoffParameter); 50 | 51 | use (addressRegister, targetRegister) = 52 | (Qubit[memory::AddressSize], Qubit[memory::DataSize]); 53 | 54 | // Convert the address Int to a Bool[] 55 | let queryAddressAsBool = IntAsBoolArray(queryAddress, BitSizeI(queryAddress)); 56 | // Prepare the address register 57 | ApplyPauliFromBitString (PauliX, true, queryAddressAsBool, addressRegister); 58 | // Perform the lookup 59 | memory::Read(LittleEndian(addressRegister), targetRegister); 60 | // Get results and make sure its the same format as the data provided i.e. Bool[]. 61 | let result = ResultArrayAsBoolArray(MultiM(targetRegister)); 62 | // Reset all the qubits before returning them 63 | ResetAll(addressRegister+targetRegister); 64 | AllEqualityFactB(result, expectedValue, 65 | $"Expecting value {expectedValue} at address {queryAddress}, got {result}."); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /tests/SelectTest.qs: -------------------------------------------------------------------------------- 1 | namespace Tests { 2 | 3 | open Microsoft.Quantum.Math; 4 | open Microsoft.Quantum.Convert; 5 | open Microsoft.Quantum.Arrays; 6 | open Microsoft.Quantum.Canon; 7 | open Microsoft.Quantum.Intrinsic; 8 | open Microsoft.Quantum.Arithmetic; 9 | open Microsoft.Quantum.Diagnostics; 10 | open Microsoft.Quantum.Measurement; 11 | open Microsoft.Quantum.Logical; 12 | open QsharpCommunity.Qram; 13 | 14 | 15 | // Basic lookup with all addresses checked, all valid tradeoff parameters tested 16 | // for single-bit data. 17 | @Test("ToffoliSimulator") 18 | operation SelectOracleSingleBitSingleLookupMatchResults() : Unit { 19 | let data = SingleBitData(); 20 | let largestAddress = Max(Mapped(AddressLookup, data::DataSet)); 21 | for i in 0..largestAddress { 22 | for control in [true, false] { 23 | CreateQueryMeasureOneAddressSelect(data, i, control); 24 | } 25 | } 26 | } 27 | 28 | // Basic lookup with all addresses checked, all valid tradeoff parameters tested 29 | // for multi-bit data. 30 | @Test("ToffoliSimulator") 31 | operation SelectOracleMultiBitSingleLookupMatchResults() : Unit { 32 | let data = MultiBitData(); 33 | let largestAddress = Max(Mapped(AddressLookup, data::DataSet)); 34 | for i in 0..largestAddress { 35 | for control in [true, false] { 36 | CreateQueryMeasureOneAddressSelect(data, i, control); 37 | } 38 | } 39 | } 40 | 41 | internal operation CreateQueryMeasureOneAddressSelect( 42 | data : MemoryBank, 43 | queryAddress : Int, 44 | control : Bool 45 | ) 46 | : Unit { 47 | // Get the data value you expect to find at queryAddress 48 | let expectedValue = DataAtAddress(data, queryAddress); 49 | let emptyValue = ConstantArray(data::DataSize, false); 50 | 51 | // Create the new Qrom oracle 52 | let memory = SelectQromOracle(data::DataSet); 53 | 54 | use (addressRegister, targetRegister) = 55 | (Qubit[memory::AddressSize], Qubit[memory::DataSize]); 56 | 57 | if control { 58 | use ctl = Qubit(); 59 | 60 | for active in [true, false] { 61 | within { 62 | // Activate control qubit 63 | ApplyIfA(X, active, ctl); 64 | // Prepare the address register 65 | ApplyXorInPlace(queryAddress, LittleEndian(addressRegister)); 66 | } apply { 67 | // Perform the lookup 68 | Controlled memory::Read([ctl], (LittleEndian(addressRegister), targetRegister)); 69 | } 70 | 71 | // Get results and make sure its the same format as the data provided i.e. Bool[]. 72 | let result = ResultArrayAsBoolArray(ForEach(MResetZ, targetRegister)); 73 | AllEqualityFactB(result, active ? expectedValue | emptyValue, 74 | $"Expecting value {expectedValue} at address {queryAddress}, got {result}."); 75 | } 76 | } else { 77 | within { 78 | // Prepare the address register 79 | ApplyXorInPlace(queryAddress, LittleEndian(addressRegister)); 80 | } apply { 81 | // Perform the lookup 82 | memory::Read(LittleEndian(addressRegister), targetRegister); 83 | } 84 | 85 | // Get results and make sure its the same format as the data provided i.e. Bool[]. 86 | let result = ResultArrayAsBoolArray(ForEach(MResetZ, targetRegister)); 87 | AllEqualityFactB(result, expectedValue, 88 | $"Expecting value {expectedValue} at address {queryAddress}, got {result}."); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /tests/tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | --------------------------------------------------------------------------------