├── .all-contributorsrc ├── .devcontainer └── devcontainer.json ├── .gitattributes ├── .github └── workflows │ ├── publish.yml │ └── test.yml ├── .gitignore ├── CHP-Sim.sln ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── docs └── user-guide.md ├── environment-QuTiP.yml ├── environment-quaec.yml ├── sample ├── ChpSimMagic.ipynb ├── Program.qs ├── Sample.csproj └── qutip-scratchpad.ipynb ├── src ├── ChpSimulator.csproj ├── ChpSimulator.xml ├── DebugMessage.cs ├── Extensions.cs ├── QSharpCommunity.Simulators.Chp.nuspec ├── StabilizerProcessor.cs ├── StabilizerSimulator.cs ├── jupyter │ ├── ChpMagic.cs │ ├── StabilizerTableau.cs │ ├── TableauToHtmlEncoder.cs │ └── TableauToTextEncoder.cs └── stylecop.json └── test ├── AllocationTests.qs ├── CNotTests.qs ├── ChpSimulator.Test.csproj ├── ClassiclyControlledTest.qs ├── HadamardTests.qs ├── MeasurementTest.qs ├── PauliXTests.qs ├── PhaseTest.qs ├── States.qs └── ZTest.qs /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "RolfHuisman", 10 | "name": "Rolf Huisman", 11 | "avatar_url": "https://avatars.githubusercontent.com/u/39134931?v=4", 12 | "profile": "https://github.com/RolfHuisman", 13 | "contributions": [ 14 | "infra", 15 | "test", 16 | "code" 17 | ] 18 | } 19 | ], 20 | "contributorsPerLine": 7, 21 | "projectName": "chp-sim", 22 | "projectOwner": "qsharp-community", 23 | "repoType": "github", 24 | "repoHost": "https://github.com", 25 | "skipCi": true 26 | } 27 | -------------------------------------------------------------------------------- /.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 | "ms-dotnettools.csharp" 9 | ], 10 | "remoteEnv": { 11 | "IQSHARP_HOSTING_ENV": "CHP_DEVCONTAINER" 12 | } 13 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.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 24 | uses: actions/setup-dotnet@v3 25 | with: 26 | dotnet-version: '8.0.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 | name: Build and Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Setup .NET 17 | uses: actions/setup-dotnet@v3 18 | with: 19 | dotnet-version: '8.0.x' 20 | - name: Install dependencies 21 | run: dotnet restore 22 | - name: Build 23 | run: dotnet build --configuration Release --no-restore 24 | - name: Test 25 | run: dotnet test --no-restore --verbosity normal 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Python temporary files 2 | .ipynb_checkpoints 3 | .pytest_cache 4 | 5 | # Git ignore file for the Solid project 6 | 7 | # Build artifacts 8 | *.g.cs 9 | bin/ 10 | obj/ 11 | Documentation/Help/ 12 | packages/ 13 | *.obj 14 | *.dll 15 | *.pdb 16 | *.exe 17 | *.chm 18 | 19 | # test outputs 20 | TestResults/ 21 | *.qxe 22 | 23 | # Random VS files 24 | *.suo 25 | *.vssscc 26 | *.vspscc 27 | UpgradeLog.htm 28 | 29 | # Random non-solution files 30 | ~$Solid.docx 31 | 32 | ## Ignore Visual Studio temporary files, build results, and 33 | ## files generated by popular Visual Studio add-ons. 34 | ## 35 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 36 | 37 | # User-specific files 38 | *.suo 39 | *.user 40 | *.userosscache 41 | *.sln.docstates 42 | 43 | # User-specific files (MonoDevelop/Xamarin Studio) 44 | *.userprefs 45 | 46 | # Build results 47 | [Dd]ebug/ 48 | [Dd]ebugPublic/ 49 | [Rr]elease/ 50 | [Rr]eleases/ 51 | x64/ 52 | x86/ 53 | bld/ 54 | [Bb]in/ 55 | [Oo]bj/ 56 | [Ll]og/ 57 | 58 | # Visual Studio 2015 cache/options directory 59 | .vs/ 60 | # Uncomment if you have tasks that create the project's static files in wwwroot 61 | #wwwroot/ 62 | 63 | # MSTest test Results 64 | [Tt]est[Rr]esult*/ 65 | [Bb]uild[Ll]og.* 66 | 67 | # NUNIT 68 | *.VisualState.xml 69 | TestResult.xml 70 | 71 | # Build Results of an ATL Project 72 | [Dd]ebugPS/ 73 | [Rr]eleasePS/ 74 | dlldata.c 75 | 76 | # Benchmark Results 77 | BenchmarkDotNet.Artifacts/ 78 | 79 | # .NET Core 80 | project.lock.json 81 | project.fragment.lock.json 82 | artifacts/ 83 | **/Properties/launchSettings.json 84 | 85 | *_i.c 86 | *_p.c 87 | *_i.h 88 | *.ilk 89 | *.meta 90 | *.obj 91 | *.pch 92 | *.pdb 93 | *.pgc 94 | *.pgd 95 | *.rsp 96 | *.sbr 97 | *.tlb 98 | *.tli 99 | *.tlh 100 | *.tmp 101 | *.tmp_proj 102 | *.log 103 | *.vspscc 104 | *.vssscc 105 | .builds 106 | *.pidb 107 | *.svclog 108 | *.scc 109 | 110 | # Chutzpah Test files 111 | _Chutzpah* 112 | 113 | # Visual C++ cache files 114 | ipch/ 115 | *.aps 116 | *.ncb 117 | *.opendb 118 | *.opensdf 119 | *.sdf 120 | *.cachefile 121 | *.VC.db 122 | *.VC.VC.opendb 123 | 124 | # Visual Studio profiler 125 | *.psess 126 | *.vsp 127 | *.vspx 128 | *.sap 129 | 130 | # TFS 2012 Local Workspace 131 | $tf/ 132 | 133 | # Guidance Automation Toolkit 134 | *.gpState 135 | 136 | # ReSharper is a .NET coding add-in 137 | _ReSharper*/ 138 | *.[Rr]e[Ss]harper 139 | *.DotSettings.user 140 | 141 | # JustCode is a .NET coding add-in 142 | .JustCode 143 | 144 | # TeamCity is a build add-in 145 | _TeamCity* 146 | 147 | # DotCover is a Code Coverage Tool 148 | *.dotCover 149 | 150 | # AxoCover is a Code Coverage Tool 151 | .axoCover/* 152 | !.axoCover/settings.json 153 | 154 | # Visual Studio code coverage results 155 | *.coverage 156 | *.coveragexml 157 | 158 | # NCrunch 159 | _NCrunch_* 160 | .*crunch*.local.xml 161 | nCrunchTemp_* 162 | 163 | # MightyMoose 164 | *.mm.* 165 | AutoTest.Net/ 166 | 167 | # Web workbench (sass) 168 | .sass-cache/ 169 | 170 | # Installshield output folder 171 | [Ee]xpress/ 172 | 173 | # DocProject is a documentation generator add-in 174 | DocProject/buildhelp/ 175 | DocProject/Help/*.HxT 176 | DocProject/Help/*.HxC 177 | DocProject/Help/*.hhc 178 | DocProject/Help/*.hhk 179 | DocProject/Help/*.hhp 180 | DocProject/Help/Html2 181 | DocProject/Help/html 182 | 183 | # Click-Once directory 184 | publish/ 185 | 186 | # Publish Web Output 187 | *.[Pp]ublish.xml 188 | *.azurePubxml 189 | # Note: Comment the next line if you want to checkin your web deploy settings, 190 | # but database connection strings (with potential passwords) will be unencrypted 191 | *.pubxml 192 | *.publishproj 193 | 194 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 195 | # checkin your Azure Web App publish settings, but sensitive information contained 196 | # in these scripts will be unencrypted 197 | PublishScripts/ 198 | 199 | # NuGet Packages 200 | *.nupkg 201 | # The packages folder can be ignored because of Package Restore 202 | **/packages/* 203 | # except build/, which is used as an MSBuild target. 204 | !**/packages/build/ 205 | # Uncomment if necessary however generally it will be regenerated when needed 206 | #!**/packages/repositories.config 207 | # NuGet v3's project.json files produces more ignorable files 208 | *.nuget.props 209 | *.nuget.targets 210 | 211 | # Microsoft Azure Build Output 212 | csx/ 213 | *.build.csdef 214 | 215 | # Microsoft Azure Emulator 216 | ecf/ 217 | rcf/ 218 | 219 | # Windows Store app package directories and files 220 | AppPackages/ 221 | BundleArtifacts/ 222 | Package.StoreAssociation.xml 223 | _pkginfo.txt 224 | *.appx 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Since there are multiple workflows, uncomment next line to ignore bower_components 244 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 245 | #bower_components/ 246 | 247 | # RIA/Silverlight projects 248 | Generated_Code/ 249 | 250 | # Backup & report files from converting an old project file 251 | # to a newer Visual Studio version. Backup files are not needed, 252 | # because we have git ;-) 253 | _UpgradeReport_Files/ 254 | Backup*/ 255 | UpgradeLog*.XML 256 | UpgradeLog*.htm 257 | 258 | # SQL Server files 259 | *.mdf 260 | *.ldf 261 | *.ndf 262 | 263 | # Business Intelligence projects 264 | *.rdl.data 265 | *.bim.layout 266 | *.bim_*.settings 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Typescript v1 declaration files 279 | typings/ 280 | 281 | # Visual Studio 6 build log 282 | *.plg 283 | 284 | # Visual Studio 6 workspace options file 285 | *.opt 286 | 287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 288 | *.vbw 289 | 290 | # Visual Studio LightSwitch build output 291 | **/*.HTMLClient/GeneratedArtifacts 292 | **/*.DesktopClient/GeneratedArtifacts 293 | **/*.DesktopClient/ModelManifest.xml 294 | **/*.Server/GeneratedArtifacts 295 | **/*.Server/ModelManifest.xml 296 | _Pvt_Extensions 297 | 298 | # Paket dependency manager 299 | .paket/paket.exe 300 | paket-files/ 301 | 302 | # FAKE - F# Make 303 | .fake/ 304 | 305 | # JetBrains Rider 306 | .idea/ 307 | *.sln.iml 308 | 309 | # CodeRush 310 | .cr/ 311 | 312 | # Python Tools for Visual Studio (PTVS) 313 | __pycache__/ 314 | *.pyc 315 | 316 | # Cake - Uncomment if you are using it 317 | # tools/** 318 | # !tools/packages.config 319 | 320 | # Tabs Studio 321 | *.tss 322 | 323 | # Telerik's JustMock configuration file 324 | *.jmconfig 325 | 326 | # BizTalk build output 327 | *.btp.cs 328 | *.btm.cs 329 | *.odx.cs 330 | *.xsd.cs 331 | 332 | # Really random 333 | *.ionide 334 | 335 | ## Core latex/pdflatex auxiliary files: 336 | *.aux 337 | *.lof 338 | *.log 339 | *.lot 340 | *.fls 341 | *.out 342 | *.toc 343 | *.fmt 344 | *.fot 345 | *.cb 346 | *.cb2 347 | .*.lb 348 | 349 | ## Build tool auxiliary files: 350 | *.fdb_latexmk 351 | *.synctex 352 | *.synctex(busy) 353 | *.synctex.gz 354 | *.synctex.gz(busy) 355 | *.pdfsync 356 | 357 | ## Intermediate documents: 358 | *.dvi 359 | *.xdv 360 | *-converted-to.* 361 | # these rules might exclude image files for figures etc. 362 | # *.ps 363 | # *.eps 364 | # Allow PDFs in fig/. 365 | !fig/*.pdf 366 | 367 | ## Bibliography auxiliary files (bibtex/biblatex/biber): 368 | *.bbl 369 | *.bcf 370 | *.blg 371 | *-blx.aux 372 | *-blx.bib 373 | *.run.xml 374 | *Notes.bib 375 | 376 | ## Images 377 | *.png 378 | *.svg 379 | -------------------------------------------------------------------------------- /CHP-Sim.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30309.148 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChpSimulator", "src\ChpSimulator.csproj", "{F1CC2581-49ED-4491-AD84-2C37F5428355}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChpSimulator.Test", "test\ChpSimulator.Test.csproj", "{D6869FAA-528A-41EF-A7C8-ED053DF8931C}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{66F1F35E-1BD1-4E55-AE35-9CA204E81834}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{8D76E860-BEB1-4897-96B5-52936D18C88C}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sample", "sample\Sample.csproj", "{D35500B2-61A0-48CE-B706-1E6F96B74867}" 15 | EndProject 16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{93CCCBA5-53B5-4B20-BFAD-70C238113B57}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Debug|x64 = Debug|x64 22 | Release|Any CPU = Release|Any CPU 23 | Release|x64 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {F1CC2581-49ED-4491-AD84-2C37F5428355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {F1CC2581-49ED-4491-AD84-2C37F5428355}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {F1CC2581-49ED-4491-AD84-2C37F5428355}.Debug|x64.ActiveCfg = Debug|x64 29 | {F1CC2581-49ED-4491-AD84-2C37F5428355}.Debug|x64.Build.0 = Debug|x64 30 | {F1CC2581-49ED-4491-AD84-2C37F5428355}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {F1CC2581-49ED-4491-AD84-2C37F5428355}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {F1CC2581-49ED-4491-AD84-2C37F5428355}.Release|x64.ActiveCfg = Release|x64 33 | {F1CC2581-49ED-4491-AD84-2C37F5428355}.Release|x64.Build.0 = Release|x64 34 | {D6869FAA-528A-41EF-A7C8-ED053DF8931C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {D6869FAA-528A-41EF-A7C8-ED053DF8931C}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {D6869FAA-528A-41EF-A7C8-ED053DF8931C}.Debug|x64.ActiveCfg = Debug|x64 37 | {D6869FAA-528A-41EF-A7C8-ED053DF8931C}.Debug|x64.Build.0 = Debug|x64 38 | {D6869FAA-528A-41EF-A7C8-ED053DF8931C}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {D6869FAA-528A-41EF-A7C8-ED053DF8931C}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {D6869FAA-528A-41EF-A7C8-ED053DF8931C}.Release|x64.ActiveCfg = Release|x64 41 | {D6869FAA-528A-41EF-A7C8-ED053DF8931C}.Release|x64.Build.0 = Release|x64 42 | {D35500B2-61A0-48CE-B706-1E6F96B74867}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {D35500B2-61A0-48CE-B706-1E6F96B74867}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {D35500B2-61A0-48CE-B706-1E6F96B74867}.Debug|x64.ActiveCfg = Debug|x64 45 | {D35500B2-61A0-48CE-B706-1E6F96B74867}.Debug|x64.Build.0 = Debug|x64 46 | {D35500B2-61A0-48CE-B706-1E6F96B74867}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {D35500B2-61A0-48CE-B706-1E6F96B74867}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {D35500B2-61A0-48CE-B706-1E6F96B74867}.Release|x64.ActiveCfg = Release|x64 49 | {D35500B2-61A0-48CE-B706-1E6F96B74867}.Release|x64.Build.0 = Release|x64 50 | EndGlobalSection 51 | GlobalSection(SolutionProperties) = preSolution 52 | HideSolutionNode = FALSE 53 | EndGlobalSection 54 | GlobalSection(NestedProjects) = preSolution 55 | {F1CC2581-49ED-4491-AD84-2C37F5428355} = {66F1F35E-1BD1-4E55-AE35-9CA204E81834} 56 | {D6869FAA-528A-41EF-A7C8-ED053DF8931C} = {93CCCBA5-53B5-4B20-BFAD-70C238113B57} 57 | {D35500B2-61A0-48CE-B706-1E6F96B74867} = {8D76E860-BEB1-4897-96B5-52936D18C88C} 58 | EndGlobalSection 59 | GlobalSection(ExtensibilityGlobals) = postSolution 60 | SolutionGuid = {63FCAC84-8BE6-45BB-8064-B02E925C6EAB} 61 | EndGlobalSection 62 | EndGlobal 63 | -------------------------------------------------------------------------------- /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.16.2105140472 2 | 3 | ENV IQSHARP_HOSTING_ENV=CHP_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 "Chp" && \ 17 | dotnet pack ${HOME}/src/ChpSimulator.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 Sarah Kaiser 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CHP simulator for Q\# 2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-) 4 | 5 | 6 | This library implements a new classical simulator for Q# that utilizes the CHP stabilizer classical sub-theory. 7 | Based on the Python implementation by @Strilanc here: https://github.com/Strilanc/python-chp-stabilizer-simulator. 8 | 9 | ## Motivation 10 | 11 | > **tl;dr** If we impose some constraints on quantum systems they can become way easier to simulate classically. 12 | > 13 | > This simulator uses one such set of constraints to simulate thousands of qubits easily which allows us to learn more about quantum algorithms we don't yet have the hardware to run or simulate in full generality. 14 | 15 | Simulating quantum systems on a classical computer is hard to do in full generalization, as the resources needed scale exponentially with the number of qubits you want to simulate (up to about ~30 qubits on a typical machine). 16 | If you impose some constraints on the operations you can do in your programs, you can use a different kind of simulator that allows you to simulate hundreds of qubits by using what is called a _classical sub-theory_ of quantum physics. 17 | There are a variety of sub-theories that each have a different set of constraints you have to work with to leverage it. 18 | This repo implements a simulator for the CHP (CNOT, Hadamard, and Phase) classical sub-theory which helpfully has the constraint baked into the name. 19 | In this simulator, all operations it supports have to be comprised of (or decomposable to) only the operations CNOT, Hadamard, and Phase. 20 | If you run a program with this simulator as the target, and you ask for an operation that is not supported, the simulator will throw and exception. 21 | 22 | ## Build status 23 | 24 | ![Build](https://github.com/qsharp-community/chp-sim/workflows/Build/badge.svg) 25 | [![NuGet](https://img.shields.io/nuget/v/QSharpCommunity.Simulators.Chp)](https://www.nuget.org/packages/QSharpCommunity.Simulators.Chp/) 26 | [![QSharpCommunity.Simulators.Chp on fuget.org](https://www.fuget.org/packages/QSharpCommunity.Simulators.Chp/badge.svg)](https://www.fuget.org/packages/QSharpCommunity.Simulators.Chp) 27 | 28 | ## Code style 29 | 30 | [![q# code style](https://img.shields.io/badge/code%20style-Q%23-blue)](https://docs.microsoft.com/en-us/quantum/contributing/style-guide?tabs=guidance) 31 | [![q# APIcode style](https://img.shields.io/badge/code%20style-Q%23%20API-ff69b4)](https://docs.microsoft.com/en-us/quantum/contributing/style-guide?tabs=guidance) 32 | [![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) 33 | [![CoC](https://img.shields.io/badge/code%20of%20conduct-contributor%20covenant-yellow)](CODE_OF_CONDUCT.md) 34 | 35 | ## Screenshots 36 | 37 | ![Jupyter screenshot](/docs/media/jupyter-magic.png) 38 | 39 | ## Tech/framework used 40 | 41 | **Built with:** 42 | 43 | - [Quantum Development Kit](https://docs.microsoft.com/quantum/) 44 | - [.NET Core SDK 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) 45 | - [Python](https://www.python.org/downloads/) 46 | - [Visual Studio Code](https://code.visualstudio.com/) and [Visual Studio](https://visualstudio.microsoft.com/) 47 | - [Jupyter Notebook](https://jupyter.org/) 48 | 49 | ## Features 50 | 51 | Anywhere you can use Q#, you can use this simulator! 52 | 53 | - Python host program 54 | - Jupyter Notebooks 55 | - Stand-alone command line application 56 | - C#/F# host program 57 | 58 | ## Code Example 59 | 60 | TODO: Add more! Fix syntax highlighting 61 | 62 | 63 | ## Installation 64 | 65 | To use this simulator, there is no reqired installation (unless you want to develop the simulator locally). 66 | See the section below on how to use the simulator to see how to add it to your projects. 67 | 68 | More generally, 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/). 69 | 70 | 71 | ### Python installation the scratch pad notebooks (Python packages only, no Q#/Chp simulator) 72 | 73 | 1. Start with your favorite Anaconda or Miniconda install 74 | 2. Use the included `environment-qutip.yml` or `environment-quaec.yml` to create a conda envionment. 75 | ```bash 76 | $ conda env create -f 77 | ``` 78 | 3. Activate the environment and then start the Jupyter Notebook. The `` will be at the top of the yml file you used to create the environment. 79 | ```bash 80 | $ conda activate 81 | $ jupyter notebook 82 | ``` 83 | Then you should have Jupyter Notebook launch and you can use the corresponding notebook at the environment root for scratch work/testing your understanding of stabilizers. 84 | 85 | 86 | ## API Reference 87 | 88 | TODO: Complete once compiler extension is finalized for scraping API docs 89 | 90 | ## Tests 91 | 92 | The tests for this library all live in the `tests` directory. 93 | 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. 94 | If you are adding new features or functionality, make sure to add some tests to either the existing files, or make a new one. 95 | 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). 96 | 97 | ## How to use? 98 | 99 | ### You want to use a published version of the simulator: 100 | 101 | Just add a `PackageReference` to you project file with the following line: 102 | 103 | ```xml 104 | 105 | ``` 106 | or this console command: 107 | 108 | ```bash 109 | $ dotnet add package QSharpCommunity.Simulators.Chp -v X.X.X 110 | ``` 111 | 112 | In both cases you can omit the version information to use the latest available Chp simulator on https://NuGet.org. 113 | 114 | 115 | 116 | ### You want to develop the simulator (locally build and use simulator): 117 | 118 | The basic idea in this case is build locally a version of the nuget package for the simulator and then put it in a folder that is a known source to nuget. 119 | 120 | 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): 121 | 122 | ```Powershell 123 | > rm C:\Users\skais\nuget-packages\QSharpCommunity.Simulators.Chp.X.X.X.nupkg 124 | > rm C:\Users\skais\.nuget\packages\QSharpCommunity.Simulators.Chp\ 125 | ``` 126 | 127 | 1. Build the package for the Chp Simulator: 128 | 129 | ```Powershell 130 | > cd src 131 | > dotnet pack 132 | ``` 133 | 134 | 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). 135 | 136 | ```Powershell 137 | > cp .\bin\Debug\QSharpCommunity.Simulators.Chp.X.X.X.nupkg 'C:\Users\skais\nuget-packages\' 138 | ``` 139 | 140 | ## Contribute 141 | 142 | Please see our [contributing guidelines](CONTRIBUTING.md) and our [code of conduct](CODE_OF_CONDUCT.md) before working on a contribution, thanks! 143 | 144 | ## Credits 145 | 146 | - Primary developers: @crazy4pi314 @RolfHuisman 147 | - Contributors: @cgranade 148 | ### Notes 149 | 150 | If you need to check your intuition/understanding of the stabilizer formalism, you should check out these Python packages: 151 | - [Quaec](http://www.cgranade.com/python-quaec/) 152 | - [QuTiP](http://qutip.org/) 153 | 154 | ## License 155 | 156 | MIT © [Sarah Kaiser](https://github.com/qsharp-community/chp-sim/blob/master/LICENSE) 157 | 158 | ## Contributors ✨ 159 | 160 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 |

Rolf Huisman

🚇 ⚠️ 💻
170 | 171 | 172 | 173 | 174 | 175 | 176 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! -------------------------------------------------------------------------------- /docs/user-guide.md: -------------------------------------------------------------------------------- 1 | # User Guide for the Q# Stabilizer Simulator 2 | 3 | The StabilizerSimulator (also referred to as CHP based on the paper that proposes it) allows you to simulate your quantum programs using only the operations supported by the formalism. 4 | 5 | TODO: FINISH ME, look at https://docs.microsoft.com/en-us/quantum/user-guide/machines/resources-estimator 6 | -------------------------------------------------------------------------------- /environment-QuTiP.yml: -------------------------------------------------------------------------------- 1 | name: chp-qutip 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - notebook 6 | - numpy 7 | - scipy 8 | - qutip -------------------------------------------------------------------------------- /environment-quaec.yml: -------------------------------------------------------------------------------- 1 | name: chp-quaec 2 | channels: 3 | - defaults 4 | dependencies: 5 | - notebook 6 | - python=2.7 7 | - numpy 8 | - scipy 9 | - pip: 10 | - quaec 11 | -------------------------------------------------------------------------------- /sample/ChpSimMagic.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Sample use of the CHP Simulator in Q# Jupyter Notebook" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "### 1. Start by loading the package that contains the simulator" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "%package QSharpCommunity.Simulators.Chp" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "### 2. Ask for all the Jupyter magic commands to see that the `%chp` is loaded properly." 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "%lsmagic" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "### 3. Write or load the Q# code you want to use" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "Let's start by loading the Q# libraries we will need for our sample below:" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": null, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "open Microsoft.Quantum.Diagnostics;\n", 63 | "open Microsoft.Quantum.Arrays;" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "Set the number of qubits you want the simulator to use, and to not print small amplitudes. You can use a ton of qubits here (our default is 1024) but to make it easier to print and validate we will use 4 here 😁" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": null, 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "%config chp.nQubits = 4\n", 80 | "%config dump.truncateSmallAmplitudes = true" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "> TIP: You can always check to see what you have configured for options by just running `%config`:" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "%config" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "Now let's try and use the CHP simulator! We will start by defining an operation here that has two `DumpMachine` outputs so we can check what the simulator knows about our qubits. We also use `AsserMeasurement` as a way to test that the simulator returns the correct results." 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "operation RunChpDemo() : Unit {\n", 113 | " use register = Qubit[4];\n", 114 | " H(register[2]); //|+>\n", 115 | " DumpMachine();\n", 116 | " \n", 117 | " S(register[2]); //|i>\n", 118 | " S(register[2]); //|->\n", 119 | " H(register[2]); //|1>\n", 120 | " DumpMachine();\n", 121 | " \n", 122 | " AssertMeasurement([PauliZ],[register[0]], Zero, \"first qubit shouldn't have been flipped\");\n", 123 | " AssertMeasurement([PauliZ],[register[1]], Zero, \"second qubit shouldn't have been flipped\");\n", 124 | " AssertMeasurement([PauliZ],[register[2]], One, \"third qubit should have been flipped\");\n", 125 | " AssertMeasurement([PauliZ],[register[3]], Zero, \"fourth qubit shouldn't have been flipped\");\n", 126 | " \n", 127 | " Reset(register[2]);\n", 128 | "} " 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": null, 134 | "metadata": {}, 135 | "outputs": [], 136 | "source": [ 137 | "%chp RunChpDemo" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": null, 143 | "metadata": {}, 144 | "outputs": [], 145 | "source": [ 146 | "%simulate RunChpDemo" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "### If you want to display the simulator information as a Tableau/Matrix:" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": null, 159 | "metadata": {}, 160 | "outputs": [], 161 | "source": [ 162 | "%config chp.dumpFormat = \"matrix\"" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "metadata": {}, 169 | "outputs": [], 170 | "source": [ 171 | "%chp RunChpDemo" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "### If you want to turn on internal debug messages:" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "%config chp.debug = true" 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "execution_count": null, 193 | "metadata": {}, 194 | "outputs": [], 195 | "source": [ 196 | "%chp RunChpDemo" 197 | ] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "metadata": {}, 202 | "source": [ 203 | "#### Optional: If you want to save your simulator config run the following, for more info run `%config?`" 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "execution_count": null, 209 | "metadata": {}, 210 | "outputs": [], 211 | "source": [ 212 | "%config --save" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": null, 218 | "metadata": {}, 219 | "outputs": [], 220 | "source": [ 221 | "%version" 222 | ] 223 | } 224 | ], 225 | "metadata": { 226 | "kernelspec": { 227 | "display_name": "Q#", 228 | "language": "qsharp", 229 | "name": "iqsharp" 230 | }, 231 | "language_info": { 232 | "file_extension": ".qs", 233 | "mimetype": "text/x-qsharp", 234 | "name": "qsharp", 235 | "version": "0.14" 236 | } 237 | }, 238 | "nbformat": 4, 239 | "nbformat_minor": 4 240 | } 241 | -------------------------------------------------------------------------------- /sample/Program.qs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Sarah Kaiser. All rights reserved. 2 | // Licensed under the MIT License. 3 | 4 | namespace QSharpCommunity.Simulators.Chp.Sample { 5 | open Microsoft.Quantum.Canon; 6 | open Microsoft.Quantum.Intrinsic; 7 | open Microsoft.Quantum.Diagnostics; 8 | 9 | @EntryPoint() 10 | operation Test() : Unit { 11 | use q = Qubit(); 12 | DumpMachine(); 13 | let resultZero = M(q); 14 | EqualityFactR(resultZero, Zero, "X didn't return correct measurement."); 15 | X(q); 16 | DumpMachine(); 17 | let resultOne = M(q); 18 | EqualityFactR(resultOne, One, "X didn't return correct measurement."); 19 | DumpMachine(); 20 | if (M(q) == One) { X(q); } 21 | DumpMachine(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sample/Sample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | QSharpCommunity.Simulators.Chp.StabilizerSimulator 7 | AnyCPU;x64 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /sample/qutip-scratchpad.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Scratch pad for testing" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "Using packages like QuTiP, you can check your understanding of the actions of the CHP operations as well as Pauli products.\n", 15 | "> NOTE: Either run this in a Python env where you have installed QuTiP and NumPy or create the `conda` environment based on the `environment-qutip.yml`." 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 18, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "import qutip as qt\n", 25 | "import numpy as np" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 23, 31 | "metadata": {}, 32 | "outputs": [ 33 | { 34 | "name": "stderr", 35 | "output_type": "stream", 36 | "text": [ 37 | ":4: DeprecationWarning: Importing functions/classes of the qip submodule directly from the namespace qutip is deprecated. Please import them from the submodule instead, e.g.\n", 38 | "from qutip.qip.operations import cnot\n", 39 | "from qutip.qip.circuit import QubitCircuit\n", 40 | "\n", 41 | " H = qt.hadamard_transform()\n" 42 | ] 43 | } 44 | ], 45 | "source": [ 46 | "# CHP ops\n", 47 | "# S is the more cannonical name for P\n", 48 | "S = qt.qip.operations.phasegate(np.pi/2)\n", 49 | "H = qt.hadamard_transform()\n", 50 | "CNOT = qt.qip.operations.cnot()\n", 51 | "\n", 52 | "# Pauli operations\n", 53 | "X = qt.sigmax()\n", 54 | "Y = qt.sigmay()\n", 55 | "Z = qt.sigmaz()\n", 56 | "I = qt.qeye(1)" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 13, 62 | "metadata": {}, 63 | "outputs": [ 64 | { 65 | "data": { 66 | "text/latex": [ 67 | "Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & -1.0j\\\\1.0j & 0.0\\\\\\end{array}\\right)\\end{equation*}" 68 | ], 69 | "text/plain": [ 70 | "Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\n", 71 | "Qobj data =\n", 72 | "[[0.+0.j 0.-1.j]\n", 73 | " [0.+1.j 0.+0.j]]" 74 | ] 75 | }, 76 | "execution_count": 13, 77 | "metadata": {}, 78 | "output_type": "execute_result" 79 | } 80 | ], 81 | "source": [ 82 | "S * X * S.dag()" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": 14, 88 | "metadata": {}, 89 | "outputs": [ 90 | { 91 | "data": { 92 | "text/latex": [ 93 | "Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & -1.0j\\\\1.0j & 0.0\\\\\\end{array}\\right)\\end{equation*}" 94 | ], 95 | "text/plain": [ 96 | "Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\n", 97 | "Qobj data =\n", 98 | "[[0.+0.j 0.-1.j]\n", 99 | " [0.+1.j 0.+0.j]]" 100 | ] 101 | }, 102 | "execution_count": 14, 103 | "metadata": {}, 104 | "output_type": "execute_result" 105 | } 106 | ], 107 | "source": [ 108 | "Y" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 24, 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "data": { 118 | "text/latex": [ 119 | "Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.0 & 1.0\\\\1.0 & 0.0\\\\\\end{array}\\right)\\end{equation*}" 120 | ], 121 | "text/plain": [ 122 | "Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\n", 123 | "Qobj data =\n", 124 | "[[0. 1.]\n", 125 | " [1. 0.]]" 126 | ] 127 | }, 128 | "execution_count": 24, 129 | "metadata": {}, 130 | "output_type": "execute_result" 131 | } 132 | ], 133 | "source": [ 134 | "H * S * S * H" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": null, 140 | "metadata": {}, 141 | "outputs": [], 142 | "source": [] 143 | } 144 | ], 145 | "metadata": { 146 | "kernelspec": { 147 | "display_name": "Python 3.8.2 64-bit ('qsharp-book': conda)", 148 | "language": "python", 149 | "name": "python38264bitqsharpbookconda1b2b918f2bce4e578f9d1fbcf8270573" 150 | }, 151 | "language_info": { 152 | "codemirror_mode": { 153 | "name": "ipython", 154 | "version": 3 155 | }, 156 | "file_extension": ".py", 157 | "mimetype": "text/x-python", 158 | "name": "python", 159 | "nbconvert_exporter": "python", 160 | "pygments_lexer": "ipython3", 161 | "version": "3.8.2" 162 | } 163 | }, 164 | "nbformat": 4, 165 | "nbformat_minor": 4 166 | } 167 | -------------------------------------------------------------------------------- /src/ChpSimulator.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | AnyCPU;x64 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | QSharpCommunity.Simulators.Chp 24 | Quantum simulator for Q# that uses the CHP classical subtheory of quantum mechanics. 25 | https://qsharp.community/ 26 | Copyright (c) Sarah Kaiser. All rights reserved. Licensed under the MIT License. 27 | MIT 28 | 29 | https://github.com/qsharp-community/chp-sim.git 30 | git 31 | ChpSimulator.xml 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/ChpSimulator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ChpSimulator 5 | 6 | 7 | 8 | 9 | Message to show in debugging. 10 | 11 | 12 | 13 | 14 | Gets or sets the message to show for debugging. 15 | 16 | 17 | 18 | 19 | Extension methods for the simulators. 20 | 21 | 22 | 23 | 24 | Set the diagonal line of the matrix to the value. 25 | 26 | Matrix type. 27 | The matrix. 28 | The value to set it at. 29 | 30 | 31 | 32 | Swapped the columns. 33 | 34 | The matrix. 35 | Colum to swap with idx2. 36 | Colum to swap with idx1. 37 | 38 | 39 | 40 | Returns the row of the matrix. 41 | 42 | the matrix type. 43 | The matrix. 44 | The row that needs to be returned. 45 | The row highlighted by idxRow. 46 | 47 | 48 | 49 | Returns the column of the matrix. 50 | 51 | the matrix type. 52 | The matrix. 53 | The column that needs to be returned. 54 | The row highlighted by idxColumn. 55 | 56 | 57 | 58 | Represents the Row including the phase as a text string of Pauli operators. 59 | 60 | Row represented as a vector. 61 | Should the text be formatted for a LaTeX presentation 62 | Should the representation leave out identities? 63 | The rendered row including the phase to a text string of Pauli operators. 64 | 65 | 66 | 67 | Renders the row to a text string of Pauli operators. 68 | 69 | The matrix. 70 | Row index. 71 | Should the text be formatted for a LaTeX presentation 72 | Should the representation leave out identities? 73 | The rendered row including the phase to a text string of Pauli operators. 74 | 75 | 76 | 77 | Renders the row to a latex usable text string. 78 | 79 | The Matrix. 80 | Row index. 81 | A rendered string of the row. 82 | 83 | 84 | 85 | Renders the matrix to a text string of Pauli operators. 86 | 87 | The Matrix. 88 | Include the stabilizers in the string. 89 | A text string representation of the table as Pauli operators. 90 | 91 | 92 | 93 | Renders the group represented by the matrix to a latex string of Pauli operators. 94 | 95 | The matrix. 96 | A latex string representation of the table as Pauli operators. 97 | 98 | 99 | 100 | Renders the group represented by the matrix to a latex string of Pauli operators. 101 | 102 | The matrix. 103 | A latex string representation of the table as Pauli operators. 104 | 105 | 106 | 107 | Renders the matrix to a string representing a latex table. 108 | 109 | The matrix. 110 | Include the stabilizers in the string. 111 | A latex string representation of the matrix as latex table. 112 | 113 | 114 | 115 | Split the row into; stabilizers, destabilizers, and phase. 116 | 117 | Boolean representation of the row. 118 | 3-Element Tuple with seperated stabilizers, destabilizers, and phase. 119 | 120 | 121 | 122 | Calculate the product of the phase. 123 | 124 | Left vector. 125 | Right vector. 126 | PhaseProduct. 127 | 128 | 129 | 130 | Set the row sum for the Matrix. 131 | 132 | The Matrix. 133 | Index of vector to. 134 | Index of vector from. 135 | 136 | 137 | 138 | Set the row sum for the Matrix. 139 | 140 | The vector. 141 | The Matrix. 142 | Index of vector from. 143 | 144 | 145 | 146 | Search the matrix. 147 | 148 | Type of the matrix. 149 | Source list to check. 150 | Predicate to check. 151 | Indices of where predicate is true. 152 | 153 | 154 | 155 | Try to find the PauliZ that it can be measured on (if there isn't a measurement on X or Y.). 156 | 157 | The Pauli axis being measured on. 158 | The index of the PauliX. -1 otherwise. 159 | If it can be measured on a single PauliZ. 160 | 161 | 162 | 163 | Runs a given function or operation on the ChpSimulator target machine. 164 | 165 | 166 | 167 | 168 | Initializes a new instance of the class. 169 | Default constructor. 170 | 171 | Symbol resolver. 172 | Source for confirgarion settings. 173 | 174 | 175 | 176 | Gets the ISumbolResolver used to find the function/operation to simulate. 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | Simulates a function/operation using the ChpSimulator as target machine. 185 | It expects a single input: the name of the function/operation to simulate. 186 | 187 | current parameters for the function. 188 | channel connecting up with Jupyter. 189 | function result. 190 | 191 | 192 | 193 | Representation of the Tableau. 194 | 195 | 196 | 197 | 198 | Gets or sets the data to be shown in the Tableau format. 199 | 200 | 201 | 202 | 203 | Encodes the Tableau in HTML so it can be rendered by Jupyter. 204 | 205 | 206 | 207 | 208 | Initializes a new instance of the class. 209 | 210 | Settings to be used. 211 | 212 | 213 | 214 | Gets the mimetype used for rendering that its html. 215 | 216 | 217 | 218 | 219 | Returns the StabilizerTableau into the text as encoded data. 220 | 221 | Should be the StabilizerTableau. 222 | Text encoded table. 223 | 224 | 225 | 226 | Encodes the Tableau in text so it can be rendered by jupiter. 227 | 228 | 229 | 230 | 231 | Gets the mimetype used for rendering that its text. 232 | 233 | 234 | 235 | 236 | Returns the StabilizerTableau into the text as encoded data. 237 | 238 | Should be the StabilizerTableau. 239 | Text encoded table. 240 | 241 | 242 | 243 | CHP Simulator class. 244 | 245 | 246 | 247 | 248 | Current allocated qubit count. 249 | 250 | 251 | 252 | 253 | Initializes a new instance of the class. 254 | 255 | Amount of qubits to simulate. 256 | 257 | 258 | 259 | Gets or sets the simulator used in this run. 260 | 261 | 262 | 263 | 264 | Temporary check to give a more readable exception as long as there is no dynamic allocations. 265 | 266 | qubits to allocate. 267 | 268 | 269 | 270 | Temporary check to give a more readable exception as long as there is no dynamic allocations. 271 | 272 | qubits to allocate. 273 | count of qubits to reserve for borrowing. 274 | 275 | 276 | 277 | Temporary check to give a more readable exception as long as there is no dynamic allocations. 278 | 279 | qubits to deallocate. 280 | 281 | 282 | 283 | Temporary check to give a more readable exception as long as there is no dynamic allocations. 284 | 285 | qubits to deallocate. 286 | count of qubits being released. 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | CHP Simulator. 402 | 403 | 404 | 405 | 406 | Initializes a new instance of the class. 407 | 408 | Qubits to use for simulation. 409 | 410 | 411 | 412 | If diagnostic is enabled, show diagnostic information. 413 | 414 | Diagnostic displayable information. 415 | 416 | 417 | 418 | -------------------------------------------------------------------------------- /src/DebugMessage.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Sarah Kaiser. Licensed under the MIT License. 3 | // 4 | #nullable enable 5 | 6 | namespace QSharpCommunity.Simulators.Chp 7 | { 8 | /// 9 | /// Message to show in debugging. 10 | /// 11 | internal class DebugMessage 12 | { 13 | /// 14 | /// Gets or sets the message to show for debugging. 15 | /// 16 | public string? Message { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Extensions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Sarah Kaiser. Licensed under the MIT License. 3 | // 4 | 5 | // This C# project is based on a Python implementation by @Strilanc here: 6 | // https://github.com/Strilanc/python-chp-stabilizer-simulator 7 | namespace QSharpCommunity.Simulators.Chp 8 | { 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using Microsoft.Quantum.Simulation.Core; 13 | 14 | /// 15 | /// Extension methods for the simulators. 16 | /// 17 | internal static class Extensions 18 | { 19 | /// 20 | /// Set the diagonal line of the matrix to the value. 21 | /// 22 | /// Matrix type. 23 | /// The matrix. 24 | /// The value to set it at. 25 | internal static void SetDiagonal(this T[,] matrix, T value) 26 | { 27 | // TODO: better safety checking for the num rows 28 | foreach (var idxRow in Enumerable.Range(0, matrix.GetLength(0))) 29 | { 30 | matrix[idxRow, idxRow] = value; 31 | } 32 | } 33 | 34 | /// 35 | /// Swapped the columns. 36 | /// 37 | /// The matrix. 38 | /// Colum to swap with idx2. 39 | /// Colum to swap with idx1. 40 | internal static void SwapColumns(this bool[,] matrix, int idx1, int idx2) 41 | { 42 | foreach (var idxRow in Enumerable.Range(0, matrix.GetLength(0))) 43 | { 44 | matrix[idxRow, idx1] ^= matrix[idxRow, idx2]; 45 | matrix[idxRow, idx2] ^= matrix[idxRow, idx1]; 46 | matrix[idxRow, idx1] ^= matrix[idxRow, idx2]; 47 | } 48 | } 49 | 50 | /// 51 | /// Returns the row of the matrix. 52 | /// 53 | /// the matrix type. 54 | /// The matrix. 55 | /// The row that needs to be returned. 56 | /// The row highlighted by idxRow. 57 | internal static IEnumerable Row(this T[,] matrix, int idxRow) 58 | { 59 | foreach (var idxColumn in Enumerable.Range(0, matrix.GetLength(1))) 60 | { 61 | yield return matrix[idxRow, idxColumn]; 62 | } 63 | } 64 | 65 | /// 66 | /// Returns the column of the matrix. 67 | /// 68 | /// the matrix type. 69 | /// The matrix. 70 | /// The column that needs to be returned. 71 | /// The row highlighted by idxColumn. 72 | internal static IEnumerable Column(this T[,] matrix, int idxColumn) 73 | { 74 | foreach (var idxRow in Enumerable.Range(0, matrix.GetLength(0))) 75 | { 76 | yield return matrix[idxRow, idxColumn]; 77 | } 78 | } 79 | 80 | /// 81 | /// Represents the Row including the phase as a text string of Pauli operators. 82 | /// 83 | /// Row represented as a vector. 84 | /// Should the text be formatted for a LaTeX presentation 85 | /// Should the representation leave out identities? 86 | /// The rendered row including the phase to a text string of Pauli operators. 87 | internal static string RowToPauliString(this bool[] vector, bool asLatex = false, bool asSparse = false) 88 | { 89 | var (xs, zs, r) = vector.SplitRow(); 90 | if (asSparse) 91 | { 92 | var factors = Enumerable 93 | .Zip(xs, zs, (x, z) => (x, z)) 94 | .Select((e, i) => (e, i)) 95 | .Where(ei => ei.e.x || ei.e.z) 96 | .Select(ei => (ei.e.x, ei.e.z) switch 97 | { 98 | (false, false) => throw new Exception("Should never happen, but can't prove that."), 99 | (true, false) => asLatex ? $"X_{{{ei.i}}}" : $"X{ei.i}", 100 | (false, true) => asLatex ? $"Y_{{{ei.i}}}" : $"Y{ei.i}", 101 | (true, true) => asLatex ? $"Z_{{{ei.i}}}" : $"Z{ei.i}" 102 | }) 103 | .ToList(); 104 | return (r ? "-" : "+") + ( 105 | factors.Any() 106 | ? string.Join(string.Empty, factors) 107 | : asLatex ? "\\mathbb{1}" : "I" 108 | ); 109 | } 110 | else{ 111 | return (r ? "-" : "+") + string.Join( 112 | string.Empty, 113 | Enumerable.Zip(xs, zs, (x, z) => 114 | (x, z) switch 115 | { 116 | (false, false) => asLatex ? "\\mathbb{1}" :"I", 117 | (true, false) => "X", 118 | (false, true) => "Z", 119 | (true, true) => "Y", 120 | })); 121 | } 122 | 123 | } 124 | 125 | /// 126 | /// Renders the row to a text string of Pauli operators. 127 | /// 128 | /// The matrix. 129 | /// Row index. 130 | /// Should the text be formatted for a LaTeX presentation 131 | /// Should the representation leave out identities? 132 | /// The rendered row including the phase to a text string of Pauli operators. 133 | internal static string RowToPauliString(this bool[,] matrix, int idx, bool asLatex = false, bool asSparse = false) => matrix.Row(idx).ToArray().RowToPauliString(asLatex, asSparse); 134 | 135 | /// 136 | /// Renders the row to a latex usable text string. 137 | /// 138 | /// The Matrix. 139 | /// Row index. 140 | /// A rendered string of the row. 141 | internal static string RowToBinaryLatex(this bool[,] matrix, int idx) => 142 | string.Join(" & ", matrix.Row(idx).ToArray().Select(val => val ? 1 : 0)); 143 | 144 | /// 145 | /// Renders the matrix to a text string of Pauli operators. 146 | /// 147 | /// The Matrix. 148 | /// Include the stabilizers in the string. 149 | /// A text string representation of the table as Pauli operators. 150 | internal static string MatrixToPauliString(this bool[,] matrix, bool showDestabilizers = false) => 151 | "<" + string.Join(", ", Enumerable.Range(matrix.GetLength(0) / 2, matrix.GetLength(0) / 2).Select(idx => matrix.RowToPauliString(idx, false, false))) + ">" + 152 | (showDestabilizers ? 153 | "| >" + string.Join(", ", Enumerable.Range(0, matrix.GetLength(0) / 2).Select(idx => matrix.RowToPauliString(idx, false, false))) + "<" : 154 | ">"); 155 | 156 | /// 157 | /// Renders the group represented by the matrix to a latex string of Pauli operators. 158 | /// 159 | /// The matrix. 160 | /// A latex string representation of the table as Pauli operators. 161 | internal static string MatrixToPauliLatex(this bool[,] matrix) => 162 | "\\langle" + string.Join(", ", Enumerable.Range(matrix.GetLength(0) / 2, matrix.GetLength(0) / 2).Select(idx => matrix.RowToPauliString(idx, true, false))) + "\\rangle"; 163 | 164 | /// 165 | /// Renders the group represented by the matrix to a latex string of Pauli operators. 166 | /// 167 | /// The matrix. 168 | /// A latex string representation of the table as Pauli operators. 169 | internal static string MatrixToSparsePauliLatex(this bool[,] matrix) => 170 | "\\langle" + string.Join(", ", Enumerable.Range(matrix.GetLength(0) / 2, matrix.GetLength(0) / 2).Select(idx => matrix.RowToPauliString(idx, true, true))) + "\\rangle"; 171 | 172 | /// 173 | /// Renders the matrix to a string representing a latex table. 174 | /// 175 | /// The matrix. 176 | /// Include the stabilizers in the string. 177 | /// A latex string representation of the matrix as latex table. 178 | internal static string MatrixToBinaryLatexString(this bool[,] matrix, bool showDestabilizers = false) => 179 | ( 180 | showDestabilizers 181 | ? string.Join( 182 | @" \\", Enumerable.Range(0, matrix.GetLength(0) / 2).Select(idx => matrix.RowToBinaryLatex(idx))) + @" \\ \hline" 183 | : string.Empty) + 184 | string.Join(@" \\", Enumerable.Range(matrix.GetLength(0) / 2, matrix.GetLength(0) / 2).Select(idx => matrix.RowToBinaryLatex(idx))); 185 | 186 | /// 187 | /// Split the row into; stabilizers, destabilizers, and phase. 188 | /// 189 | /// Boolean representation of the row. 190 | /// 3-Element Tuple with seperated stabilizers, destabilizers, and phase. 191 | internal static (bool[] Stabilizers, bool[] DeStabilizers, bool Phase) SplitRow(this IEnumerable row) 192 | { 193 | var vector = row.ToArray(); 194 | var nQubits = (vector.Length - 1) / 2; 195 | return (vector[0..nQubits], vector[nQubits..^1], vector[^1]); 196 | } 197 | 198 | /// 199 | /// Calculate the product of the phase. 200 | /// 201 | /// Left vector. 202 | /// Right vector. 203 | /// PhaseProduct. 204 | internal static bool PhaseProduct(this IEnumerable row1, IEnumerable row2) 205 | { 206 | static int G(bool x1, bool z1, bool x2, bool z2) => 207 | (x1, z1) switch 208 | { 209 | (false, false) => 0, 210 | (true, true) => (z2 ? 1 : 0) - (x2 ? 1 : 0), 211 | (true, false) => (z2 ? 1 : 0) * ((2 * (x2 ? 1 : 0)) - 1), 212 | (false, true) => (x2 ? 1 : 0) * ((2 * (z2 ? 1 : 0)) - 1), 213 | }; 214 | 215 | var (xs1, zs1, r1) = row1.SplitRow(); 216 | var (xs2, zs2, r2) = row2.SplitRow(); 217 | var acc = 0; 218 | 219 | foreach (var idxColumn in Enumerable.Range(0, xs1.Length)) 220 | { 221 | acc += G(xs1[idxColumn], zs1[idxColumn], xs2[idxColumn], zs2[idxColumn]); 222 | } 223 | 224 | return ((r1 ? 2 : 0) + (r2 ? 2 : 0) + acc) % 4 == 2; 225 | } 226 | 227 | /// 228 | /// Set the row sum for the Matrix. 229 | /// 230 | /// The Matrix. 231 | /// Index of vector to. 232 | /// Index of vector from. 233 | internal static void SetToRowSum(this bool[,] matrix, int idxTarget, int idxSource) 234 | { 235 | foreach (var idxColumn in Enumerable.Range(0, matrix.GetLength(1) - 1)) 236 | { 237 | matrix[idxTarget, idxColumn] ^= matrix[idxSource, idxColumn]; 238 | } 239 | 240 | matrix[idxTarget, matrix.GetLength(1) - 1] = matrix.Row(idxTarget).PhaseProduct(matrix.Row(idxSource)); 241 | } 242 | 243 | /// 244 | /// Set the row sum for the Matrix. 245 | /// 246 | /// The vector. 247 | /// The Matrix. 248 | /// Index of vector from. 249 | internal static void SetToRowSum(this bool[] vector, bool[,] matrix, int idxSource) 250 | { 251 | foreach (var idxColumn in Enumerable.Range(0, matrix.GetLength(1) - 1)) 252 | { 253 | vector[idxColumn] ^= matrix[idxSource, idxColumn]; 254 | } 255 | 256 | vector[matrix.GetLength(1) - 1] = vector.PhaseProduct(matrix.Row(idxSource)); 257 | } 258 | 259 | /// 260 | /// Search the matrix. 261 | /// 262 | /// Type of the matrix. 263 | /// Source list to check. 264 | /// Predicate to check. 265 | /// Indices of where predicate is true. 266 | internal static IEnumerable IndicesWhere(this IEnumerable source, Func predicate) 267 | { 268 | foreach (var item in source.Select((element, idx) => (element, idx))) 269 | { 270 | if (predicate(item.element)) 271 | { 272 | yield return item.idx; 273 | } 274 | } 275 | } 276 | 277 | /// 278 | /// Try to find the PauliZ that it can be measured on (if there isn't a measurement on X or Y.). 279 | /// 280 | /// The Pauli axis being measured on. 281 | /// The index of the PauliX. -1 otherwise. 282 | /// If it can be measured on a single PauliZ. 283 | internal static bool TryGetSingleZ(this IEnumerable paulis, out int idx) 284 | { 285 | if (paulis.Any(basis => basis == Pauli.PauliX || basis == Pauli.PauliY)) 286 | { 287 | idx = -1; 288 | return false; 289 | } 290 | 291 | var idxs = paulis 292 | .Select((pauli, idx) => (pauli, idx)) 293 | .Where(item => item.pauli == Pauli.PauliZ) 294 | .Select(item => item.idx); 295 | 296 | if (idxs.Count() != 1) 297 | { 298 | idx = -1; 299 | return false; 300 | } 301 | else 302 | { 303 | idx = idxs.Single(); 304 | return true; 305 | } 306 | } 307 | } 308 | } -------------------------------------------------------------------------------- /src/QSharpCommunity.Simulators.Chp.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | QSharpCommunity.Simulators.Chp 5 | $version$ 6 | Q# Chp Simulator 7 | sckaiser 8 | sckaiser 9 | 10 | MIT 11 | https://qsharp.community/projects/ 12 | 13 | 14 | false 15 | Quantum simulator for Q# that uses the CHP classical subtheory of quantum mechanics. 16 | 17 | 18 | 19 | @ Sarah Kaiser. All rights reserved. 20 | Quantum Q# Qsharp 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/StabilizerProcessor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Sarah Kaiser. Licensed under the MIT License. 3 | // 4 | #nullable enable 5 | 6 | // This C# project is based on a Python implementation by @Strilanc here: 7 | // https://github.com/Strilanc/python-chp-stabilizer-simulator 8 | namespace QSharpCommunity.Simulators.Chp 9 | { 10 | using System; 11 | using System.Diagnostics.CodeAnalysis; 12 | using System.IO; 13 | using System.Linq; 14 | using System.Runtime.ExceptionServices; 15 | using Microsoft.Quantum.Simulation.Common; 16 | using Microsoft.Quantum.Simulation.Core; 17 | 18 | /// 19 | /// CHP Simulator class. 20 | /// 21 | public class StabilizerProcessor : QuantumProcessorBase 22 | { 23 | private readonly bool[,] table; 24 | private readonly int nQubits; 25 | 26 | /// 27 | /// Current allocated qubit count. 28 | /// 29 | private int allocated = 0; 30 | 31 | /// 32 | /// Initializes a new instance of the class. 33 | /// 34 | /// Amount of qubits to simulate. 35 | public StabilizerProcessor(int? nQubits = null) 36 | { 37 | this.nQubits = nQubits ?? 1024; 38 | 39 | // By default, this array is full of false 40 | this.table = new bool[2 * this.nQubits, (2 * this.nQubits) + 1]; 41 | this.table.SetDiagonal(true); 42 | } 43 | 44 | /// 45 | /// Gets or sets the simulator used in this run. 46 | /// 47 | internal StabilizerSimulator? Simulator { get; set; } 48 | 49 | private int RIndex => 2 * this.nQubits; 50 | 51 | ////////////////////////////////////////////////////////////////////// 52 | // Public 53 | ////////////////////////////////////////////////////////////////////// 54 | 55 | /// 56 | /// Temporary check to give a more readable exception as long as there is no dynamic allocations. 57 | /// 58 | /// qubits to allocate. 59 | public override void OnAllocateQubits(IQArray qubits) 60 | { 61 | this.Allocate(qubits); 62 | base.OnAllocateQubits(qubits); 63 | } 64 | 65 | /// 66 | /// Temporary check to give a more readable exception as long as there is no dynamic allocations. 67 | /// 68 | /// qubits to allocate. 69 | /// count of qubits to reserve for borrowing. 70 | public override void OnBorrowQubits(IQArray qubits, long allocatedForBorrowingCount) 71 | { 72 | this.Allocate(qubits); 73 | base.OnBorrowQubits(qubits, allocatedForBorrowingCount); 74 | } 75 | 76 | /// 77 | /// Temporary check to give a more readable exception as long as there is no dynamic allocations. 78 | /// 79 | /// qubits to deallocate. 80 | public override void OnReleaseQubits(IQArray qubits) 81 | { 82 | this.DeAllocate(qubits); 83 | base.OnReleaseQubits(qubits); 84 | } 85 | 86 | /// 87 | /// Temporary check to give a more readable exception as long as there is no dynamic allocations. 88 | /// 89 | /// qubits to deallocate. 90 | /// count of qubits being released. 91 | public override void OnReturnQubits(IQArray qubits, long releasedOnReturnCount) 92 | { 93 | this.DeAllocate(qubits); 94 | base.OnReturnQubits(qubits, releasedOnReturnCount); 95 | } 96 | 97 | /// 98 | public override void Reset(Qubit qubit) 99 | { 100 | if (this.M(qubit) == Result.One) 101 | { 102 | this.X(qubit); 103 | } 104 | } 105 | 106 | ////////////////////////////////////////////////////////////////////// 107 | // Overrides - Supported 108 | ////////////////////////////////////////////////////////////////////// 109 | 110 | /// 111 | public override void H(Qubit qubit) 112 | { 113 | this.Hadamard(qubit.Id); 114 | } 115 | 116 | /// 117 | public override void ControlledH(IQArray controls, Qubit qubit) 118 | { 119 | if (controls.Length == 0) 120 | { 121 | this.H(qubit); 122 | } 123 | else 124 | { 125 | throw new UnsupportedOperationException("Controlled H is not a Clifford operation."); 126 | } 127 | } 128 | 129 | /// 130 | public override void S(Qubit qubit) 131 | { 132 | this.Phase(qubit.Id); 133 | } 134 | 135 | /// 136 | public override void SAdjoint(Qubit qubit) 137 | { 138 | this.Phase(qubit.Id); 139 | this.Phase(qubit.Id); 140 | this.Phase(qubit.Id); 141 | } 142 | 143 | /// 144 | public override void OnDumpMachine(T location) 145 | { 146 | this.Simulator?.MaybeDisplayDiagnostic(new StabilizerTableau 147 | { 148 | Data = this.table, 149 | }); 150 | if (location is QVoid) 151 | { 152 | System.Console.WriteLine(this.table.MatrixToPauliString(true)); 153 | } 154 | else if (location is string filename) 155 | { 156 | File.WriteAllText(filename, this.table.MatrixToPauliString(true)); 157 | } 158 | else 159 | { 160 | throw new Exception("Not a valid file path."); 161 | } 162 | } 163 | 164 | /// 165 | public override void OnDumpRegister(T location, IQArray qubits) 166 | { 167 | this.OnMessage("Only DumpMachine is supported in this simulator."); 168 | } 169 | 170 | /// 171 | public override void X(Qubit qubit) 172 | { 173 | this.Hadamard(qubit.Id); 174 | this.Phase(qubit.Id); 175 | this.Phase(qubit.Id); 176 | this.Hadamard(qubit.Id); 177 | } 178 | 179 | /// 180 | public override void ControlledX(IQArray controls, Qubit qubit) 181 | { 182 | if (controls.Length == 1) 183 | { 184 | this.Cnot(controls.First().Id, qubit.Id); 185 | } 186 | else 187 | { 188 | throw new UnsupportedOperationException("Only singular controlled gates are allowed."); 189 | } 190 | } 191 | 192 | /// 193 | public override void Y(Qubit qubit) 194 | { 195 | this.SAdjoint(qubit); 196 | this.X(qubit); 197 | this.S(qubit); 198 | } 199 | 200 | /// 201 | public override void ControlledY(IQArray controls, Qubit qubit) 202 | { 203 | if (controls.Length == 1) 204 | { 205 | this.SAdjoint(qubit); 206 | this.ControlledX(controls, qubit); 207 | this.S(qubit); 208 | } 209 | else 210 | { 211 | throw new UnsupportedOperationException("Only singular controlled gates are allowed."); 212 | } 213 | } 214 | 215 | /// 216 | public override void Z(Qubit qubit) 217 | { 218 | this.Phase(qubit.Id); 219 | this.Phase(qubit.Id); 220 | } 221 | 222 | /// 223 | public override void ControlledZ(IQArray controls, Qubit qubit) 224 | { 225 | if (controls.Length == 1) 226 | { 227 | this.Hadamard(qubit.Id); 228 | this.Cnot(controls.First().Id, qubit.Id); 229 | this.Hadamard(qubit.Id); 230 | } 231 | else 232 | { 233 | throw new UnsupportedOperationException("Only singular controlled gates are allowed."); 234 | } 235 | } 236 | 237 | /// 238 | public override void SWAP(Qubit qubit1, Qubit qubit2) 239 | { 240 | this.Cnot(qubit1.Id, qubit2.Id); 241 | this.Cnot(qubit2.Id, qubit1.Id); 242 | this.Cnot(qubit1.Id, qubit2.Id); 243 | } 244 | 245 | /// 246 | public override void Assert(IQArray bases, IQArray qubits, Result result, string msg) => 247 | this.AssertProb(bases, qubits, result == Result.One ? 0 : 1, msg, 1e-10); 248 | 249 | /// 250 | public override void AssertProb(IQArray bases, IQArray qubits, double probabilityOfZero, string msg, double tol) 251 | { 252 | bool shouldBeDeterministic; 253 | Result? expectedResult; 254 | 255 | // Is the probability 0? 256 | if (Math.Abs(probabilityOfZero - 0) < tol) 257 | { 258 | shouldBeDeterministic = true; 259 | expectedResult = Result.One; 260 | } 261 | else if (Math.Abs(probabilityOfZero - 0.5) < tol) 262 | { 263 | shouldBeDeterministic = false; 264 | expectedResult = null; 265 | } 266 | else if (Math.Abs(probabilityOfZero - 1) < tol) 267 | { 268 | shouldBeDeterministic = true; 269 | expectedResult = Result.Zero; 270 | } 271 | else 272 | { 273 | throw new ExecutionFailException(msg); 274 | } 275 | 276 | this.Simulator?.MaybeDisplayDiagnostic( 277 | new DebugMessage 278 | { 279 | Message = $"shouldBeDeterministic = {shouldBeDeterministic}, expectedResult = {expectedResult}", 280 | }); 281 | 282 | if (!bases.TryGetSingleZ(out var idx)) 283 | { 284 | var aux = this.Simulator!.QubitManager?.Allocate(); 285 | if (aux == null) 286 | { 287 | throw new NullReferenceException("Qubit manager was null."); 288 | } 289 | 290 | try 291 | { 292 | this.WriteToScratch(bases, qubits, aux); 293 | this.AssertProb( 294 | new QArray(new[] { Pauli.PauliZ }), 295 | new QArray(new[] { aux }), 296 | probabilityOfZero, 297 | msg, 298 | tol); 299 | this.WriteToScratch( 300 | new QArray(bases.Reverse()), 301 | new QArray(qubits.Reverse()), 302 | aux); 303 | } 304 | finally 305 | { 306 | this.Simulator!.QubitManager?.Release(aux); 307 | } 308 | } 309 | else 310 | { 311 | var isDeterministic = this.IsMeasurementDetermined(qubits[idx].Id, out var result); 312 | if (isDeterministic == shouldBeDeterministic) 313 | { 314 | if (!isDeterministic || expectedResult == result) 315 | { 316 | return; 317 | } 318 | 319 | throw new ExecutionFailException(msg); 320 | } 321 | } 322 | } 323 | 324 | /// 325 | public override Result M(Qubit qubit) => this.MeasureByIndex(qubit.Id); 326 | 327 | /// 328 | public override Result Measure(IQArray bases, IQArray qubits) 329 | { 330 | if (!bases.TryGetSingleZ(out var idx)) 331 | { 332 | // throw new UnsupportedOperationException("Not yet implemented."); 333 | var aux = this.Simulator!.QubitManager?.Allocate(); 334 | if (aux == null) 335 | { 336 | throw new NullReferenceException("Qubit manager was null."); 337 | } 338 | 339 | try 340 | { 341 | this.WriteToScratch(bases, qubits, aux); 342 | return this.MeasureByIndex(aux.Id); 343 | } 344 | finally 345 | { 346 | this.Simulator!.QubitManager?.Release(aux); 347 | } 348 | } 349 | 350 | return this.MeasureByIndex(qubits[idx].Id); 351 | } 352 | 353 | ////////////////////////////////////////////////////////////////////// 354 | // Overrides - Unsupported 355 | ////////////////////////////////////////////////////////////////////// 356 | 357 | /// 358 | public override void ControlledExp(IQArray controls, IQArray paulis, double theta, IQArray qubits) => 359 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 360 | 361 | /// 362 | public override void ControlledExpFrac(IQArray controls, IQArray paulis, long numerator, long power, IQArray qubits) => 363 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 364 | 365 | /// 366 | public override void ControlledR(IQArray controls, Pauli axis, double theta, Qubit qubit) => 367 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 368 | 369 | /// 370 | public override void ControlledR1(IQArray controls, double theta, Qubit qubit) => 371 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 372 | 373 | /// 374 | public override void ControlledR1Frac(IQArray controls, long numerator, long power, Qubit qubit) => 375 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 376 | 377 | /// 378 | public override void ControlledRFrac(IQArray controls, Pauli axis, long numerator, long power, Qubit qubit) => 379 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 380 | 381 | /// 382 | public override void ControlledS(IQArray controls, Qubit qubit) => 383 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 384 | 385 | /// 386 | public override void ControlledSAdjoint(IQArray controls, Qubit qubit) => 387 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 388 | 389 | /// 390 | public override void ControlledSWAP(IQArray controls, Qubit qubit1, Qubit qubit2) => 391 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 392 | 393 | /// 394 | public override void ControlledT(IQArray controls, Qubit qubit) => 395 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 396 | 397 | /// 398 | public override void ControlledTAdjoint(IQArray controls, Qubit qubit) => 399 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 400 | 401 | /// 402 | public override void Exp(IQArray paulis, double theta, IQArray qubits) => 403 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 404 | 405 | /// 406 | public override void ExpFrac(IQArray paulis, long numerator, long power, IQArray qubits) => 407 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 408 | 409 | /// 410 | public override void R(Pauli axis, double theta, Qubit qubit) => 411 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 412 | 413 | /// 414 | public override void R1(double theta, Qubit qubit) => 415 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 416 | 417 | /// 418 | public override void R1Frac(long numerator, long power, Qubit qubit) => 419 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 420 | 421 | /// 422 | public override void RFrac(Pauli axis, long numerator, long power, Qubit qubit) => 423 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 424 | 425 | /// 426 | public override void T(Qubit qubit) => 427 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 428 | 429 | /// 430 | public override void TAdjoint(Qubit qubit) => 431 | throw new UnsupportedOperationException("This operation is not supported in the CHP Stabilizer formalism."); 432 | 433 | ////////////////////////////////////////////////////////////////////// 434 | // Internal 435 | ////////////////////////////////////////////////////////////////////// 436 | 437 | private int X(int idxCol) => idxCol; 438 | 439 | private int Z(int idxCol) => this.nQubits + idxCol; 440 | 441 | private void Hadamard(int target) 442 | { 443 | // This takes care of mapping X->Z and Z->X 444 | this.table.SwapColumns(this.X(target), this.Z(target)); 445 | 446 | // Now need to handle the phase, this represents the fact that HYH = -Y 447 | foreach (var idxRow in Enumerable.Range(0, this.table.GetLength(0))) 448 | { 449 | this.table[idxRow, this.RIndex] ^= this.table[idxRow, this.X(target)] && this.table[idxRow, this.Z(target)]; 450 | } 451 | } 452 | 453 | private void Phase(int target) 454 | { 455 | // Add global phase, this represents the fact that SYS^{+} = -Y 456 | foreach (var idxRow in Enumerable.Range(0, this.table.GetLength(0))) 457 | { 458 | this.table[idxRow, this.RIndex] ^= this.table[idxRow, this.X(target)] && this.table[idxRow, this.Z(target)]; 459 | } 460 | 461 | foreach (var idxRow in Enumerable.Range(0, this.table.GetLength(0))) 462 | { 463 | this.table[idxRow, this.Z(target)] ^= this.table[idxRow, this.X(target)]; 464 | } 465 | } 466 | 467 | private void Cnot(int control, int target) 468 | { 469 | foreach (var idxRow in Enumerable.Range(0, this.table.GetLength(0))) 470 | { 471 | this.table[idxRow, this.RIndex] ^= this.table[idxRow, this.X(control)] & 472 | this.table[idxRow, this.Z(target)] & 473 | (this.table[idxRow, this.X(target)] ^ this.table[idxRow, this.Z(control)] ^ true); 474 | } 475 | 476 | foreach (var idxRow in Enumerable.Range(0, this.table.GetLength(0))) 477 | { 478 | this.table[idxRow, this.X(target)] ^= this.table[idxRow, this.X(control)]; 479 | } 480 | 481 | foreach (var idxRow in Enumerable.Range(0, this.table.GetLength(0))) 482 | { 483 | this.table[idxRow, this.Z(control)] ^= this.table[idxRow, this.Z(target)]; 484 | } 485 | } 486 | 487 | private Result MeasureByIndex(int idx) 488 | { 489 | // Deterministic Case 490 | if (this.IsMeasurementDetermined(idx, out var result)) 491 | { 492 | return result; 493 | } 494 | 495 | // Non-Deterministic Case 496 | else 497 | { 498 | var collisions = this.table.Column(idx).IndicesWhere(b => b).ToList(); 499 | var idxFirst = this.nQubits + this.table.Column(idx).Skip(this.nQubits).IndicesWhere(b => b).First(); 500 | 501 | foreach (var idxCollision in collisions.Where(idxCollision => idxCollision != idxFirst)) 502 | { 503 | this.table.SetToRowSum(idxCollision, idxFirst); 504 | } 505 | 506 | foreach (var idxColumn in Enumerable.Range(0, this.table.GetLength(1))) 507 | { 508 | this.table[idxFirst - this.nQubits, idxColumn] = this.table[idxFirst, idxColumn]; 509 | this.table[idxFirst, idxColumn] = false; 510 | } 511 | 512 | this.table[idxFirst, this.Z(idx)] = true; 513 | this.table[idxFirst, this.RIndex] = result == Result.One; 514 | return result; 515 | } 516 | } 517 | 518 | private bool IsMeasurementDetermined(int idx, [NotNullWhen(true)] out Result result) 519 | { 520 | var isDetermined = !this.table.Column(idx).Skip(this.nQubits).Any(b => b); 521 | if (isDetermined) 522 | { 523 | var vector = new bool[(2 * this.nQubits) + 1]; 524 | foreach (var idxDestabilizer in Enumerable.Range(0, this.nQubits)) 525 | { 526 | if (this.table[idxDestabilizer, this.X(idx)]) 527 | { 528 | vector.SetToRowSum(this.table, idxDestabilizer + this.nQubits); 529 | } 530 | } 531 | 532 | result = vector[^1] ? Result.One : Result.Zero; 533 | } 534 | else 535 | { 536 | result = new System.Random().Next(2) == 1 ? Result.One : Result.Zero; 537 | } 538 | 539 | this.Simulator?.MaybeDisplayDiagnostic(new DebugMessage 540 | { 541 | Message = $"IsResultDetermined({idx}, out {result}) = {isDetermined}", 542 | }); 543 | return isDetermined; 544 | } 545 | 546 | private void Allocate(IQArray qubits) 547 | { 548 | this.allocated += qubits.Count; 549 | if (this.allocated > this.nQubits) 550 | { 551 | throw new UnsupportedOperationException($"Simulator supports a max of {this.nQubits} qubits. Total requested {this.allocated}"); 552 | } 553 | } 554 | 555 | private void DeAllocate(IQArray qubits) 556 | { 557 | this.allocated -= qubits.Count; 558 | } 559 | 560 | private void WriteToScratch(IQArray bases, IQArray qubits, Qubit aux) 561 | { 562 | foreach (var (pauli, qubit) in Enumerable.Zip(bases, qubits, (pauli, qubit) => (pauli, qubit))) 563 | { 564 | switch (pauli) 565 | { 566 | case Pauli.PauliI: 567 | break; 568 | 569 | case Pauli.PauliX: 570 | this.H(qubit); 571 | this.ControlledX(new QArray(new[] { qubit }), aux); 572 | this.H(qubit); 573 | break; 574 | 575 | case Pauli.PauliY: 576 | this.H(qubit); 577 | this.S(qubit); 578 | this.ControlledX(new QArray(new[] { qubit }), aux); 579 | this.SAdjoint(qubit); 580 | this.H(qubit); 581 | break; 582 | 583 | // Pauli.PauliZ: 584 | default: 585 | this.ControlledX(new QArray(new[] { qubit }), aux); 586 | break; 587 | } 588 | } 589 | } 590 | } 591 | } 592 | -------------------------------------------------------------------------------- /src/StabilizerSimulator.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Sarah Kaiser. Licensed under the MIT License. 3 | // 4 | // This C# project is based on a Python implementation by @Strilanc here: 5 | // https://github.com/Strilanc/python-chp-stabilizer-simulator 6 | 7 | namespace QSharpCommunity.Simulators.Chp 8 | { 9 | using System; 10 | using Microsoft.Quantum.Simulation.Common; 11 | using Microsoft.Quantum.Simulation.QuantumProcessor; 12 | 13 | /// 14 | /// CHP Simulator. 15 | /// 16 | public class StabilizerSimulator : QuantumProcessorDispatcher 17 | { 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// Qubits to use for simulation. 22 | public StabilizerSimulator(int? nQubits = null) 23 | : base(new StabilizerProcessor(nQubits)) 24 | { 25 | (this.QuantumProcessor as StabilizerProcessor).Simulator = this; 26 | } 27 | 28 | /// 29 | /// If diagnostic is enabled, show diagnostic information. 30 | /// 31 | /// Diagnostic displayable information. 32 | internal new void MaybeDisplayDiagnostic(object displayable) => 33 | base.MaybeDisplayDiagnostic(displayable); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/jupyter/ChpMagic.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Sarah Kaiser. Licensed under the MIT License. 3 | // 4 | // Adapted from Toffoli magic command in the IQSharp project here: 5 | // https://github.com/microsoft/iqsharp/blob/master/src/Kernel/Magic/ToffoliMagic.cs 6 | 7 | namespace QSharpCommunity.Simulators.Chp 8 | { 9 | using System; 10 | using System.Threading.Tasks; 11 | using Microsoft.Jupyter.Core; 12 | using Microsoft.Quantum.IQSharp; 13 | using Microsoft.Quantum.IQSharp.Common; 14 | using Microsoft.Quantum.IQSharp.Jupyter; 15 | using Microsoft.Quantum.Simulation.Simulators; 16 | 17 | /// 18 | /// Runs a given function or operation on the ChpSimulator target machine. 19 | /// 20 | public class ChpMagic : AbstractMagic 21 | { 22 | private const string ParameterNameOperationName = "__operationName__"; 23 | private const int DefaultNQubits = 1024; 24 | private readonly IConfigurationSource configurationSource; 25 | 26 | /// 27 | /// Initializes a new instance of the class. 28 | /// Default constructor. 29 | /// 30 | /// Symbol resolver. 31 | /// Source for confirgarion settings. 32 | public ChpMagic(ISymbolResolver resolver, IConfigurationSource configurationSource) 33 | : base( 34 | "chp", 35 | new Documentation 36 | { 37 | Summary = "Runs a given function or operation on the StabilizerSimulator target machine.", 38 | Description = @" 39 | This magic command allows executing a given function or operation on the StabilizerSimulator, 40 | which performs a simulation of the given function or operation in which the state can always be 41 | represented by a stabilizer of the form described by CHP, and prints the resulting return value. 42 | 43 | See the [StabilizerSimulator user guide](https://github.com/qsharp-community/chp-sim/docs/user-guide.md) to learn more. 44 | 45 | #### Required parameters 46 | 47 | - Q# operation or function name. This must be the first parameter, and must be a valid Q# operation 48 | or function name that has been defined either in the notebook or in a Q# file in the same folder. 49 | - Arguments for the Q# operation or function must also be specified as `key=value` pairs. 50 | ", 51 | Examples = new[] 52 | { 53 | @" 54 | Use the StabilizerSimulator to simulate a Q# operation 55 | defined as `operation MyOperation() : Result`: 56 | ``` 57 | In []: %chp MyOperation 58 | Out[]: 59 | ``` 60 | ", 61 | @" 62 | Use the StabilizerSimulator to simulate a Q# operation 63 | defined as `operation MyOperation(a : Int, b : Int) : Result`: 64 | ``` 65 | In []: %chp MyOperation a=5 b=10 66 | Out[]: 67 | ``` 68 | ", 69 | }, 70 | }) 71 | { 72 | this.SymbolResolver = resolver; 73 | this.configurationSource = configurationSource; 74 | } 75 | 76 | /// 77 | /// Gets the ISumbolResolver used to find the function/operation to simulate. 78 | /// 79 | public ISymbolResolver SymbolResolver { get; } 80 | 81 | /// 82 | public override ExecutionResult Run(string input, IChannel channel) => 83 | this.RunAsync(input, channel).Result; 84 | 85 | /// 86 | /// Simulates a function/operation using the ChpSimulator as target machine. 87 | /// It expects a single input: the name of the function/operation to simulate. 88 | /// 89 | /// current parameters for the function. 90 | /// channel connecting up with Jupyter. 91 | /// function result. 92 | public async Task RunAsync(string input, IChannel channel) 93 | { 94 | var inputParameters = ParseInputParameters(input, firstParameterInferredName: ParameterNameOperationName); 95 | 96 | var name = inputParameters.DecodeParameter(ParameterNameOperationName); 97 | var symbol = this.SymbolResolver.Resolve(name) as dynamic; // FIXME: should be as IQSharpSymbol. 98 | if (symbol == null) 99 | { 100 | throw new InvalidOperationException($"Invalid operation name: {name}"); 101 | } 102 | 103 | var nQubits = 104 | this.configurationSource.GetOptionOrDefault("chp.nQubits", DefaultNQubits); 105 | 106 | var debug = 107 | this.configurationSource.GetOptionOrDefault("chp.debug", false); 108 | 109 | var qsim = new StabilizerSimulator(nQubits).WithStackTraceDisplay(channel); 110 | qsim.DisableLogToConsole(); 111 | qsim.OnDisplayableDiagnostic += (displayable) => 112 | { 113 | if (displayable is DebugMessage message) 114 | { 115 | if (debug) 116 | { 117 | channel.Stderr($"DEBUG: {message.Message}"); 118 | } 119 | } 120 | else 121 | { 122 | channel.Display(displayable); 123 | } 124 | }; 125 | qsim.OnLog += channel.Stdout; 126 | 127 | var operationInfo = (OperationInfo)symbol.Operation; 128 | var value = await operationInfo.RunAsync(qsim, inputParameters); 129 | 130 | return value.ToExecutionResult(); 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /src/jupyter/StabilizerTableau.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Sarah Kaiser. Licensed under the MIT License. 3 | // 4 | // Adapted from State display encoders in the IQSharp project here: 5 | // https://github.com/microsoft/iqsharp/blob/master/src/Jupyter/Visualization/StateDisplayEncoders.cs 6 | #nullable enable 7 | 8 | namespace QSharpCommunity.Simulators.Chp 9 | { 10 | using System; 11 | 12 | /// 13 | /// Representation of the Tableau. 14 | /// 15 | public class StabilizerTableau 16 | { 17 | /// 18 | /// Gets or sets the data to be shown in the Tableau format. 19 | /// 20 | public bool[,] Data { get; set; } = new bool[1, 1]; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/jupyter/TableauToHtmlEncoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Sarah Kaiser. Licensed under the MIT License. 3 | // 4 | // Adapted from State display encoders in the IQSharp project here: 5 | // https://github.com/microsoft/iqsharp/blob/master/src/Jupyter/Visualization/StateDisplayEncoders.cs 6 | #nullable enable 7 | 8 | namespace QSharpCommunity.Simulators.Chp 9 | { 10 | using System; 11 | using Microsoft.Jupyter.Core; 12 | using Microsoft.Quantum.IQSharp.Jupyter; 13 | 14 | /// 15 | /// Encodes the Tableau in HTML so it can be rendered by Jupyter. 16 | /// 17 | public class TableauToHtmlEncoder : IResultEncoder 18 | { 19 | private readonly IConfigurationSource configurationSource; 20 | private enum DumpFormat 21 | { 22 | Matrix, 23 | DensePaulis, 24 | SparsePaulis 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class. 29 | /// 30 | /// Settings to be used. 31 | public TableauToHtmlEncoder(IConfigurationSource configurationSource) 32 | { 33 | this.configurationSource = configurationSource; 34 | } 35 | 36 | /// 37 | /// Gets the mimetype used for rendering that its html. 38 | /// 39 | public string MimeType => MimeTypes.Html; 40 | 41 | /// 42 | /// Returns the StabilizerTableau into the text as encoded data. 43 | /// 44 | /// Should be the StabilizerTableau. 45 | /// Text encoded table. 46 | public EncodedData? Encode(object displayable) 47 | { 48 | if (displayable is StabilizerTableau tableau) 49 | { 50 | var showDestabilizers = 51 | this.configurationSource.GetOptionOrDefault("chp.showDestabilizers", false); 52 | 53 | var nQubits = tableau.Data.GetLength(0) / 2; 54 | 55 | var dumpFormat = 56 | this.configurationSource.GetOptionOrDefault("chp.dumpFormat", DumpFormat.DensePaulis); 57 | 58 | // Display the tableau as a matrix 59 | if (dumpFormat == DumpFormat.Matrix) 60 | { 61 | var tableFormat = new string('c', nQubits); 62 | var tableRows = tableau.Data.MatrixToBinaryLatexString(showDestabilizers); 63 | 64 | var outputTable = $@" 65 | $\left(\begin{{array}}{{{tableFormat}|{tableFormat}|c}} 66 | {tableRows} 67 | \end{{array}} \right)$"; 68 | 69 | return outputTable.ToEncodedData(); 70 | } 71 | 72 | // Display the tableau as a list of Pauli operators. 73 | else if (dumpFormat == DumpFormat.DensePaulis) 74 | { 75 | var stabilizerList = tableau.Data.MatrixToPauliLatex(); 76 | var outputLine = $@"${stabilizerList}$"; 77 | return outputLine.ToEncodedData(); 78 | } 79 | 80 | // Display the tableau as a list of Pauli operators, omitting the identities. 81 | else if (dumpFormat == DumpFormat.SparsePaulis) 82 | { 83 | var stabilizerList = tableau.Data.MatrixToSparsePauliLatex(); 84 | var outputLine = $@"${stabilizerList}$"; 85 | return outputLine.ToEncodedData(); 86 | } 87 | 88 | else 89 | { // message that the dumpformat is not supported. 90 | return null; 91 | } 92 | 93 | } 94 | else 95 | { 96 | return null; 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/jupyter/TableauToTextEncoder.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Sarah Kaiser. Licensed under the MIT License. 3 | // 4 | // Adapted from State display encoders in the IQSharp project here: 5 | // https://github.com/microsoft/iqsharp/blob/master/src/Jupyter/Visualization/StateDisplayEncoders.cs 6 | #nullable enable 7 | 8 | namespace QSharpCommunity.Simulators.Chp 9 | { 10 | using System; 11 | using Microsoft.Jupyter.Core; 12 | using Microsoft.Quantum.IQSharp.Jupyter; 13 | 14 | /// 15 | /// Encodes the Tableau in text so it can be rendered by jupiter. 16 | /// 17 | public class TableauToTextEncoder : IResultEncoder 18 | { 19 | /// 20 | /// Gets the mimetype used for rendering that its text. 21 | /// 22 | public string MimeType => MimeTypes.PlainText; 23 | 24 | /// 25 | /// Returns the StabilizerTableau into the text as encoded data. 26 | /// 27 | /// Should be the StabilizerTableau. 28 | /// Text encoded table. 29 | public EncodedData? Encode(object displayable) 30 | { 31 | if (displayable is StabilizerTableau tableau) 32 | { 33 | return tableau.Data.MatrixToPauliString(true).ToEncodedData(); 34 | } 35 | else 36 | { 37 | return null; 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | // ACTION REQUIRED: This file was automatically added to your project, but it 3 | // will not take effect until additional steps are taken to enable it. See the 4 | // following page for additional information: 5 | // 6 | // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md 7 | 8 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 9 | "settings": { 10 | "documentationRules": { 11 | "companyName": "https://qsharp.community/", 12 | "copyrightText": "Copyright (c) Sarah Kaiser. Licensed under the MIT License." 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/AllocationTests.qs: -------------------------------------------------------------------------------- 1 | namespace ChpSimulator.Test { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Intrinsic; 5 | 6 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 7 | @Test("QuantumSimulator") 8 | operation AllocateOneQubit () : Unit { 9 | use q = Qubit(); 10 | AssertMeasurement([PauliZ], [q], Zero, "Newly allocated qubit must be in |0> state."); 11 | Message("Test passed."); 12 | } 13 | 14 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 15 | @Test("QuantumSimulator") 16 | operation BorrowOneQubit () : Unit { 17 | borrow q = Qubit(); 18 | AssertMeasurement([PauliZ], [q], Zero, "Newly allocated qubit must be in |0> state."); 19 | Message("Test passed."); 20 | } 21 | 22 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 23 | @Test("QuantumSimulator") 24 | operation AllocateMultipleQubits () : Unit { 25 | use register = Qubit[4]; 26 | AssertAllZero(register); 27 | Message("Test passed."); 28 | } 29 | 30 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 31 | @Test("QuantumSimulator") 32 | operation BorrowingMultipleQubits () : Unit { 33 | borrow register = Qubit[4]; 34 | AssertAllZero(register); 35 | Message("Test passed."); 36 | } 37 | 38 | // Check that we don't go directly OOM with largish values 39 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 40 | @Test("ToffoliSimulator") 41 | operation AllocateManyQubits () : Unit { 42 | use register = Qubit[1024]; 43 | AssertAllZero(register); 44 | //Make sure the compiler doesn't cheat at us' 45 | for q in register 46 | { 47 | X(q); 48 | } 49 | ResetAll(register); 50 | Message("Test passed."); 51 | } 52 | 53 | // Check that we don't go directly OOM with largish values 54 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 55 | @Test("ToffoliSimulator") 56 | operation BorrowingManyQubits () : Unit { 57 | borrow register = Qubit[1024]; 58 | AssertAllZero(register); 59 | //Make sure the compiler doesn't cheat at us' 60 | for q in register 61 | { 62 | X(q); 63 | } 64 | ResetAll(register); 65 | Message("Test passed."); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/CNotTests.qs: -------------------------------------------------------------------------------- 1 | namespace ChpSimulator.Test { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Intrinsic; 5 | 6 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 7 | @Test("QuantumSimulator") 8 | operation CNotZeroZeroZero() : Unit { 9 | use (c,t) = (Qubit(), Qubit()); 10 | CNOT(c,t); 11 | 12 | AssertMeasurement([PauliZ],[c], Zero, "Should be untouched"); 13 | AssertMeasurement([PauliZ],[t], Zero, "Should be untouched"); 14 | Reset(c); 15 | Reset(t); 16 | Message("Test passed."); 17 | } 18 | 19 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 20 | @Test("QuantumSimulator") 21 | operation CNotZeroOneOne() : Unit { 22 | use (c,t) = (Qubit(), Qubit()); 23 | X(t); 24 | CNOT(c,t); 25 | 26 | AssertMeasurement([PauliZ],[c], Zero, "Should be untouched"); 27 | AssertMeasurement([PauliZ],[t], One, "Should be rotated"); 28 | Reset(t); 29 | Message("Test passed."); 30 | } 31 | 32 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 33 | @Test("QuantumSimulator") 34 | operation CNotOneZeroOne() : Unit { 35 | use (c,t) = (Qubit(), Qubit()); 36 | X(c); 37 | CNOT(c,t); 38 | 39 | AssertMeasurement([PauliZ],[c], One, "Should be set"); 40 | AssertMeasurement([PauliZ],[t], One, "Should be rotated"); 41 | Reset(c); 42 | Reset(t); 43 | Message("Test passed."); 44 | } 45 | 46 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 47 | @Test("QuantumSimulator") 48 | operation CNotOneOneZero() : Unit { 49 | use (c,t) = (Qubit(), Qubit()); 50 | X(c); 51 | X(t); 52 | CNOT(c,t); 53 | AssertMeasurement([PauliZ],[c], One, "Should be untouched"); 54 | AssertMeasurement([PauliZ],[t], Zero, "Should be rotated"); 55 | 56 | Reset(c); 57 | Message("Test passed."); 58 | } 59 | 60 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 61 | @Test("QuantumSimulator") 62 | operation InvertedCNotZeroZeroZero() : Unit { 63 | use (c,t) = (Qubit(), Qubit()); 64 | H(c); 65 | H(t); 66 | CNOT(t,c); 67 | H(c); 68 | H(t); 69 | 70 | AssertMeasurement([PauliZ],[c], Zero, "Should be untouched"); 71 | AssertMeasurement([PauliZ],[t], Zero, "Should be untouched"); 72 | Reset(c); 73 | Reset(t); 74 | Message("Test passed."); 75 | } 76 | 77 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 78 | @Test("QuantumSimulator") 79 | operation InvertedCNotZeroOneOne() : Unit { 80 | use (c,t) = (Qubit(), Qubit()); 81 | X(t); 82 | H(c); 83 | H(t); 84 | CNOT(t,c); 85 | H(c); 86 | H(t); 87 | 88 | AssertMeasurement([PauliZ],[c], Zero, "Should be untouched"); 89 | AssertMeasurement([PauliZ],[t], One, "Should be rotated"); 90 | Reset(t); 91 | Message("Test passed."); 92 | } 93 | 94 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 95 | @Test("QuantumSimulator") 96 | operation InvertedCNotOneZeroOne() : Unit { 97 | use (c,t) = (Qubit(), Qubit()); 98 | X(c); 99 | H(c); 100 | H(t); 101 | CNOT(t,c); 102 | H(c); 103 | H(t); 104 | 105 | AssertMeasurement([PauliZ],[c], One, "Should be set"); 106 | AssertMeasurement([PauliZ],[t], One, "Should be rotated"); 107 | Reset(c); 108 | Reset(t); 109 | Message("Test passed."); 110 | } 111 | 112 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 113 | @Test("QuantumSimulator") 114 | operation InvertedCNotOneOneZero() : Unit { 115 | use (c,t) = (Qubit(), Qubit()); 116 | X(c); 117 | X(t); 118 | H(c); 119 | H(t); 120 | CNOT(t,c); 121 | H(c); 122 | H(t); 123 | AssertMeasurement([PauliZ],[c], One, "Should be untouched"); 124 | AssertMeasurement([PauliZ],[t], Zero, "Should be rotated"); 125 | 126 | Reset(c); 127 | Message("Test passed."); 128 | } 129 | 130 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 131 | @Test("QuantumSimulator") 132 | operation CNotEqual() : Unit { 133 | use (c,t) = (Qubit(), Qubit()); 134 | H(c); 135 | CNOT(c,t); 136 | 137 | let left = M(c); 138 | let right = M(t); 139 | EqualityFactR(left,right, "Should be the same"); 140 | 141 | Reset(c); 142 | Reset(t); 143 | Message("Test passed."); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /test/ChpSimulator.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | false 6 | AnyCPU;x64 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | all 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /test/ClassiclyControlledTest.qs: -------------------------------------------------------------------------------- 1 | namespace ChpSimulator.Test { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Intrinsic; 5 | 6 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 7 | @Test("QuantumSimulator") 8 | operation MeasurementAndMessageTest() : Unit { 9 | use q = Qubit(); 10 | H(q); 11 | let r = M(q); 12 | if (r == Zero) { 13 | Dog(); 14 | } 15 | else 16 | { 17 | Duck(); 18 | } 19 | Reset(q); 20 | Message("Test passed."); 21 | } 22 | 23 | operation Dog() : Unit 24 | { 25 | Message("Woof!!"); 26 | } 27 | 28 | operation Duck() : Unit 29 | { 30 | Message("Quack!!"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/HadamardTests.qs: -------------------------------------------------------------------------------- 1 | namespace ChpSimulator.Test { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Intrinsic; 5 | 6 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 7 | @Test("QuantumSimulator") 8 | operation HadamardQubits () : Unit { 9 | use q = Qubit(); 10 | H(q); //|+> 11 | S(q); //|i> 12 | S(q); //|-> 13 | H(q); //|1> 14 | AssertMeasurement([PauliZ],[q], One, "Should make the rotations"); 15 | Reset(q); 16 | Message("Test passed."); 17 | } 18 | 19 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 20 | @Test("QuantumSimulator") 21 | operation HadamardMultipleQubits () : Unit { 22 | use register = Qubit[4]; 23 | H(register[2]); //|+> 24 | S(register[2]); //|i> 25 | S(register[2]); //|-> 26 | H(register[2]); //|1> 27 | AssertMeasurement([PauliZ],[register[0]], Zero, "first qubit shouldn't have been flipped"); 28 | AssertMeasurement([PauliZ],[register[1]], Zero, "second qubit shouldn't have been flipped"); 29 | AssertMeasurement([PauliZ],[register[2]], One, "third qubit should have been flipped"); 30 | AssertMeasurement([PauliZ],[register[3]], Zero, "fourth qubit shouldn't have been flipped"); 31 | Reset(register[2]); 32 | Message("Test passed."); 33 | } 34 | 35 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 36 | @Test("QuantumSimulator") 37 | operation HadamardProbMeasuredQubits () : Unit { 38 | use q = Qubit(); 39 | H(q); //|+> 40 | AssertMeasurementProbability([PauliZ],[q], One, 0.5, "Should make the rotations",1e-5); 41 | Reset(q); 42 | Message("Test passed."); 43 | } 44 | 45 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 46 | @Test("QuantumSimulator") 47 | operation HadamardProbMeasuredMultipleQubits () : Unit { 48 | use register = Qubit[4]; 49 | H(register[2]); //|+> 50 | 51 | AssertMeasurement([PauliZ],[register[0]], Zero, "first qubit shouldn't have been flipped"); 52 | AssertMeasurement([PauliZ],[register[1]], Zero, "second qubit shouldn't have been flipped"); 53 | AssertMeasurementProbability([PauliZ],[register[2]], One, 0.5, "should be in superposition", 1e-5); 54 | AssertMeasurement([PauliZ],[register[3]], Zero, "fourth qubit shouldn't have been flipped"); 55 | Reset(register[2]); 56 | Message("Test passed."); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/MeasurementTest.qs: -------------------------------------------------------------------------------- 1 | namespace ChpSimulator.Test { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Intrinsic; 5 | 6 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 7 | @Test("QuantumSimulator") 8 | operation MeasureZeroTest() : Unit { 9 | use (a,b) = (Qubit(),Qubit()); 10 | let x = M(a); 11 | let y = M(b); 12 | 13 | EqualityFactR(x,Zero, "Should be |0>"); 14 | EqualityFactR(y,Zero, "Should be |0>"); 15 | 16 | AssertMeasurement([PauliZ], [a], Zero, "Should not be changed. Still be |0>"); 17 | AssertMeasurement([PauliZ], [b], Zero, "Should not be changed. Still be |0>"); 18 | Reset(b); 19 | Message("Test passed."); 20 | } 21 | 22 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 23 | @Test("QuantumSimulator") 24 | operation MeasureOneTest() : Unit { 25 | use (a,b) = (Qubit(),Qubit()); 26 | StateOne(b); 27 | let x = M(a); 28 | let y = M(b); 29 | 30 | EqualityFactR(x,Zero, "Measurement should be |0>"); 31 | EqualityFactR(y,One, "Measurement should be |1>"); 32 | AssertMeasurement([PauliZ], [a], Zero, "Should not be changed. Still be |0>"); 33 | AssertMeasurement([PauliZ], [b], One, "Should be |1>"); 34 | Reset(b); 35 | Message("Test passed."); 36 | } 37 | 38 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 39 | @Test("QuantumSimulator") 40 | operation MeasureOneBothTest() : Unit { 41 | use (a,b) = (Qubit(),Qubit()); 42 | StateOne(a); 43 | StateOne(b); 44 | let x = M(a); 45 | let y = M(b); 46 | 47 | EqualityFactR(x,One, "Measurement should be |1>"); 48 | EqualityFactR(y,One, "Measurement should be |1>"); 49 | AssertMeasurement([PauliZ], [a], One, "Should be |1>"); 50 | AssertMeasurement([PauliZ], [b], One, "Should be |1>"); 51 | Reset(b); 52 | Message("Test passed."); 53 | } 54 | 55 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 56 | @Test("QuantumSimulator") 57 | operation MeasureBellBothTest() : Unit { 58 | use (a, b) = (Qubit(), Qubit()); 59 | H(a); 60 | CNOT(a, b); 61 | let x = Measure([PauliX, PauliX],[a, b]); 62 | //M(a) == Measure([PauliZ], [a]) 63 | EqualityFactR(x, Zero, "Measurements should be Zero"); 64 | 65 | Reset(a); 66 | Reset(b); 67 | Message("Test passed."); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /test/PauliXTests.qs: -------------------------------------------------------------------------------- 1 | namespace ChpSimulator.Test { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Intrinsic; 5 | 6 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 7 | @Test("QuantumSimulator") 8 | operation PauliXFlipOneQubit () : Unit { 9 | use q = Qubit(); 10 | X(q); 11 | AssertMeasurement([PauliZ],[q], One, "Qubit should have been flipped"); 12 | Reset(q); 13 | Message("Test passed."); 14 | } 15 | 16 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 17 | @Test("QuantumSimulator") 18 | operation PauliXFlipSecondQubit () : Unit { 19 | use register = Qubit[4]; 20 | X(register[1]); 21 | AssertMeasurement([PauliZ],[register[0]], Zero, "first qubit shouldn't have been flipped"); 22 | AssertMeasurement([PauliZ],[register[1]], One, "second qubit should have been flipped"); 23 | AssertMeasurement([PauliZ],[register[2]], Zero, "third qubit shouldn't have been flipped"); 24 | AssertMeasurement([PauliZ],[register[3]], Zero, "fourth qubit shouldn't have been flipped"); 25 | ResetAll(register); 26 | Message("Test passed."); 27 | } 28 | 29 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 30 | @Test("QuantumSimulator") 31 | operation PauliXPairQubit () : Unit { 32 | use (left,right) = (Qubit(),Qubit()); 33 | X(right); 34 | AssertMeasurement([PauliZ],[left], Zero, "first qubit shouldn't have been flipped"); 35 | AssertMeasurement([PauliZ],[right], One, "second qubit should have been flipped"); 36 | 37 | Reset(right); 38 | Message("Test passed."); 39 | } 40 | 41 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 42 | @Test("QuantumSimulator") 43 | operation PauliXFlipAfterHadamardQubit () : Unit { 44 | use q = Qubit(); 45 | H(q); // |+> 46 | X(q); // |+> 47 | H(q); // |0> 48 | AssertMeasurement([PauliZ],[q], Zero, "Qubit shouldn't have been flipped"); 49 | Reset(q); 50 | Message("Test passed."); 51 | } 52 | 53 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 54 | @Test("QuantumSimulator") 55 | operation FlippedPauliXFlipAfterHadamardQubit () : Unit { 56 | use q = Qubit(); 57 | X(q); // |1> 58 | H(q); // |-> 59 | X(q); // |-> 60 | H(q); // |1> 61 | AssertMeasurement([PauliZ],[q], One, "Qubit shouldn't have been flipped"); 62 | Reset(q); 63 | Message("Test passed."); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/PhaseTest.qs: -------------------------------------------------------------------------------- 1 | namespace ChpSimulator.Test { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Intrinsic; 5 | 6 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 7 | @Test("QuantumSimulator") 8 | operation PhaseRotateXQubit () : Unit { 9 | use q = Qubit(); 10 | StatePlus(q); //|+> 11 | S(q); //|i> 12 | AssertMeasurementProbability([PauliX], [q], One, 0.5, "Should be |i>", 1e-5 ); 13 | Reset(q); 14 | Message("Test passed."); 15 | } 16 | 17 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 18 | @Test("QuantumSimulator") 19 | operation PhaseRotateX2Qubit () : Unit { 20 | use q = Qubit(); 21 | StateI(q); 22 | S(q); //|-> 23 | AssertMeasurement([PauliX], [q], One, "Should be |->"); 24 | Reset(q); 25 | Message("Test passed."); 26 | } 27 | 28 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 29 | @Test("QuantumSimulator") 30 | operation PhaseRotateYQubit () : Unit { 31 | use q = Qubit(); 32 | H(q); //|+> 33 | S(q); //|i> 34 | AssertMeasurement([PauliY], [q], Zero, "Should be |i>"); 35 | Reset(q); 36 | Message("Test passed."); 37 | } 38 | 39 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 40 | @Test("QuantumSimulator") 41 | operation PhaseRotateY2Qubit () : Unit { 42 | use q = Qubit(); 43 | H(q); //|+> 44 | S(q); //|i> 45 | S(q); //|-> 46 | AssertMeasurementProbability([PauliY], [q], One, 0.5, "Should be |i>", 1e-5 ); 47 | Reset(q); 48 | Message("Test passed."); 49 | } 50 | 51 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 52 | @Test("QuantumSimulator") 53 | operation PhaseRotateZQubit () : Unit { 54 | use q = Qubit(); 55 | H(q); //|+> 56 | S(q); //|i> 57 | AssertMeasurementProbability([PauliZ], [q], One, 0.5, "Should be |i>", 1e-5 ); 58 | Reset(q); 59 | Message("Test passed."); 60 | } 61 | 62 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 63 | @Test("QuantumSimulator") 64 | operation PhaseRotateZ2Qubit () : Unit { 65 | use q = Qubit(); 66 | H(q); //|+> 67 | S(q); //|i> 68 | S(q); //|-> 69 | AssertMeasurementProbability([PauliZ], [q], One, 0.5, "Should be |->", 1e-5 ); 70 | Reset(q); 71 | Message("Test passed."); 72 | } 73 | 74 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 75 | @Test("QuantumSimulator") 76 | operation PhaseZeroQubit () : Unit { 77 | use q = Qubit(); 78 | S(q); //|0> 79 | AssertMeasurement([PauliZ], [q], Zero, "S gate can't move |0>"); 80 | Reset(q); 81 | Message("Test passed."); 82 | } 83 | 84 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 85 | @Test("QuantumSimulator") 86 | operation PhaseOneQubit () : Unit { 87 | use q = Qubit(); 88 | X(q); //|1> 89 | S(q); //|1> 90 | AssertMeasurement([PauliZ], [q], One, "S gate can't move |1>"); 91 | Reset(q); 92 | Message("Test passed."); 93 | } 94 | 95 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 96 | @Test("QuantumSimulator") 97 | operation PhaseRotateMultiQubit () : Unit { 98 | use register = Qubit[3]; 99 | H(register[1]); //|+> 100 | S(register[1]); //|i> 101 | 102 | AssertMeasurement([PauliZ],[register[0]], Zero, "Should be untouched"); 103 | AssertMeasurementProbability([PauliZ], [register[1]], One, 0.5, "Should be |i>", 1e-5 ); 104 | AssertMeasurement([PauliZ],[register[2]], Zero, "Should be untouched"); 105 | Reset(register[1]); 106 | Message("Test passed."); 107 | } 108 | 109 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 110 | @Test("QuantumSimulator") 111 | operation PhaseRotateXMultiQubit () : Unit { 112 | use register = Qubit[3]; 113 | H(register[1]); //|+> 114 | S(register[1]); //|i> 115 | 116 | AssertMeasurementProbability([PauliX], [register[0]], One, 0.5, "Should be |0>", 1e-5 ); 117 | AssertMeasurementProbability([PauliX], [register[1]], One, 0.5, "Should be |i>", 1e-5 ); 118 | AssertMeasurementProbability([PauliX], [register[2]], One, 0.5, "Should be |0>", 1e-5 ); 119 | Reset(register[1]); 120 | Message("Test passed."); 121 | } 122 | 123 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 124 | @Test("QuantumSimulator") 125 | operation PhaseRotateYMultiQubit () : Unit { 126 | use register = Qubit[3]; 127 | H(register[1]); //|+> 128 | S(register[1]); //|i> 129 | 130 | AssertMeasurementProbability([PauliY], [register[0]], One, 0.5, "Should be |0>", 1e-5 ); 131 | AssertMeasurement([PauliY],[register[1]], Zero, "Should be |i>"); 132 | AssertMeasurementProbability([PauliY], [register[2]], One, 0.5, "Should be |0>", 1e-5 ); 133 | Reset(register[1]); 134 | Message("Test passed."); 135 | } 136 | 137 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 138 | @Test("QuantumSimulator") 139 | operation PhaseRotatePairYMultiQubit () : Unit { 140 | use (left,right) = (Qubit(),Qubit()); 141 | H(right); //|+> 142 | S(right); //|i> 143 | S(right); //|-> 144 | AssertMeasurement([PauliZ],[left], Zero, "Should be untouched"); 145 | AssertMeasurementProbability([PauliY], [right], One, 0.5, "Should be |->", 1e-5 ); 146 | Reset(right); 147 | Message("Test passed."); 148 | } 149 | 150 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 151 | @Test("QuantumSimulator") 152 | operation PhaseRotatePairXMultiQubit () : Unit { 153 | use (left,right) = (Qubit(),Qubit()); 154 | H(right); //|+> 155 | S(right); //|i> 156 | S(right); //|-> 157 | AssertMeasurement([PauliX], [right], One, "Should be |->"); 158 | AssertMeasurementProbability([PauliX], [left], One, 0.5, "Should be untouched", 1e-5 ); 159 | Reset(right); 160 | Message("Test passed."); 161 | } 162 | 163 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 164 | @Test("QuantumSimulator") 165 | operation PhaseRotatePairZMultiQubit () : Unit { 166 | use (left,right) = (Qubit(),Qubit()); 167 | H(right); //|+> 168 | S(right); //|i> 169 | S(right); //|-> 170 | AssertMeasurement([PauliZ],[left], Zero, "Should be untouched"); 171 | AssertMeasurementProbability([PauliZ], [right], One, 0.5, "Should be |->", 1e-5 ); 172 | Reset(right); 173 | Message("Test passed."); 174 | } 175 | 176 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 177 | @Test("QuantumSimulator") 178 | operation PhaseMultiQubit () : Unit { 179 | use register = Qubit[3]; 180 | S(register[1]); //|0> 181 | AssertAllZero(register); 182 | Message("Test passed."); 183 | } 184 | 185 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 186 | @Test("QuantumSimulator") 187 | operation PhaseXMultiQubit () : Unit { 188 | use register = Qubit[3]; 189 | X(register[1]); //|1> 190 | S(register[1]); //|1> 191 | 192 | AssertMeasurement([PauliZ],[register[0]], Zero, "Should be untouched"); 193 | AssertMeasurement([PauliZ],[register[1]], One, "Qubit shouldn't have been flipped"); 194 | AssertMeasurement([PauliZ],[register[2]], Zero, "Should be untouched"); 195 | ResetAll(register); 196 | Message("Test passed."); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /test/States.qs: -------------------------------------------------------------------------------- 1 | namespace ChpSimulator.Test { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Intrinsic; 5 | 6 | /// 7 | /// Some Helper functions to make the unittest more readable 8 | /// 9 | 10 | // Brings from state |0> to |+> 11 | operation StatePlus (q: Qubit) : Unit { 12 | H(q); 13 | } 14 | 15 | // Brings from state |0> to |i> 16 | operation StateI (q: Qubit) : Unit { 17 | StatePlus(q); //|+> 18 | S(q); //|i> 19 | } 20 | 21 | // Brings from state |0> to |-> 22 | operation StateMinus (q: Qubit) : Unit { 23 | StateI(q); //|i> 24 | S(q); //|-> 25 | } 26 | 27 | // Brings from state |0> to |-> 28 | operation StateMinusI (q: Qubit) : Unit { 29 | StateMinus(q); //|-> 30 | S(q); //|-i> 31 | } 32 | 33 | // Brings from state |0> to |1> 34 | operation StateOne (q: Qubit) : Unit { 35 | StateMinus(q); //|-> 36 | H(q); //|1> 37 | } 38 | 39 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 40 | @Test("QuantumSimulator") 41 | operation StatePlusXTest() : Unit { 42 | use (a,b) = (Qubit(),Qubit()); 43 | StatePlus(b); 44 | AssertMeasurementProbability([PauliX], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 45 | AssertMeasurement([PauliX], [b], Zero, "Should be |+>"); 46 | Reset(b); 47 | Message("Test passed."); 48 | } 49 | 50 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 51 | @Test("QuantumSimulator") 52 | operation StatePlusYTest() : Unit { 53 | use (a,b) = (Qubit(),Qubit()); 54 | StatePlus(b); 55 | AssertMeasurementProbability([PauliY], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 56 | AssertMeasurementProbability([PauliY], [b], One, 0.5, "Should be |+>", 1e-5 ); 57 | Reset(b); 58 | Message("Test passed."); 59 | } 60 | 61 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 62 | @Test("QuantumSimulator") 63 | operation StatePlusZTest() : Unit { 64 | use (a,b) = (Qubit(),Qubit()); 65 | StatePlus(b); 66 | AssertMeasurement([PauliZ], [a], Zero, "Should not be changed. Still be |0>"); 67 | AssertMeasurementProbability([PauliZ], [b], One, 0.5, "Should be |+>", 1e-5 ); 68 | Reset(b); 69 | Message("Test passed."); 70 | } 71 | 72 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 73 | @Test("QuantumSimulator") 74 | operation StateMinusXTest() : Unit { 75 | use (a,b) = (Qubit(),Qubit()); 76 | StateMinus(b); 77 | AssertMeasurementProbability([PauliX], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 78 | AssertMeasurement([PauliX], [b], One, "Should be |->"); 79 | Reset(b); 80 | Message("Test passed."); 81 | } 82 | 83 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 84 | @Test("QuantumSimulator") 85 | operation StateMinusYTest() : Unit { 86 | use (a,b) = (Qubit(),Qubit()); 87 | StateMinus(b); 88 | AssertMeasurementProbability([PauliY], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 89 | AssertMeasurementProbability([PauliY], [b], One, 0.5, "Should be |->", 1e-5 ); 90 | Reset(b); 91 | Message("Test passed."); 92 | } 93 | 94 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 95 | @Test("QuantumSimulator") 96 | operation StateMinusZTest() : Unit { 97 | use (a,b) = (Qubit(),Qubit()); 98 | StateMinus(b); 99 | AssertMeasurement([PauliZ], [a], Zero, "Should not be changed. Still be |0>"); 100 | AssertMeasurementProbability([PauliZ], [b], One, 0.5, "Should be |->", 1e-5 ); 101 | Reset(b); 102 | Message("Test passed."); 103 | } 104 | 105 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 106 | @Test("QuantumSimulator") 107 | operation StateIXTest() : Unit { 108 | use (a,b) = (Qubit(),Qubit()); 109 | StateI(b); 110 | AssertMeasurementProbability([PauliX], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 111 | AssertMeasurementProbability([PauliX], [b], One, 0.5, "Should be |i>", 1e-5 ); 112 | Reset(b); 113 | Message("Test passed."); 114 | } 115 | 116 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 117 | @Test("QuantumSimulator") 118 | operation StateIYTest() : Unit { 119 | use (a,b) = (Qubit(),Qubit()); 120 | StateI(b); 121 | AssertMeasurementProbability([PauliY], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 122 | AssertMeasurement([PauliY], [b], Zero, "Should be |i>"); 123 | Reset(b); 124 | Message("Test passed."); 125 | } 126 | 127 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 128 | @Test("QuantumSimulator") 129 | operation StateIZTest() : Unit { 130 | use (a,b) = (Qubit(),Qubit()); 131 | StateI(b); 132 | AssertMeasurement([PauliZ], [a], Zero, "Should not be changed. Still be |0>"); 133 | AssertMeasurementProbability([PauliZ], [b], One, 0.5, "Should be |i>", 1e-5 ); 134 | Reset(b); 135 | Message("Test passed."); 136 | } 137 | 138 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 139 | @Test("QuantumSimulator") 140 | operation StateMinusIXTest() : Unit { 141 | use (a,b) = (Qubit(),Qubit()); 142 | StateMinusI(b); 143 | AssertMeasurementProbability([PauliX], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 144 | AssertMeasurementProbability([PauliX], [b], One, 0.5, "Should be |-i>", 1e-5 ); 145 | Reset(b); 146 | Message("Test passed."); 147 | } 148 | 149 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 150 | @Test("QuantumSimulator") 151 | operation StateMinusIYTest() : Unit { 152 | use (a,b) = (Qubit(),Qubit()); 153 | StateMinusI(b); 154 | AssertMeasurementProbability([PauliY], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 155 | AssertMeasurement([PauliY], [b], One, "Should be |-i>"); 156 | Reset(b); 157 | Message("Test passed."); 158 | } 159 | 160 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 161 | @Test("QuantumSimulator") 162 | operation StateMinusIZTest() : Unit { 163 | use (a,b) = (Qubit(),Qubit()); 164 | StateMinusI(b); 165 | AssertMeasurement([PauliZ], [a], Zero, "Should not be changed. Still be |0>"); 166 | AssertMeasurementProbability([PauliZ], [b], One, 0.5, "Should be |-i>", 1e-5 ); 167 | Reset(b); 168 | Message("Test passed."); 169 | } 170 | 171 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 172 | @Test("QuantumSimulator") 173 | operation StateOneXTest() : Unit { 174 | use (a,b) = (Qubit(),Qubit()); 175 | StateOne(b); 176 | AssertMeasurementProbability([PauliX], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 177 | AssertMeasurementProbability([PauliX], [b], One, 0.5, "Should be |1>", 1e-5 ); 178 | Reset(b); 179 | Message("Test passed."); 180 | } 181 | 182 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 183 | @Test("QuantumSimulator") 184 | operation StateOneYTest() : Unit { 185 | use (a,b) = (Qubit(),Qubit()); 186 | StateOne(b); 187 | AssertMeasurementProbability([PauliY], [a], One, 0.5, "Should not be changed and still be |0>", 1e-5 ); 188 | AssertMeasurementProbability([PauliY], [b], One, 0.5, "Should be |1>", 1e-5 ); 189 | Reset(b); 190 | Message("Test passed."); 191 | } 192 | 193 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 194 | @Test("QuantumSimulator") 195 | operation StateOneZTest() : Unit { 196 | use (a,b) = (Qubit(),Qubit()); 197 | StateOne(b); 198 | AssertMeasurement([PauliZ], [a], Zero, "Should not be changed. Still be |0>"); 199 | AssertMeasurement([PauliZ], [b], One, "Should be |1>"); 200 | Reset(b); 201 | Message("Test passed."); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /test/ZTest.qs: -------------------------------------------------------------------------------- 1 | namespace ChpSimulator.Test { 2 | open Microsoft.Quantum.Canon; 3 | open Microsoft.Quantum.Diagnostics; 4 | open Microsoft.Quantum.Intrinsic; 5 | 6 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 7 | @Test("QuantumSimulator") 8 | operation ZRotateHXQubit () : Unit { 9 | use q = Qubit(); 10 | H(q); //|+> 11 | Z(q); //|-> 12 | AssertMeasurement([PauliX], [q], One, "Should be |->"); 13 | Reset(q); 14 | Message("Test passed."); 15 | } 16 | 17 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 18 | @Test("QuantumSimulator") 19 | operation ZRotateHYQubit () : Unit { 20 | use q = Qubit(); 21 | H(q); //|+> 22 | Z(q); //|-> 23 | AssertMeasurementProbability([PauliY], [q], One, 0.5, "Should be |->", 1e-5 ); 24 | Reset(q); 25 | Message("Test passed."); 26 | } 27 | 28 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 29 | @Test("QuantumSimulator") 30 | operation ZRotateHZQubit () : Unit { 31 | use q = Qubit(); 32 | H(q); //|+> 33 | Z(q); //|-> 34 | AssertMeasurementProbability([PauliZ], [q], One, 0.5, "Should be |->", 1e-5 ); 35 | Reset(q); 36 | Message("Test passed."); 37 | } 38 | 39 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 40 | @Test("QuantumSimulator") 41 | operation ZRotateXQubit () : Unit { 42 | use q = Qubit(); 43 | Z(q); //|0> 44 | AssertMeasurementProbability([PauliX], [q], One, 0.5, "Should be |0>", 1e-5 ); 45 | Reset(q); 46 | Message("Test passed."); 47 | } 48 | 49 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 50 | @Test("QuantumSimulator") 51 | operation ZRotateYQubit () : Unit { 52 | use q = Qubit(); 53 | Z(q); //|0> 54 | AssertMeasurementProbability([PauliY], [q], One, 0.5, "Should be |0>", 1e-5 ); 55 | Reset(q); 56 | Message("Test passed."); 57 | } 58 | 59 | @Test("QSharpCommunity.Simulators.Chp.StabilizerSimulator") 60 | @Test("QuantumSimulator") 61 | operation ZRotateZQubit () : Unit { 62 | use q = Qubit(); 63 | Z(q); //|0> 64 | AssertMeasurement([PauliZ], [q], Zero, "Should be |0>"); 65 | Reset(q); 66 | Message("Test passed."); 67 | } 68 | } 69 | --------------------------------------------------------------------------------