From 5a45d1b3522f3161f1e73b5cebf72e94be82eb9f Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Wed, 27 Nov 2024 01:53:28 +0000 Subject: [PATCH] build based on ee452ab --- dev/.documenter-siteinfo.json | 2 +- dev/benchmarks.html | 2 +- dev/dev/index.html | 2 +- .../examples/1.prepare-ghz-state/index.html | 152 ++++---- .../2.qft-phase-estimation/index.html | 130 +++---- .../examples/3.grover-search/index.html | 46 ++- .../examples/4.shor-algorithm/index.html | 2 +- .../examples/5.shor-9-code/index.html | 2 +- .../6.quantum-circuit-born-machine/index.html | 342 +++++++++--------- .../index.html | 2 +- .../8.riemannian-gradient-flow/index.html | 60 +-- dev/index.html | 2 +- dev/man/automatic_differentiation.html | 2 +- dev/man/bitbasis.html | 2 +- dev/man/blocks.html | 112 +++--- dev/man/cuda.html | 2 +- dev/man/plot.html | 8 +- dev/man/registers.html | 76 ++-- dev/man/simplification.html | 6 +- dev/man/symbolic.html | 4 +- dev/man/yao2einsum.html | 2 +- dev/notes.html | 2 +- dev/performancetips.html | 2 +- dev/quick-start.html | 2 +- dev/search_index.js | 2 +- 25 files changed, 481 insertions(+), 485 deletions(-) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 77950ede..beca528d 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-24T04:55:52","documenter_version":"1.8.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-27T01:53:21","documenter_version":"1.8.0"}} \ No newline at end of file diff --git a/dev/benchmarks.html b/dev/benchmarks.html index 2c6fb1e3..037e8f20 100644 --- a/dev/benchmarks.html +++ b/dev/benchmarks.html @@ -1,2 +1,2 @@ -Benchmarks · Documentation | Yao

Benchmarks

Benchmark Guard

To ensure some PR do not contain performance regression, we defined package benchmarks with PkgBenchmark in each component package, you can run the benchmark suite and compare the performance between different version and commits.

Benchmark with Other Packages

We also provide benchmarks comparing to other packages, you can find a complete benchmark results here: quantum-benchmarks

a glance of Yao's benchmark comparing to other packages:

relative-gate

relative-circuit

+Benchmarks · Documentation | Yao

Benchmarks

Benchmark Guard

To ensure some PR do not contain performance regression, we defined package benchmarks with PkgBenchmark in each component package, you can run the benchmark suite and compare the performance between different version and commits.

Benchmark with Other Packages

We also provide benchmarks comparing to other packages, you can find a complete benchmark results here: quantum-benchmarks

a glance of Yao's benchmark comparing to other packages:

relative-gate

relative-circuit

diff --git a/dev/dev/index.html b/dev/dev/index.html index 235caf9d..06620c40 100644 --- a/dev/dev/index.html +++ b/dev/dev/index.html @@ -1,2 +1,2 @@ -Developer Notes · Documentation | Yao

Developer Notes

Overview of the Architecture

The following is an overview of the entire ecosystem, where Yao and CuYao are two meta-packages.

stack

The role of QBIR

Currently the main functionality is built on the Quantum Block Intermediate Representation (QBIR). A quantum program is defined by QBIR and then interpreted to different targets, such as different simulation backend or matrix representation.

framework

+Developer Notes · Documentation | Yao

Developer Notes

Overview of the Architecture

The following is an overview of the entire ecosystem, where Yao and CuYao are two meta-packages.

stack

The role of QBIR

Currently the main functionality is built on the Quantum Block Intermediate Representation (QBIR). A quantum program is defined by QBIR and then interpreted to different targets, such as different simulation backend or matrix representation.

framework

diff --git a/dev/generated/examples/1.prepare-ghz-state/index.html b/dev/generated/examples/1.prepare-ghz-state/index.html index 67b7cb2a..b7cd852a 100644 --- a/dev/generated/examples/1.prepare-ghz-state/index.html +++ b/dev/generated/examples/1.prepare-ghz-state/index.html @@ -73,91 +73,91 @@ bar(hist.edges[1] .- 0.5, hist.weights, legend=:none) - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -

GHZ state will collapse to $|0000⟩$ or $|1111⟩$.


This page was generated using Literate.jl.

+

GHZ state will collapse to $|0000⟩$ or $|1111⟩$.


This page was generated using Literate.jl.

diff --git a/dev/generated/examples/2.qft-phase-estimation/index.html b/dev/generated/examples/2.qft-phase-estimation/index.html index 311b1741..6514a858 100644 --- a/dev/generated/examples/2.qft-phase-estimation/index.html +++ b/dev/generated/examples/2.qft-phase-estimation/index.html @@ -93,72 +93,72 @@ phases = rand(1<<M) phases[0b010+1] = θ U = P * Diagonal(exp.(2π * im * phases)) * P'
32×32 Matrix{ComplexF64}:
-    0.246399+0.115208im       0.0861315-0.143743im      -0.198112+0.136464im      0.0676113-0.0440561im   0.00983366-0.022845im       -0.0856452+0.363304im     -0.0386727-0.0284968im    -0.0449702-0.0235183im   -0.0869103-0.0397107im     0.0434723+0.0664853im     -0.124813+0.210515im      -0.0278408+0.0402997im        0.234717-0.0639829im      0.161881-0.015782im     -0.114625-0.14776im      -0.0353109+0.154731im       0.0146657-0.031926im      -0.102381-0.0918771im      0.233505+0.0350168im     -0.176102+0.0567858im     0.0377062-0.169042im    -0.0300664+0.348562im    -0.0758468-0.0166647im     -0.225628+0.0873245im    -0.0441154+0.218237im     0.0389638-0.0595369im    -0.165446+0.0116461im      0.152713-0.10042im     -0.0449934+0.0157762im     -0.0726893-0.0524538im    0.0729676+0.0690124im    0.00613757+0.0458347im
-     0.16796-0.0610965im       0.123476+0.16497im     -0.00601311-0.0422473im    -0.0023416-0.0850796im     -0.19318+0.0253683im      -0.0375928+0.210454im    -0.00376374+0.0355531im    -0.0373398+0.113978im    -0.0422534-0.0941257im     -0.224495-0.0673913im      -0.10086-0.0662432im      0.0983835-0.248966im       -0.0438732+0.0702543im   -0.00615178+0.182882im     -0.112288-0.125177im       0.258248-0.081549im       -0.203199-0.0811951im    0.00733711+0.130874im      0.0496601-0.0228924im     -0.151974-0.204323im     -0.0507104+0.0384323im     0.074441-0.0567563im    -0.149172-0.182131im    -0.00203453+0.119221im     -0.0995078-0.201756im      -0.17335-0.196183im     0.0171555+0.0340969im     -0.185607-0.0580839im   -0.0833827-0.0327391im   -0.000526364+0.216728im     -0.253983+0.129422im      0.0838458+0.0797968im
-   -0.148659+0.106148im      -0.0644724+0.0581801im       0.24327+0.078323im       0.146871-0.245547im     -0.138629+0.0117933im        0.212922+0.263887im     -0.0259914+0.0575505im   -0.00489541-0.0110281im   -0.0833667+0.0153164im      0.102374-0.127931im      0.0452629-0.0449734im      0.0971992-0.0463612im      -0.0952327+0.0297361im    -0.0266881-0.00447228im   0.0325743-0.0548712im     0.0360851+0.108762im        0.148414+0.0651243im      -0.18117-0.199183im       0.146558+0.112261im     -0.0737488+0.212265im     -0.0735675-0.123558im    -0.0638914-0.10077im      0.0799929+0.070165im        0.11489-0.119058im      -0.168977-0.241228im     0.0781235-0.0387043im    0.0829247-0.127486im       0.177619+0.23761im     -0.0993804+0.26946im       -0.0524406+0.0529975im   -0.0668787+0.180681im      -0.083678-0.0355198im
-   -0.119084+0.0991857im       0.121995-0.081709im     -0.0357291+0.0280413im       0.14611+0.0780467im    -0.132363+0.0426292im      -0.0306435+0.217958im     -0.0775165-0.116055im      -0.115431-0.0384844im     0.144577-0.0491073im    -0.0891247-0.0448591im    0.00710907-0.207806im         0.13085+0.0740405im        0.282064+0.0509758im      0.102853+0.00372252im    0.225532+0.188891im      0.0364058-0.000538922im   -0.0720639+0.0238915im     -0.127577+0.169173im     -0.0574907-0.13933im       -0.107577+0.160773im     -0.0382275+0.142244im     0.0327876-0.0938574im    -0.142591+0.0194514im    -0.0538919-0.103967im     -0.0343362+0.043592im    -0.0808006-0.19531im       0.225437+0.260364im       0.102668+0.143748im      0.153638+0.0865013im       0.099781-0.0466031im     0.113398-0.327538im      0.0392191+0.0621532im
-  -0.0411711+0.169088im      -0.0312233+0.0588672im     0.0865952-0.14781im      -0.0853417-0.0697271im    -0.182351+0.167883im        -0.120774-0.0113786im     -0.226754+0.0137001im      0.293591-0.125606im      0.224114-0.13371im        0.138643+0.0299386im      0.020981-0.116074im       -0.126666+0.0400986im      -0.0271384-0.188502im      0.0396068-0.0761467im   -0.0706592-0.124335im      -0.124904-0.105755im        -0.22956-0.0178971im    -0.0140893+0.156223im       0.129346-0.00514352im    -0.127279+0.0575825im      0.197929+0.224967im     0.0317844+0.0976812im     0.108955-0.0303738im     0.0666847+0.20649im        0.171007-0.00647896im   0.0937147+0.0754688im    0.0843849-0.055534im      0.0441968+0.0239783im   -0.0922496+0.17702im        -0.137695+0.206176im        0.1487+0.0246492im    -0.0560542+0.160017im
-    0.109968+0.0394175im     -0.0830804-0.0470226im      0.121912-0.0619607im    -0.0900856+0.163182im     -0.125972+0.0994022im        0.256925-0.00307899im    0.0342044-0.389207im     -0.0716208+0.0480144im    0.0554961-0.233163im    -0.00144207+0.0868779im      0.116934-0.0454155im     -0.0246943+0.166195im       0.00112034+0.110519im      -0.247562+0.0461467im   -0.0581914+0.00218358im     0.121263-0.0386456im     -0.0335353+0.211296im   -0.000853082-0.104091im       0.200132+0.206724im      0.0381027-0.14361im        0.325335+0.0296094im     0.121758-0.0281094im    0.0138559+0.163503im      -0.129711-0.0316801im     0.0423435-0.0367509im   -0.0619309-0.0560742im    -0.134946+0.195983im       0.125273-0.0353591im   -0.0158086-0.0270277im         0.1439-0.0768224im   -0.0986002+0.0590315im     -0.118503+0.025893im
-   -0.218482+0.244581im       0.0857028+0.0464688im     0.0483433+0.0607406im     0.0275629+0.035747im     -0.142279+0.065234im        0.0868086+0.0547387im     0.0598023+0.0814029im     -0.111274+0.289051im    0.00241954-0.0952305im     -0.146541-0.0269435im   -0.00817482-0.0179894im      -0.104012+0.083169im       -0.0602822-0.156738im     -0.0464365+0.17539im       0.175257-0.0771357im     -0.158425-0.0842796im       0.162799-0.0461627im     0.0406705-0.0226552im     -0.173234-0.0919546im      0.119544-0.0344104im      0.115018-0.205185im      0.168068+0.244478im      0.240908-0.0686859im     0.0832269-0.069827im     -0.0179103+0.13446im      -0.199874-0.0383416im    -0.171432+0.142273im      -0.121577+0.0968507im    -0.186287-0.00358247im   -0.00795114+0.156422im        0.1593+0.0185493im       0.18028+0.0245006im
- -0.00825948+0.194238im        0.104895+0.0615852im     0.0541992+0.167895im       0.069928-0.0201921im    0.0663814-0.000600553im     -0.114773-0.14059im       -0.235851+0.0953884im    0.00725011-0.0672694im    -0.132733+0.136069im      -0.128576+0.323116im      0.0596167-0.0223914im     -0.0197523-0.138358im       -0.0567612-0.0326774im     0.0338968-0.138521im      0.109748+0.0251123im      0.173136-0.0678938im     0.00720967+0.0212567im    -0.0235103-0.229829im     -0.0822271-0.00670776im   -0.0311485-0.0253625im     0.0407973+0.215779im      0.175701+0.0833429im    0.0684339+0.145483im     -0.0248855-0.109938im     -0.0102857-0.101376im      0.266523-0.148169im    -0.0291877+0.144953im      0.0981536-0.253037im     0.0136103+0.121627im        0.174576+0.003433im    -0.0614501+0.136001im       0.311164+0.0379198im
-   0.0191999-0.19979im         0.153516-0.105532im     -0.0431503+0.0756041im      0.333335-0.0336627im    0.0740475+0.10573im        0.00261597-0.0818076im    -0.0572133-0.176289im     -0.0238131-0.0626657im    0.0909446+0.176055im      -0.110144-0.226535im       0.182583+0.066994im        -0.14452+0.115765im         0.132216-0.0404625im    -0.0895741-0.0324275im   -0.0482188-0.303248im     -0.0687959-0.15461im       -0.0825549-0.390684im      0.0758276+0.0921496im        0.0397-0.00112144im     0.111894-0.0179667im      0.160834-0.119729im    -0.0825548-0.0816734im    -0.051251+0.0957145im     0.0984195+0.00469741im    -0.010582-0.205482im    0.00753621-0.0780781im   -0.0989124-0.0641076im      0.139693-0.0233733im   -0.0683541+0.126776im          0.1319-0.00259519im   0.0261646-0.0483438im      0.147536-0.091449im
-   0.0540371-0.0399724im      -0.101646-0.0215275im    -0.0494322+0.0101189im      -0.16471+0.0589449im    0.0653499+0.0506819im        0.137384-0.063im         -0.127687+0.167022im        -0.1482+0.0706257im   -0.0570145-0.211616im       0.113436+0.101341im     0.00763758-0.146785im       -0.191184+0.0877731im        0.393574+0.10476im        -0.17402-0.0664512im    0.0944271-0.161462im        0.10138+0.00512648im     0.0165576-0.115423im        0.22857-0.130099im      0.0409037+0.0252593im    -0.0532475+0.182042im      -0.202728+0.100161im     -0.173929+0.00671358im  -0.0427966-0.219826im       0.053885-0.1612im        0.0800672-0.0858484im    0.0391727+0.0215373im   -0.0706505+0.160772im      -0.154152-0.0764im       -0.108233+0.18675im        -0.123983+0.121617im    -0.0475619-0.0342323im    -0.0458498-0.16667im
-   -0.079444+0.126137im      -0.0242278-0.145736im       0.136371+0.0991748im     0.0899638+0.320271im    -0.0353351-0.0124055im        0.131787-0.00122841im    -0.107992+0.0782152im      0.288242+0.0340569im    0.0700197-0.114295im       0.098366+0.0243686im     0.0397831-0.0268942im       0.108358-0.274857im       -0.0148326+0.0800494im      0.128908+0.182113im     -0.068434-0.274679im     -0.0197431+0.230266im      -0.0413242+0.0663491im     0.0216366-0.0490989im     0.0313749-0.216863im       0.170652-0.00931152im    0.0268023+0.0761323im    -0.149233-0.117166im     -0.148772+0.0675043im      0.144837+0.0727456im    -0.0107186+0.0312661im    0.0672773-0.206589im     -0.278924+0.00387544im    -0.128359+0.0401332im    0.0955943-0.0704476im     -0.0479466-0.166923im     0.0900072-0.0195578im     0.0477889-0.0857932im
-   -0.050652+0.190509im        0.102154-0.105646im      -0.039637+0.0208232im     0.0714695+0.00107605im    0.180342-0.071763im       -0.0988715+0.0239407im    -0.0822772-0.164621im       0.173504+0.148014im      -0.17524-0.162328im     0.00282644-0.0263106im      0.401823+0.137706im      -0.0721877+0.16477im        -0.0832405+0.0436727im    -0.0650249+0.0379257im   -0.0769615-0.0292433im       0.22042-0.0509278im      0.0540968+0.163944im      0.0824217+0.239816im       -0.13352+0.00870519im   -0.0848638+0.170389im     -0.0845903+0.0457847im   -0.0179843+0.144339im     0.0174489-0.107914im      -0.143648-0.0879369im     -0.030113-0.25179im     -0.0690046-0.0759703im    0.0861226-0.159425im     -0.0352599+0.0245793im     0.196568-0.15527im        -0.153801+0.0382229im     0.145497+0.120395im     0.00384587-0.0590552im
-   0.0573482-0.199634im       0.0872603-0.191566im      -0.132362-0.0537182im    -0.0788465-0.122757im      -0.14957-0.0820847im       0.0512138-0.180353im     -0.0217253+0.0408783im      0.227102-0.132967im      0.186324+0.0729179im      0.133807-0.0517452im   0.000644708+0.2407im         0.0993075+0.0929215im        0.079766+0.125668im      0.0331942+0.205282im      0.146053-0.0116547im    -0.0710787+0.0863424im      0.0141167+0.185343im       0.120975-0.116886im      -0.074682+0.232677im       0.136322+0.00797441im   -0.0948451-0.0244149im  -0.00546557+0.0797604im    0.0831274+0.092279im     -0.0239354+0.00493699im   -0.0495475-0.0259856im    -0.177441-0.200944im     0.0780158+0.143968im      0.0168017-0.00468514im     0.11645+0.160955im       -0.175712+0.202959im     -0.113794+0.0346542im      0.251644+0.185572im
-  -0.0502284+1.58897e-5im       0.14789-0.322592im       0.339092-0.0548708im     -0.105481-0.017207im      0.269176-0.106449im        0.0976986+0.0352348im      0.139207+0.156366im     0.00709297-0.0390716im    0.0865243+0.0881061im     0.0461906-0.0768591im     0.0229325-0.0145152im    -0.00185575+0.0799847im      -0.0459292-0.132619im      0.0322643+0.144326im     0.0729162-0.0498243im      0.140111-0.0633848im      0.0728301+0.0336045im     0.0102096-0.0230397im      0.210762-0.00334431im    -0.201121-0.148368im      0.0501612+0.0876101im    -0.128412+0.116264im    -0.0925291-0.209329im       0.186195-0.113492im      0.0262794-0.0771323im   -0.0089263+0.100354im      0.100752+0.0861456im      0.103392-0.0936241im    -0.175485-0.172753im       0.0543343-0.12468im     -0.0047802-0.114703im       0.123388+0.288531im
-   0.0139094-0.0584252im    -0.00757593-0.150255im       0.175032-0.0536521im      0.105135-0.0576504im   -0.0881678+0.173119im         -0.24199-0.0906749im    -0.0829842+0.0769881im    -0.0756951-0.0337848im   -0.0529265+0.124291im      0.0308069-0.0813712im     0.0186158-0.0417193im      -0.129662-0.107954im       -0.0218168-0.131368im     -0.0644895+0.110784im      0.109548-0.0215239im     -0.057847+0.195414im        0.152255+0.0915778im      0.157401+0.40532im        0.189542+0.101682im      -0.029273+0.0712376im    -0.0491036-0.0134692im      0.26156+0.0224791im    -0.182286+0.112693im     -0.0981886-0.253613im      -0.045461+0.0979992im     0.103884+0.107492im     -0.192841+0.103427im      -0.183389+0.0650292im    0.0829547+0.0690902im      0.0114791-0.0341736im    -0.184028+0.111288im      -0.110049+0.042644im
-   -0.055825-0.151455im      -0.0495828+0.273837im       0.280883-0.0906726im      -0.10011+0.131917im      -0.19434-0.0732926im       0.0849296+0.1057im        0.0486464-0.0800563im      0.108622-0.26247im     -0.0557833+0.0017824im    -0.0572038+0.124323im      -0.114735+0.0513731im      -0.131688+0.0149347im        0.234981-0.121747im     -0.0216311+0.13239im      0.0201432-0.0955147im    -0.0345766+0.048358im      0.00752781+0.0324864im      0.237612+0.118321im     -0.0755963+0.0286757im     0.0112769-0.10268im       -0.208515-0.17301im       0.125176+0.206613im     0.0659153-0.0275678im    -0.0294005+0.0233494im    -0.0679253-0.148363im      0.185571-0.133711im      0.206778-0.0918056im      0.100198-0.0236701im     0.015891-0.099655im        0.119469-0.196639im      0.156668-0.0222412im      0.047338-0.128329im
-   0.0909537-0.188131im      -0.0112806+0.0219909im    -0.0950594-0.0594047im     0.0338686-0.0280672im    -0.232965+0.0726812im    -0.000955704+0.0141779im    -0.0583341+0.0575472im      0.108165+0.168218im     -0.011769+0.162124im       -0.30753-0.0868438im    -0.0988916-0.118911im       -0.255962+0.200681im        -0.156783-0.0175783im      0.196463-0.100165im      0.222489-0.0905517im    -0.0787529-0.00222162im   0.000916109+0.302242im      -0.172954-0.150774im       0.178685-0.0364154im     0.0365579+0.0267688im    -0.0193775+0.0376919im   -0.0553593+0.0238895im   -0.0783808-0.0966653im     0.0409791-0.0425241im     0.0987954-0.232924im     0.0503972+0.0335411im   -0.0909847+0.0770229im     0.0677088-0.10567im       0.128862-0.224196im       -0.159193-0.0210854im    0.0519906-0.0680011im    -0.0247202-0.192697im
-  -0.0909398+0.010935im       -0.152592+0.250483im     -0.0133428+0.0444147im     0.0567861-0.156624im    -0.0185105+0.142465im       -0.0632694-0.0176021im       0.15011+0.00359879im    -0.180614-0.053235im     -0.202341+0.0700556im      0.125271+0.155812im       0.185384+0.189925im        0.131295-0.093913im        -0.143644+0.100106im      0.0437891+0.134654im     0.0994682-0.197779im      0.0728782-0.17979im        -0.284307+0.177088im      0.0523936+0.104184im       0.195965+0.101421im       0.171653+0.0860191im     0.0378977-0.0593154im    -0.169543-0.00190702im   -0.123045-0.00146224im   -0.0234015-0.0501442im    -0.0463323+0.1257im       0.0668319+0.0616657im    0.0577525+0.17378im     -0.00447686-0.0457088im    -0.127451-0.020551im       -0.108567+0.0217589im      0.20187-0.258367im       0.107049-0.00745235im
-  -0.0348499+0.0923505im      0.0988152-0.106424im       0.184793-0.0171527im    -0.0426597+0.0426772im     0.218196-0.200778im        -0.112414-0.167694im     -0.0190429-0.223205im      -0.138674-0.00198107im   0.0661357-0.0709395im     -0.100291-0.0729509im     -0.294443+0.18731im        0.0197352-0.202861im        0.0249217+0.0281209im      0.189338-0.104234im     0.0320579-0.0916965im   0.000835118-0.110631im      -0.0303145+0.0476351im     0.0617147-0.0117683im      0.112597+0.0981421im      0.062024+0.304466im    -0.00809107-0.0648226im     0.158126-0.0105891im     0.173008-0.0317465im     0.0978995+0.235157im      -0.157302-0.186482im     0.0468267-0.00325617im   -0.040492+0.239275im     -0.0273387+0.0431516im    0.0235296-0.0665848im     0.00539531+0.16982im      0.0147705-0.0835929im     -0.227596-0.088263im
-   -0.224333+0.244535im        0.108232-0.103982im     -0.0994016-0.119106im      0.0395846-0.011828im     -0.237994-0.0789439im        0.147468+0.0120893im    -0.0313771+0.0982868im    -0.0961739+0.0680115im   0.00994819+0.188027im       0.309188+0.00874504im   -0.0602879+0.073135im      -0.0562858+0.0502045im        0.173356+0.0637386im    -0.0188633+0.0888709im    -0.142519+0.123831im      0.0375707+0.125304im       -0.158237-0.0557604im    0.00606706+0.0796417im    -0.0389245-0.0994397im     0.0387042-0.0474221im     0.0935646-0.108884im     0.0497505-0.130329im    -0.0524652+0.0109126im    -0.0540532+0.0339429im    -0.0413771-0.174335im      0.175465+0.300107im     0.0158164+0.116026im       0.133445-0.151087im     0.0550901-0.29519im         0.012542+0.229261im    -0.0876942+0.0785984im     0.0985916-0.144526im
-  -0.0139253+0.0965011im       0.179388+0.168283im     -0.0380669+0.00053168im     0.158268-0.119313im      0.101908-0.168429im         0.190466-0.00672237im     0.187807+0.0368547im     0.0505541-0.0479054im    0.0473419-0.133432im      -0.131485+0.0686393im      0.142036-0.0650757im    -0.00202326-0.00701474im        0.13726+0.00234529im     0.228481-0.112275im      0.166765+0.151406im     -0.0681252+0.191845im      0.00291767-0.0925826im      0.139035+0.00307994im     0.189291+0.0842448im      0.203493-0.111019im       0.246958-0.050584im     0.0936853-0.0215174im     -0.18434-0.0114964im     0.0667232-0.0193481im   -0.00377148-0.0685544im   -0.0309626+0.0663129im     0.185095-0.00939594im    -0.252225-0.224067im     0.0672401+0.129682im        -0.15224-0.0481296im     0.145919+0.204586im      -0.148599+0.0612267im
-      -0.111+0.00185716im     0.0183194-0.209138im      -0.145383+0.0359496im    -0.0447248+0.0657203im    0.0481522+0.0655221im       0.0352629+0.0185434im    0.00461384+0.0384965im     -0.008569+0.00907578im  -0.0725395+0.175071im      -0.306535-0.148731im      -0.137599-0.0573333im   -0.000303966-0.164244im         0.221433+0.0559428im     -0.208688+0.0201532im    -0.289809-0.0830846im      0.119796+0.075052im      -0.0486589+0.228861im     -0.0918122+0.000465152im  -0.0365312+0.178486im       0.134622-0.0181517im      0.111615+0.0672834im     0.219562-0.12816im       0.138879-0.0789607im    -0.0455837-0.0695079im     0.0512937+0.0396625im      0.14619+0.0709107im     0.172514-0.103924im     -0.0760365+0.0415955im    -0.176813+0.101641im        -0.26573-0.128569im      0.213663-0.048746im      0.0953102+0.0584248im
-    0.129162+0.00903411im     0.0537329+0.0845465im     -0.056601-0.234633im       -0.15065+0.0508945im     0.119979-0.152216im       0.00589601+0.0195961im     -0.132577-0.0795668im    -0.0559293+0.0293989im   -0.0802859+0.215388im      -0.138251+0.116731im      0.0361008-0.0597893im       0.190458+0.0966015im        0.018113-0.155635im     -0.0132462+0.129992im    -0.0128454-0.0562541im     0.0560443+0.249872im      0.00769413-0.0412807im    -0.0629099+0.141809im      0.0404674+0.151559im     -0.0823857+0.103801im       0.118061+0.0241724im    -0.142899+0.00448431im   0.0198819+0.218752im       0.368534-0.117027im       0.162318+0.194545im    -0.0226534-0.170929im      0.104065+0.0259149im     0.0167498+0.0705985im   -0.0796063-0.126448im       0.0181523+0.230722im     0.0526977+0.125236im   -0.000493651-0.267244im
-  -0.0924097-0.0254711im     -0.0797988-0.0430704im     -0.181131-0.0816909im    -0.0959639-0.0539285im     0.119816-0.0204191im       -0.077525+0.0882936im      0.147091+0.189697im       0.153756+0.0649431im   -0.0593422-0.131588im      0.0273435+0.0415793im      0.120013-0.00167919im    -0.0764965+0.000585074im      0.202543+0.0746687im     0.0970817+0.201384im      0.170524-0.140043im       0.142674-0.257162im      -0.0711371-0.0246601im     -0.144761-0.0125861im    -0.0616536+0.000151421im  -0.0740926-0.0781648im   -0.00882759-0.138198im      0.370663-0.074481im     0.0259084+0.239208im       0.289848-0.0483007im     0.0102887+0.0554238im     0.100484-0.0337917im    -0.108909-0.126453im       0.180803-0.0749299im      0.11542+0.00713212im    -0.0565438-0.0084237im    -0.128518-0.107975im       -0.25792+0.0339874im
-  -0.0406844-0.000147317im    -0.193574-0.0918962im     -0.126698+0.0577254im      0.150173-0.396646im    -0.0174129-0.043293im         0.119437-0.178904im      0.0674022-0.112609im     -0.0979556+0.0297779im    -0.141475-0.020219im      0.0448505+0.10109im      -0.0963694+0.00125643im     -0.160219+0.0278807im       0.0542284+0.197358im      0.0750871+0.270072im    -0.0383968-0.019684im      -0.159117+0.193544im      0.00566964-0.0278226im    -0.0437641+0.0204283im     0.0955525-0.088518im     -0.0691174+0.0755324im     0.0544526+0.293767im      0.100581+0.0834105im     0.140149-0.0847328im      0.054995+0.0516292im      0.152446-0.0806191im    0.0358423-0.203981im     0.0406591-0.16628im       -0.152606+0.0524849im   -0.0554093-0.136357im        0.294126-0.0359238im    0.0150783-0.085809im     -0.0322387+0.0894548im
-   0.0838545+0.0596572im      0.0907975-0.0718174im     -0.180331+0.158126im      -0.244639-0.0522143im    -0.236711-0.111781im        0.0108681-0.0116062im      0.071047-0.006492im     -0.0700737-0.170117im     -0.130959+0.0482238im     -0.130612-0.0330045im      0.159661+0.102204im      -0.0454839-0.159969im         -0.16352-0.117985im      -0.115968+0.236403im    0.00962208-0.115521im     -0.0953596+0.0571619im       0.215922-0.0727523im      0.108317-0.00908456im    -0.152248-0.173536im      -0.206308-0.0163881im      0.185575+0.12899im      -0.123643-0.057563im     0.0413595+0.036389im      0.0150119+0.0989321im    -0.0685877-0.115464im    0.00610752+0.129427im      0.101465+0.2339im        0.0810435-0.0960397im    0.0780036+0.187088im      -0.0873071-0.123083im     0.0268459-0.11065im       -0.262579-0.0848718im
-  -0.0804216-0.0640584im      -0.231475-0.0416888im     -0.158296+0.054586im       0.080316+0.00768173im    0.185434-0.0442196im        0.186965-0.0337869im     -0.114666-0.148916im      -0.105006-0.0880889im    0.0758962+0.216463im       0.144788-0.0105231im    -0.0113967-0.105365im      0.00270317-0.118737im       -0.0819164-0.0394428im    -0.0156672-0.0999164im     0.192939-0.173403im     -0.0220602-0.0139616im     -0.0909423+0.158912im      0.0761903+0.0293675im      -0.17804-0.101197im     -0.0937912-0.217247im       0.118015-0.0564223im      0.13989+0.0757526im    -0.146652-0.402788im      0.0191285-0.014397im     -0.0821686+0.132117im      0.028754-0.149689im     0.0401564+0.0638644im      0.191798+0.120454im     0.0829508+0.0297715im     -0.0513289+0.11069im      0.0302614+0.266954im      -0.152014-0.0169309im
-    0.174019+0.000977413im   -0.0426375+0.189092im      0.0300682+0.0953503im      0.249566-0.0108428im    0.0526459+0.00755752im      -0.164625+0.0761199im      0.185122-0.272551im       0.200877+0.0168607im     0.191462+0.0996327im     0.0773934+0.0114866im     -0.111443-0.0620445im     -0.0500612+0.00610143im      0.0593711-0.0275213im     -0.228751+0.14151im       0.038849-0.0117087im      0.170634+0.152415im      -0.0179042+0.11324im        0.115927-0.15061im        0.037207-0.244673im     -0.0483138+0.174392im    -0.00825229+0.117378im     0.0901992-0.0374399im     0.147574-0.0540166im      0.209003-0.0973273im      -0.20663+0.14491im      -0.155354+0.268341im    0.00275939-0.0556093im     0.0273795-0.219287im     0.0358238+0.0154575im     -0.0451633+0.0594241im   -0.0125438-0.0315177im     0.0805916-0.0409553im
-    0.359376-0.0131582im     -0.0192176+0.0244827im      0.236022+0.0545508im      0.131126+0.0474973im   -0.0774407-0.00428585im     0.00311175-0.0550711im   -0.00155977+0.163218im      -0.324181+0.0831353im     0.130542+0.00111992im   -0.0799801+0.0632997im     0.0522911+0.199296im        0.307306+0.145403im         0.183931+0.142996im       0.127542+0.0345666im    -0.044672-0.0846018im     -0.164377-0.121301im      -0.0217663+0.12107im       0.0817232+0.0417787im    -0.0964679-0.170819im     -0.0732598-0.158873im     -0.0042093+0.203536im     0.0675209-0.026282im      0.116669+0.058133im      0.0522245-0.121065im      0.0578574-0.0966927im    0.0762098+0.159682im     -0.060895-0.127349im      0.0763242+0.139692im     0.0826329+0.00186995im     -0.138746+0.0455069im     0.143274+0.141064im     -0.0519939+0.0386522im
-   0.0870038-0.0875223im      0.0702945+0.00479946im   0.00713083-0.0894342im     0.0417068+0.120242im      0.144471-0.166711im       -0.0364888-0.0427515im     0.0522987+0.0880141im     -0.193614-0.100079im     0.0685945-0.0682857im    -0.0424375+0.148055im       0.185524-0.181671im       -0.224584+0.0650594im    -0.000955871-0.0849567im      0.100749+0.163144im      0.119262-0.146907im      0.0571436+0.257087im       -0.102709+0.230955im      -0.256044+0.0940386im     -0.181148-0.0701527im      0.140481+0.0748944im     -0.100838-0.0344099im   -0.0461878-0.116569im     0.0237763+0.05976im        -0.23081+0.256072im     -0.0768065-0.0814771im   -0.0674109+0.142843im    -0.0588395-0.0666886im     0.0911933+0.0122719im     -0.28412+0.143819im        0.116328+0.0845249im   -0.0242056+0.0592571im    0.00124992+0.0997216im
-  -0.0722651+0.0761015im      -0.266202+0.0716544im      0.033816-0.216709im      0.0125165+0.0973479im     0.124001-0.0122246im        0.136992+0.23464im       -0.204983+0.00443473im    0.0479561+0.0466829im   -0.0388153+0.272639im     -0.0414843-0.119823im     0.00571664+0.210474im     -0.00868335+0.015608im         0.055377+0.045611im       0.059208-0.0732571im     0.131628-0.0953025im     0.0468349+0.0890479im     -0.0323311+0.0260149im    -0.0189574-0.0271038im     -0.102445+0.112264im      -0.183772-0.1662im        0.0695717+0.0418411im   -0.0837738+0.0350011im     0.118528+0.120612im      -0.100088+0.00940298im   -0.0935212-0.112123im     -0.115101+0.162894im     -0.108778-0.044436im      -0.349654-0.131685im      0.145597+0.169812im        0.211873+0.0828583im    0.0822399-0.225841im     -0.0624968+0.115973im
-   0.0481034+0.188425im      -0.0954937-0.0831109im     -0.108609-0.227423im    -0.00941635-0.121653im    -0.0218926+0.202546im        -0.119508+0.0992936im       0.10763-0.171213im      -0.103646-0.0904178im     0.155566+0.166381im     0.00597553+0.210733im      0.0454735-0.0733411im       0.128804-0.154872im         0.130611-0.136942im      -0.102028+0.0496464im   -0.0593426-0.0307024im    -0.0276494-0.125097im          0.1438+0.0430549im    -0.0895733-0.134428im      -0.138237+0.0287126im        0.1731+0.11148im       -0.172403-0.119859im    -0.0576966+0.104055im     -0.198752-0.0321037im      0.178792+0.0956783im      0.245623-0.294565im    -0.0894609+0.0698549im   -0.0959155+0.0599082im      -0.11431+0.00199611im     0.10457-0.0301224im      0.0509387-0.141714im     0.0736154+0.151456im     -0.0260199+0.167709im

and then generate the state $ψ$

psi = P[:, 3]
32-element Vector{ComplexF64}:
-  -0.08065754143391692 - 0.055009647018866625im
-   0.19006121803300283 - 0.07786891844814922im
-   0.10110022848837084 + 0.07019692892627724im
-   0.17722982976443863 - 3.845725322671953e-5im
-  -0.01965030001833992 - 0.018323474940475915im
-  -0.10041019664527258 - 0.06352273584511699im
-  -0.06025107227379753 + 0.2575612552458329im
-  -0.15443054565693942 + 0.0019917822053837943im
-   0.07667187870643152 + 0.044896211808401865im
-   0.18294782047496447 - 0.04110999141545236im
-   0.17515170204754416 + 0.043903940534800054im
-   0.11186840537164285 + 0.08167480560292308im
-  -0.18075407116958775 - 0.08938572746357397im
- -0.039464158948234025 - 0.06466933278012425im
-    0.2852231150621538 + 0.0im
-   -0.0839802547795993 - 0.0029155308881749827im
-    0.1032627242838993 + 0.05789684051869745im
-  -0.16761915087686707 + 0.1108156023017131im
-   0.05761396772027127 + 0.06514431044253055im
-   0.11456529414242904 - 0.003252883543012841im
- -0.062438541544190033 + 0.21640509879312178im
-   0.12916447469420633 - 0.24475604890695543im
-  -0.04177599826076447 + 0.1254273927708512im
-   0.28367429245849807 - 0.012852699463165529im
-   0.21998147663298118 - 0.0185541567069078im
- -0.042575270237292684 - 0.0918044215109721im
-   0.03285829646287229 + 0.07661907321005776im
-   -0.2112250459206283 + 0.16668964049279222im
-   0.09308329474067217 - 0.03622190741744301im
- -0.007285875270852709 - 0.07696829040374963im
-   0.16109043351999203 - 0.039462393398074724im
-  0.023738989929819425 + 0.28377175482297445im

In the phase estimation process, we will feed the state to circuit and measure the first n qubits processed by iQFT.

r = join(ArrayReg(psi), zero_state(N))
+   0.231069-0.124897im      -0.159318+0.0678049im     -0.109712+0.141695im    0.0847892+0.162033im   -0.0529997-0.280835im      0.172669-0.0745698im     -0.216885+0.026518im     -0.0580405-0.0067957im      0.0647342-0.177247im      -0.127984-0.014022im      0.071481-0.0358391im   -0.0783292-0.00590271im   0.00948451+0.043865im       -0.103044-0.0348882im    -0.151377-0.144612im     -0.161714-0.0636987im    0.0870037+0.0435975im    -0.0520233+0.322786im     -0.0839893-0.123598im      0.0153757+0.115706im       0.318637+0.0704118im      0.0427751-0.156118im     0.0794182+0.0928219im     0.0259497+0.14972im       -0.165592-0.0969065im     0.0570424+0.0556543im     0.0467551-0.163814im      0.0316188+0.194294im     -0.0703532+0.147769im      0.0891742-0.0497962im      0.108643+0.0147681im     0.144715-0.102403im
+  -0.058111-0.0812229im      0.148117-0.143142im      0.0843076-0.0273008im   0.0277194+0.0167757im   0.0356299+0.0208306im   -0.0879315-0.15805im      0.00985965-0.151039im     -0.0947326-0.0566634im       0.209918-0.103424im     -0.0474578+0.194972im    -0.0728262-0.183996im     0.0766917+0.0319071im    -0.0985377-0.0978904im      0.0704881-0.0129605im   0.00186046+0.153872im      -0.17241+0.043201im    -0.0923571+0.056313im     -0.0393052+0.205074im      0.0957398-0.0203425im    -0.0416311-0.236891im      -0.154639+0.0156816im      -0.176536-0.0214645im   -0.0533325-0.0588524im     0.0370877-0.0818689im     -0.360819+0.0393942im      -0.29454+0.0777244im     0.0207988+0.143045im      -0.173983+0.164162im     -0.0232884-0.0808652im      0.106209-0.151237im      0.0199752-0.163312im      0.263275+0.123397im
+    0.11918+0.0401389im     0.0632876-0.152481im      0.0302847+0.0491605im   0.0992032+0.0580294im    -0.14872-0.0601375im     0.043148-0.0240589im    0.00843713-0.0764523im      0.127162+0.366275im        0.148484+0.0081261im   -0.00323696-0.157718im     -0.226579-0.115345im     0.0669543-0.0358321im    -0.0474922-0.000370193im    -0.231592-0.119565im     -0.141938-0.0189127im   -0.0621262+0.0761274im    0.0303281+0.0685024im     -0.117178-0.0786117im     -0.138292+0.07374im      -0.0243445+0.0754762im     -0.021191-0.253402im       -0.313574-0.0346956im    -0.295463+0.0741645im   -0.00290628-0.0427212im      0.137319-0.150436im      0.0737272-0.0659192im      0.190702-0.055586im     -0.0716622+0.0223049im      0.111282-0.192468im      0.0238268+0.103035im      -0.238655+0.0178775im    0.0664709-0.0659517im
+ -0.0828839-0.00571643im     0.194218+0.129812im       0.275577+0.0182396im  -0.0766899-0.212286im   -0.0939155-0.312516im      0.277758+0.243805im       0.096773+0.00622794im     0.130315+0.141979im      -0.0142943+0.0256142im     -0.175525-0.0704253im   -0.0845739+0.0366439im   -0.0997933-0.00662547im     0.077634-0.00720772im      0.108773+0.0863542im    0.0399352-0.161256im    -0.0172259-0.00177038im   -0.306212+0.0597572im    -0.0255365+0.0204491im       0.15075+0.029628im     0.00753932+0.0656115im      0.036078+0.0699073im     -0.0650548+0.0495985im   -0.0491948-0.0837742im     -0.215802+0.0291657im     -0.136501+0.296884im      0.0525335+0.0282891im     -0.200086-0.0406578im    -0.0349786+0.149876im      0.0389756-0.0507452im      0.120952+0.100177im     -0.0493837+0.0899093im    0.0458286-0.00951407im
+ -0.0346309-0.0160318im     -0.108916-0.234345im      0.0738414-0.0485784im   0.0555183+0.0575575im   0.0839359-0.0315061im    0.0195091-0.0637373im      0.191691+0.00965286im   0.00348661+0.0256095im       0.194977+0.155328im      0.0344283-0.0296855im     0.164463+0.0411953im    -0.354705+0.0264527im      -0.40388-0.0943971im     -0.0526439+0.00907454im  -0.0515824+0.0604217im     0.165575-0.148624im     -0.154569-0.0850201im     0.0106052-0.0937891im     -0.087672+0.141647im      0.0481596-0.0761966im      0.171883-0.119504im        0.130512-0.0144922im     0.106893+0.0757138im     -0.107451-0.0653967im     -0.191333+0.00807012im    0.0104221+0.0146029im      0.067306+0.130102im       0.283037+0.155485im      -0.044307-0.0902276im     0.0323022+0.131153im     -0.0478412-0.107459im    -0.0504809-0.199936im
+  0.0655062+0.0495242im     0.0880212-0.0492795im     0.0991352-0.19813im    0.00293415+0.101335im     0.135413+0.0232519im    -0.036018-0.0587056im     -0.177518-0.0999075im       0.18504+0.0170676im      -0.137846+0.0135956im     -0.365112-0.0289669im       0.1229+0.043324im     -0.129179+0.0651106im     -0.155208+0.0657702im       0.232388-0.0235556im   -0.0430851-0.180854im      0.107559+0.0345956im    0.0667942-0.0393763im      0.160113+0.165397im      0.0203022+0.120972im      -0.170667-0.168885im     -0.0977661-0.0827207im      0.0301473+0.042493im    -0.0396362-0.220765im       0.248788-0.110092im     -0.0166515-0.0419076im      0.267143+0.0839011im      0.101459-0.173824im      -0.187825-0.0946864im     0.0933397+0.00295675im   -0.0423527+0.164048im      0.0463731-0.079783im     0.0744989-0.103469im
+  0.0832468+0.0818579im     -0.134872-0.133451im      0.0199606-0.0938608im   -0.141478+0.0055932im   0.0676819+0.157536im    -0.0512623+0.107054im       0.158122-0.021425im     -0.0365148+0.223459im      -0.0349048-0.0754187im       0.10096+0.122278im      0.101786+0.0197739im     0.251449-0.0819916im      0.179446+0.0673403im      0.0217513-0.0791647im     -0.22138-0.146791im     -0.212726-0.109044im    -0.0634722+0.122047im      0.0250124+0.0285002im    -0.0925476+0.129877im       0.158489-0.195253im     -0.0181429-0.125566im        0.177171+0.177487im     0.0816215+0.0262594im     -0.227185-0.0308447im     -0.153571-0.139182im       0.265729+0.159638im      -0.224666-0.149427im      0.0918994-0.0121509im     0.0964644-0.039752im      0.0268209-0.0935231im   -0.00457059-0.11999im      0.0942469+0.0702136im
+  -0.204298+0.131948im     -0.0481899+0.0111422im     -0.238538+0.140661im    0.0776399-0.0369159im    0.190342+0.0117131im     0.137157+0.0918708im      0.109927-0.110431im       0.244964-0.251239im       0.0404762-0.104463im     0.00150631-0.0620102im   -0.0870658-0.0722678im     0.275786+0.055372im     -0.0879558-0.0832346im      0.0977015-0.0480369im    -0.153062-0.00977088im   0.0921306+0.222085im    -0.0581215-0.0689372im    -0.0831648+0.146579im      -0.258876-0.117683im      0.0983052+0.0127114im     0.0262859-0.129385im      -0.0802107-0.00589317im   -0.026314-0.14522im      0.00753325-0.155011im      0.0241848-0.00423382im     0.112572+0.148006im      -0.141513+0.15273im       0.0391501+0.0838904im     -0.183489+0.200924im       0.149119+0.170192im     -0.0600744-0.00161947im   -0.114835-0.0315108im
+     0.1526+0.0450639im     0.0357194+0.0060607im     -0.275115+0.0577619im  -0.0926617+0.199096im    0.0905161+0.211226im      0.142739+0.186809im       0.041743+0.184913im    -0.00388326+0.13968im        0.0302979-0.227317im     0.00861791-0.139961im    -0.0194925+0.0289937im   -0.0317761+0.151681im    -0.00476838-0.122909im       0.0164036-0.0920068im    0.0662797+0.247105im      0.125722-0.215976im    -0.0245809-0.0881359im     0.0571605+0.0782768im    -0.0465501-0.0875847im      0.035392+0.0182518im    -0.0524827-0.035915im       -0.111258+0.178612im     0.0856017-0.233591im     -0.0273952+0.0409383im    -0.0114901+0.219464im    -0.00288313-0.118536im      0.0790759-0.046525im     -0.0534342+0.0431141im      0.231913-0.181596im       0.219562-0.117334im       0.220015+0.0838053im    0.0173077-0.107379im
+  -0.219449-0.178867im       0.174771-0.0958615im     0.0395155-0.133331im   -0.0837112+0.0526634im   0.0668336+0.0975632im    0.0728297+0.0512942im     0.0310722-0.0656516im      -0.25464-0.0968355im      -0.126455+0.0680213im    0.00658143-0.195587im    -0.0395005+0.0368176im   -0.0328151-0.156266im    -0.00144533+0.0854652im     -0.0232972+0.0351663im    -0.108063+0.0332368im     -0.13056-0.161862im    -0.0407535-0.0512516im     -0.142368+0.0087579im    -0.0909216-0.129669im     -0.0705747+0.122863im      -0.190968+0.229798im       -0.158745-0.0224208im   -0.0636036-0.104247im       0.255919+0.0892711im    -0.0916706-0.111258im       0.132939-0.0573048im    -0.0717198-0.163337im       0.328937-0.0924158im    -0.0710746-0.00209529im     0.244379-0.0583728im      -0.18721-0.086976im     0.0204187-0.14993im
+  -0.183899+0.0123299im   -0.00609253+0.00520566im    0.0113412-0.134146im     0.196698+0.268535im   -0.0503228-0.195175im    -0.0124705+0.116584im      -0.128505+0.15637im       0.0359948-0.0582071im       0.127744-0.0549345im      0.171771-0.109581im       0.18693-0.101939im    -0.0525699-0.188538im    -0.00046652-0.0380059im     -0.0451064+0.0607583im    0.0388329+0.0775515im   0.00443502+0.158747im     -0.238409+0.248694im       0.121264+0.000686712im    0.147893-0.0706909im      0.279091-0.225563im     -0.0802308+0.0200716im     -0.0619098+0.0955704im    0.0192865-0.0717315im   0.000470885-0.148322im       0.240615-0.0737568im     0.0281432-0.153788im      0.0932416-0.250954im      0.0867455+0.031511im     -0.0773008+0.0774665im     0.0303082+0.0510062im       0.10468-0.0535197im    0.0853439+0.10809im
+  -0.352385-0.246334im     -0.0131053-0.010784im     -0.0780744+0.0302746im  -0.0898342-0.0707005im  -0.0529344-0.0572123im    0.0693302+0.0879353im    -0.0951877+0.00102568im   -0.0952425+0.0834995im   -0.000539593-0.0309552im    -0.0230065-0.0212128im   -0.0631812+0.0091978im      0.28982+0.0246738im     -0.208998-0.0886304im       0.346303-0.143625im     0.0173013+0.0376475im   -0.0533208-0.0522018im    0.0798013+0.0499117im      0.050393+0.0921325im    -0.0513613+0.205847im      0.0933719+0.0221369im   0.000583489-0.0173077im       0.248404-0.0154082im    0.0295118+0.166386im      -0.121473+0.108225im      0.0629371-0.0652982im     -0.198912-0.234399im       0.125236-0.0942747im    -0.0864984-0.110726im      0.0873309+0.011472im     0.00394451+0.183479im     -0.0504214+0.0376863im     0.140709-0.239672im
+ -0.0773396+0.0818948im    -0.0506745-0.0868733im     -0.080151+0.0409523im  0.00519379+0.0706531im    0.154176-0.043121im     0.0913138-0.120447im      -0.242118-0.0998857im     -0.175722-0.0822458im      -0.156384+0.0265847im    -0.0281021+0.0972004im    -0.331364-0.0330942im    -0.172691+0.0835003im       0.27745+0.00738496im     0.0305297+0.135671im     -0.222502-0.0282106im     0.034733+0.0101759im    -0.152027-0.0418045im    -0.0413779-0.0293994im    -0.0225053-0.134801im       0.155159-0.151659im      -0.104462-0.109342im        0.109044-0.0845606im   -0.0717182-0.135406im      -0.160774+0.0400366im    -0.0366346-0.0304368im     -0.194935+0.100102im      0.0798572-0.0995535im      0.152132-0.00831768im    0.0803092-0.261128im      -0.224435+0.190797im       0.086159+0.12714im     -0.0764002-0.107836im
+  0.0934643-0.216033im    -0.00578296+0.0486478im     -0.124964+0.108794im   -0.0758475+0.0412462im   -0.192415-0.150925im    -0.0443379+0.053525im       0.183735-0.167646im    -0.00964726-0.0202897im       0.066248+0.0962931im    -0.0569414+0.107261im    -0.0173933-0.0152813im   -0.0400822+0.0705097im    -0.0862521-0.224859im       0.0335027-0.0841533im   -0.0152496-0.0982324im    -0.145578+0.207907im     0.0623892-0.0266251im      0.206275-0.106809im      -0.053175+0.0418794im    -0.0898547-0.106868im      -0.090575+0.243271im      0.00644822+0.00907347im    0.194576-0.186722im      -0.042101-0.170195im      0.0599152-0.175101im       0.010042+0.197176im       0.139567-0.075759im       0.177838-0.0358539im     0.0972791-0.122856im        0.13932-0.0903149im    -0.0524721+0.386588im     -0.091521+0.0811727im
+  -0.101797+0.125966im       0.145612-0.0638306im     -0.134174-0.0181816im   -0.226929+0.0404092im   -0.152304-0.222613im      -0.27702-0.186182im     -0.0847178-0.0377872im      0.203668+0.005644im       -0.128466-0.118541im       0.144812-0.296219im      0.116535+0.0191998im    0.0395596+0.019797im      -0.062971-0.135761im      -0.0249441+0.0622198im    0.0629644-0.212728im     -0.107277-0.215434im       0.16102-0.201986im       0.154049+0.0986306im     0.0466934-0.115242im      0.0474186-0.00401988im   -0.0779286-0.0089271im     -0.0896677-0.0598734im    -0.181393-0.00666069im    -0.266572-0.107744im      -0.196647-0.0172031im    -0.0172443-0.127348im     -0.0578229+0.0572816im      0.114314-0.052786im     -0.0474222-0.0229859im    -0.0574239+0.00433748im    0.0912267-0.0056309im   -0.0914614+0.0383759im
+  -0.068116+0.0188854im    -0.0741085+0.251408im       0.153079-0.242981im    0.0487394+0.0428879im     -0.1169-0.143608im      0.114582+0.0167648im     -0.017587+0.0244219im       0.19041+0.0141137im      0.0637588+0.0933343im     0.0678285-0.0576537im    -0.112398-0.0723308im     0.117484-0.0431708im      0.077296+0.142508im       -0.125613-0.246517im     -0.095559+0.0681005im   0.00901729-0.250472im     -0.083395-0.0708779im      0.114353+0.0379773im     -0.297677-0.0961496im     -0.197727+0.0104877im   -0.00213446+0.0358235im       0.110943+0.282737im     0.0978982-0.0237326im      0.187822-0.0916205im     -0.135519-0.0417977im     -0.195546+0.0236073im     0.0600491+0.161467im       0.105063-0.114923im     -0.0330604-0.0583999im     -0.149574+0.125336im         0.1407+0.0617374im     0.117263+0.131213im
+  0.0153679+0.0335165im        0.1923-0.0792929im   -0.00238958+0.199513im     0.138442-0.110664im    0.0243124-0.109256im    0.00716594+0.0387188im    -0.0505205+0.0170731im      0.118142-0.0891189im     -0.0584696+0.0834173im      0.112162-0.0866926im     0.106524-0.00905346im  0.00173537-0.0215387im       0.24317+0.105626im        0.306153-0.102735im    -0.0852841+0.109692im    -0.0394529-0.0141499im     0.299675+0.00755751im   -0.0636763-0.207474im       0.172223-0.00636315im     0.150592-0.0777553im      0.272164-0.0764607im      0.0456495+0.237533im    -0.0159426-0.011726im       0.132313-0.00676162im    -0.214963+0.0646456im     0.0411591+0.0690882im       0.32812+0.00624841im    0.0773458-0.0232109im     -0.134419-0.168941im       0.152987-0.0435539im     -0.102511-0.0220374im   0.00450076+0.0395413im
+   0.160599-0.0619919im      0.254551-0.159766im      -0.208135+0.0131301im   0.0495369-0.134312im    0.0317197+0.0625577im      0.18262+0.172098im       -0.15239-0.230582im      0.0244754+0.124793im      -0.0222582-0.00366545im  0.000527411+0.0635443im   -0.0124004+0.012719im      0.169414-0.123663im     -0.0869235-0.0861465im      -0.129763+0.086157im     -0.130876-0.0488596im     0.187433-0.184249im     0.0224579+0.0567736im       0.12802+0.0159984im      0.047812+0.0436412im    -0.0732299-0.184636im       0.112018+0.0368544im     -0.0691848-0.16309im       0.159832+0.206718im       0.144602-0.153516im      0.0161604+0.251249im      -0.171218-0.0365276im    -0.0657018-0.196929im       0.155709-0.0961693im     -0.051688+0.0461987im    -0.0837692+0.0643502im   -0.00888514-0.0615007im    -0.136558+0.218525im
+  0.0350229-0.0767332im      0.134255+0.250895im      0.0636839-0.0776159im  -0.0777576+0.210306im     0.174455-0.14642im     -0.0793821+0.00857576im    0.0440587+0.0430824im     -0.174548-0.216963im        0.260491-0.128707im     -0.0893689-0.10452im      0.0175981+0.378252im      0.126958+0.00406202im    -0.100307+0.0712133im     -0.0664079+0.0688718im    -0.148469-0.0594946im    0.0619416+0.0291046im    0.0845064+0.0206282im     0.0887466-0.149112im     -0.0162791-0.179957im    -0.00727084-0.133777im       0.141995-0.212545im     0.000675253+0.0316219im   -0.0199064+0.0778702im    -0.0338121-0.0594199im     0.0291019+0.0626384im    -0.0992892+0.0397652im     -0.189115-0.03377im       -0.136386-0.127694im     0.00826993-0.1986im       -0.0313135-0.126524im      -0.261877+0.0747764im    0.0493469-0.0877081im
+  0.0356944+0.0319174im     -0.194445-0.0621041im    -0.0131662-0.166681im   -0.0655564-0.0133837im  -0.0549575-0.223113im     0.0193885-0.0695392im      0.187488+0.171423im     -0.0295081-0.140276im       -0.129642-0.248423im      0.0219853+0.0797847im    -0.118607-0.166301im     0.0997401-0.0458798im    -0.0725335+0.0124476im     -0.0110914+0.0854497im   -0.0189508-0.0652172im    0.0598356-0.0588491im    0.0901218-0.213974im      -0.230546-0.126178im     0.00107172+0.258581im       0.202255-0.220263im       0.120759+0.252823im       -0.147152-0.102737im    -0.0401029+0.0698638im      0.226206-0.0634648im      0.088694+0.167963im       0.113567+0.0235333im    -0.0666447+0.0462057im    -0.0282024-0.111844im      0.0413478-0.19276im     -0.00116898+0.078724im       0.104236+0.0775442im     0.177837-0.0471697im
+   0.187402+0.00617114im    0.0380854+0.0124521im      0.179429-0.0347809im   -0.138708+0.0416034im    0.213197+0.110812im     0.0175729-0.169009im     -0.0766521+0.0993822im     -0.194033+0.155587im          0.1403-0.0860944im    -0.0821337-0.11407im      -0.124752-0.130309im      0.106228-0.0583774im      0.071344+0.0665192im       0.103526+0.0315396im    0.0359938-0.21807im      -0.110751+0.212909im      0.114347+0.0168264im     0.0664077-0.237508im     -0.0786391+0.103426im      -0.120851-0.0415557im     0.0145864-0.000351834im   -0.0494891+0.0814269im      0.12237-0.0522104im    -0.0533251-0.126041im    -0.00410637+0.06195im       -0.088667-0.291041im    -0.00289325+0.0794396im      0.147672+0.126851im       -0.29535+0.100447im       0.164663+0.164142im        0.23981+0.0445655im    -0.108346-0.0807464im
+ -0.0622768-0.174499im      -0.108527-0.00229519im   -0.0141628-0.110534im    -0.214091-0.262862im   0.00621233+0.0423592im   -0.0765895+0.186565im      -0.187097+0.241898im     0.00584263+0.0610744im      -0.166539+0.0311278im     -0.111915-0.236087im    0.00313377-0.102501im    -0.0387775-0.0101764im    -0.0496912+0.085278im      -0.0682745+0.0579692im    -0.142393-0.0144477im     0.127953+0.0543169im   -0.0675535+0.191657im      0.0485411+0.0802751im     -0.136868+0.00466305im    0.0486674-0.0531988im     0.0386236-0.0516871im       0.142856-0.255052im    -0.0459961-0.0350427im     0.0243644-0.154648im      0.0440575-0.0810877im    -0.0280436+0.0764949im      0.126219+0.212839im     -0.0945502+0.0840625im     -0.172291-0.262271im       0.145143-0.311733im      0.0317376-0.0109888im   -0.0692066+0.116358im
+  0.0465129+0.0017711im     -0.148845-0.169373im      -0.203351+0.0310906im   0.0824223-0.122851im    -0.098426-0.0237684im      0.15137-0.131738im      0.0765986+0.188655im      -0.136426-0.00979405im      0.174973+0.11369im       0.0627478-0.102691im      0.147518+0.0165612im     0.229659-0.0496149im      0.119488-0.071706im      -0.0425899+0.122309im    -0.0857696-0.312876im      0.226579+0.0325779im    -0.186308-0.0815062im      0.174415+0.0921029im      0.234338+0.159737im     -0.0995871+0.0881245im     -0.105407-0.0835851im      -0.045364+0.124443im    -0.0451231-0.231622im       0.127607+0.20424im      -0.0983968-0.0312896im    -0.0998938+0.0286666im     0.0600474+0.057573im     -0.0182477-0.121126im      -0.147678-0.0125636im    -0.0839493-0.0935623im    -0.0912242+0.0666518im    0.0998346-0.10685im
+   0.182184+0.106449im       0.145474-0.19653im        0.172135+0.0902624im  -0.0806588+0.132465im   -0.0305539-0.0538511im    -0.207642+0.367349im      0.0586942+0.0739528im     0.0212971-0.148731im       0.0643006-0.124015im       0.134287+0.0985412im    -0.239755-0.0809598im    -0.117385-0.0364798im    -0.0390591-0.0273767im      0.0928162+0.0134113im   0.00799183+0.0615984im    -0.059961-0.139973im     0.0454516+0.135026im      0.0874656+0.205017im      0.0792847+0.220981im     -0.0311702+0.159231im       0.111716-0.141911im        0.116407-0.0444704im     -0.11693-0.192994im       0.182352+0.027307im      0.0639045-0.163237im      -0.122402-0.0100022im     -0.209477+0.0255905im     0.0824998-0.0714065im     -0.172468+0.0242815im    -0.0871696+0.0194052im     0.0094584+0.158901im    -0.0447406-0.0597006im
+ -0.0310122-0.0387252im     0.0488681-0.115929im      0.0685382+0.0381403im    0.192268-0.10075im    -0.0224721-0.0700805im      -0.1438+0.0678031im     -0.128111+0.0314201im     -0.026171-0.0503329im       0.133334+0.00201751im    -0.312276-0.0780658im    -0.193838+0.0611621im     0.150873+0.03047im       0.0369052-0.138715im       -0.156596-0.211676im    -0.0219894+0.00481858im  -0.0171369-0.186446im     0.0508835+0.134327im     -0.0719233-0.0395282im      0.198359-0.0585232im        0.1586-0.0107767im    -0.0421512+0.155746im       -0.117943+0.0241765im     0.359392-0.128976im      -0.102449-0.026809im      0.0274494-0.0772094im      0.234059-0.0139803im    -0.0102519+0.251521im    -0.00499377-0.0714185im    -0.0179256-0.0128509im     -0.224575-0.0405822im     0.0662933-0.155426im     -0.120724-0.215423im
+  0.0144378+0.197375im     -0.0471642-0.0493847im     0.0455657-0.0250359im     0.25497-0.079687im    -0.108792+0.00795983im   0.0179289-0.000490018im  0.00109015-0.0185816im      0.127549+0.0485912im       0.182946+0.00634636im     0.171461-0.0512796im    -0.204134+0.314581im    -0.0100727-0.0225443im    -0.0496376+0.0746842im       0.319763+0.157854im     -0.190637-0.0818586im    -0.141124-0.108245im    -0.0325328-0.179831im    -0.00311498-0.0947018im     -0.157482-0.00956727im  -0.00431562-0.037599im      -0.120206+0.0968311im       0.110089-0.248053im      0.107016-0.122063im      0.0776518-0.0504649im     0.0817627+0.0392061im     0.0326459-0.216268im      0.0712003-0.0532326im     -0.074638+0.219063im      0.0399619+0.0693457im    -0.0651899-0.317941im      0.0122862-0.00564489im   0.0494742+0.0353496im
+   0.162203+0.222777im       0.218218-0.0331662im     0.0422758-0.0646189im    0.008568-0.16315im      0.173286-0.13737im       0.104355-0.0984249im      0.228595+0.190494im     -0.0504604+0.0142867im      -0.138431+0.0110186im     0.0856605+0.0139093im   -0.0270812-0.0878551im    0.0816372+0.0299435im     -0.323984+0.0740233im       0.016574+0.0548765im    -0.218392+0.149783im     -0.100369+0.249366im    -0.0286811+0.00874912im   0.00766923+0.166822im        0.14087-0.208042im     -0.0342123+0.269012im     -0.0900308+0.0200193im      0.0586036-0.00240404im    0.203391+0.11955im       -0.103056-0.0478414im    -0.0214748-0.0678902im     0.0602357-0.0329155im      0.134325-0.108685im      0.0151875-0.218582im    -0.00650633-0.135265im       -0.10606-0.0196849im      0.132629-0.00692745im   0.0386296+0.0158142im
+ -0.0948235-0.135125im       0.169842-0.07368im       -0.313342+0.0917021im   0.0145679-0.0741134im   0.0866837+0.0105088im    -0.156784-0.143933im      0.0850223+0.169831im     -0.0360244+0.0703445im     -0.0826407-0.00159873im   -0.0436229-0.0987217im    -0.215423+0.190089im     -0.130332+0.0952966im     -0.152697+0.195993im       -0.136686-0.232793im     0.0057021-0.0664947im   -0.0916306+0.0432731im    -0.111641+0.0921732im    -0.0429194-0.0386897im      0.103019+0.0198965im     0.0446899-0.139837im    -0.00617771-0.0784113im       0.132605+0.0747536im   -0.0221284-0.0126122im      0.172391+0.12513im      -0.0657597+0.060022im       0.143157-0.107546im     -0.0914073+0.0567013im       0.04656+0.155798im    -0.00677957+0.149365im     -0.0902981+0.125491im       0.010141+0.255945im      0.183578+0.314181im
+  -0.102034-0.157757im     -0.0376068-0.193981im      0.0776496-0.0506225im    0.118101+0.0166684im    0.153032+0.0215492im    -0.077175-0.0558584im      0.219798+0.0605246im      0.109751-0.245631im       -0.134889-0.0245095im      0.159256+0.0097647im  -0.00557124+0.0330289im   -0.0426294-0.135657im       0.121264-0.0850781im      0.0337861-0.094235im      0.040549-0.224214im    -0.0152906-0.0758838im    -0.115311+0.343445im     -0.0273136-0.0153572im     -0.213819-0.0287678im     -0.202293+0.00750791im     0.113609-0.0839133im      -0.227825-0.109678im     0.0992221+0.068506im     -0.0666993+0.05234im       -0.176422+0.0961963im    0.00460365-0.105092im       0.169792-0.113433im      -0.235622-0.115777im       0.117951+0.0113834im    -0.0128381-0.0344258im      0.138301+0.181835im     -0.181563-0.0456288im
+ -0.0225987+0.0833348im    -0.0438286-0.0223485im      0.209179-0.222818im     0.255201-0.0348184im    0.184798+0.126963im     -0.128661-0.0910224im     0.0773024-0.108987im    -0.00334158+0.0669923im      -0.238141+0.0749948im    -0.0952236-0.103802im       0.03231-0.0328427im     0.190557+0.113301im      0.0307219-0.128002im       -0.131101+0.0480712im     -0.10701+0.196593im      0.012933-0.168631im      0.031103-0.0743798im      0.225639-0.00333485im     0.112101-0.00498605im    0.0572375+0.00266176im     0.268779+0.0746574im     -0.0384062-0.119365im    -0.0315502-0.140345im      -0.171015+0.106354im       0.113658-0.0322043im    -0.0813197+0.0113337im     0.0227818-0.0524743im     -0.018276+0.108833im      -0.101344+0.1225im         0.162425+0.0322926im    -0.0968208+0.331619im      0.215785+0.0330781im
+ -0.0570377-0.139742im     -0.0327774-0.0307177im    -0.0252064-0.0637587im    0.229457+0.0357265im  0.00655646+0.132431im    -0.0700978-0.0414356im      0.152206+0.0919773im    -0.0431858-0.0189112im       0.301527+0.116954im      -0.171018-0.094085im    -0.0406705-0.0378543im     0.071316-0.320183im      0.0839378+0.16757im          0.17565+0.038384im     0.0972155+0.0247719im   0.00536052+0.00530351im    0.192765-0.0850433im     0.0198767+0.350613im      0.0720028-0.0546408im    -0.0738452+0.03078im       0.0598772+0.0145517im      0.0579739-0.119927im     -0.171326+0.0351446im     -0.157925+0.00662228im     0.112637+0.139982im       0.107757+0.0916441im    -0.0392294+0.0446083im      0.205062+0.0126369im      0.170325-0.232643im    -0.00436511+0.121641im       0.138247+0.0526562im      -0.1092+0.195874im
+   0.160561-0.0318399im     0.0307927+0.233052im     -0.0216587+0.0440552im      0.1677-0.0596486im    0.012743+0.155697im    -0.0441889+0.0492037im    -0.0450027+0.0410892im     0.0169078+0.0587923im     -0.0709321+0.222171im      0.0753874+0.226225im     0.0958408+0.0281579im    -0.151386-0.155369im      -0.180095+0.0704867im    -0.00625026-0.171626im    -0.0237567-0.24607im      0.0157013-0.0942824im     0.165973+0.079836im      -0.147021+0.108973im      -0.109443-0.0421566im      0.312718-0.00391913im    -0.217406-0.0214247im      -0.121691-0.0319761im    -0.076476-0.142702im       -0.15896-0.104837im     0.00558548+0.204249im      -0.131603-0.00380913im   -0.0176494+0.0416312im     0.0314384-0.191328im      -0.206197+0.0198323im     0.0351526-0.0200218im   -0.00549123+0.138133im      0.220595-0.16168im

and then generate the state $ψ$

psi = P[:, 3]
32-element Vector{ComplexF64}:
+    -0.2033346869585067 - 0.061519452261437686im
+     0.3251068655530197 + 0.0im
+    0.03334379352722254 - 0.05773221769849324im
+    0.07958086018535453 + 0.19640235307364595im
+    0.02888773434078068 - 0.14991306123396259im
+    0.10561698142749107 + 0.01754552365128968im
+  -0.027698403861219984 - 0.06505383722988169im
+    0.04603596597873679 + 0.07070248281432384im
+   0.009628709173791638 + 0.04676357615707313im
+   -0.11091504404657769 + 0.26467677469998035im
+    0.12465968731314483 + 0.004132273051938208im
+  -0.013904825166122188 + 0.08335783645537884im
+     0.2945913625146499 + 0.024327562162916667im
+     0.1215545603644323 - 0.13093194411822215im
+   -0.12036025901601137 + 0.09919748897730228im
+    -0.2587391171615193 - 0.059853563032745666im
+   -0.12001967094323193 + 0.28658267930939535im
+    0.03617656030030113 - 0.02579642062921845im
+   -0.01493661123757938 - 0.05370378317170016im
+    0.13717610318171253 - 0.18353628385735973im
+ -0.0016013026301029236 + 0.09981882897396879im
+    0.12414129873518111 + 0.05292123689564562im
+       0.07505409966426 + 0.19255962333668236im
+    0.12386792328886673 - 0.06362996505147879im
+   -0.09419397903654027 - 0.08463878114370679im
+   -0.07284326241902189 + 0.2894661686019308im
+    0.13099185832042815 + 0.03911058608171358im
+   0.009043056351700406 + 0.03330634844885166im
+   0.027541958421615994 - 0.019992026421193538im
+     0.1287905859836585 + 0.078745874525378im
+   -0.16717462531553792 + 0.02760496169332399im
+   0.010739535477543456 - 0.09626400684255601im

In the phase estimation process, we will feed the state to circuit and measure the first n qubits processed by iQFT.

r = join(ArrayReg(psi), zero_state(N))
 r |> PE(N, M, U)
ArrayReg{2, ComplexF64, Array...}
     active qubits: 8/8
     nlevel: 2

Since our phase can be represented by 3 qubits precisely, we only need to measure once

results = measure(r, 1:N; nshots=1)
1-element Vector{DitStr{2, 3, Int64}}:
  011 ₍₂₎

Recall that our QFT's bit numbering is reversed, let's reverse it back

using BitBasis
-estimated_phase = bfloat(results[]; nbits=N)
0.75

the phase is exactly 0.75!


This page was generated using Literate.jl.

+estimated_phase = bfloat(results[]; nbits=N)
0.75

the phase is exactly 0.75!


This page was generated using Literate.jl.

diff --git a/dev/generated/examples/3.grover-search/index.html b/dev/generated/examples/3.grover-search/index.html index dcea1d5d..5b377f97 100644 --- a/dev/generated/examples/3.grover-search/index.html +++ b/dev/generated/examples/3.grover-search/index.html @@ -117,10 +117,7 @@ number of iter = 5 number of iter = 6 number of iter = 7 -number of iter = 8 -number of iter = 9 -number of iter = 10 -success, overlap = 1.0 + 0.0im +success, overlap = -1.0 + 0.0im

The final state has an overlap of 1 with the target state.

Amplitude Amplification

Given a circuit to generate a state, now we want to project out the subspace with [1,3,5,8,9,11,12] fixed to 1 and [4,6] fixed to 0. We can construct an oracle

evidense = [1, 3, -4, 5, -6, 8, 9, 11, 12]
 function inference_oracle(nbit::Int, locs::Vector{Int})
     control(nbit, locs[1:end-1], abs(locs[end]) => (locs[end]>0 ? Z : -Z))
@@ -134,24 +131,23 @@
 for i = 1:num_grover_step(oracle, gen)
     grover_step!(reg, oracle, gen)
     println("step $(i-1), overlap = $(abs(reg'*solution))")
-end
step 0, overlap = 0.11457856932749395
-step 1, overlap = 0.19021840433085546
-step 2, overlap = 0.2647440104263067
-step 3, overlap = 0.3377188442363379
-step 4, overlap = 0.408715446232692
-step 5, overlap = 0.47731794463584265
-step 6, overlap = 0.543124491437735
-step 7, overlap = 0.6057496162784728
-step 8, overlap = 0.6648264843888095
-step 9, overlap = 0.7200090453722614
-step 10, overlap = 0.7709740602400635
-step 11, overlap = 0.817422994825359
-step 12, overlap = 0.859083768485696
-step 13, overlap = 0.8957123478505835
-step 14, overlap = 0.9270941762785245
-step 15, overlap = 0.9530454306502978
-step 16, overlap = 0.9734140981366541
-step 17, overlap = 0.9880808666331276
-step 18, overlap = 0.9969598236461193
-step 19, overlap = 0.9999989595364428
-

This page was generated using Literate.jl.

+end
step 0, overlap = 0.11480007965675817
+step 1, overlap = 0.19058324193670428
+step 2, overlap = 0.2652457005602443
+step 3, overlap = 0.33834841120466996
+step 4, overlap = 0.40946150147259774
+step 5, overlap = 0.4781667987090151
+step 6, overlap = 0.5440602890192854
+step 7, overlap = 0.6067544930281308
+step 8, overlap = 0.6658807444092039
+step 9, overlap = 0.7210913577866083
+step 10, overlap = 0.7720616732602615
+step 11, overlap = 0.8184919655324984
+step 12, overlap = 0.8601092064095035
+step 13, overlap = 0.89666867031338
+step 14, overlap = 0.9279553733638201
+step 15, overlap = 0.9537853375670116
+step 16, overlap = 0.974006672677868
+step 17, overlap = 0.9885004693737958
+step 18, overlap = 0.997181498487807
+

This page was generated using Literate.jl.

diff --git a/dev/generated/examples/4.shor-algorithm/index.html b/dev/generated/examples/4.shor-algorithm/index.html index 94ec24ae..ddf8161d 100644 --- a/dev/generated/examples/4.shor-algorithm/index.html +++ b/dev/generated/examples/4.shor-algorithm/index.html @@ -216,4 +216,4 @@ N = nbit+ncbit chain(N, repeat(N, H, 1:ncbit), KMod(N, ncbit, x, L), subroutine(N, qft_circuit(ncbit)', 1:ncbit)) -end
Main.var"##235".order_finding_circuit

The circuit for order finding is consisted of three parts

  1. Hadamard gates,
  2. KMod that computes a classical function mod(a^k*x, L).

k is the integer stored in first K (or ncbit) qubits and the rest N-K qubits stores a. Notice it is not a basic gate, it should have been compiled to multiple gates, which is not implemented in Yao for the moment. To learn more about implementing arithmatics on a quantum circuit, please read this paper.

  1. Inverse quantum fourier transformation.

Run

Factorizing 15, you should see 3 or 5, please report a bug if it is not...

shor(15, Val(:quantum))
3

This page was generated using Literate.jl.

+end
Main.var"##235".order_finding_circuit

The circuit for order finding is consisted of three parts

  1. Hadamard gates,
  2. KMod that computes a classical function mod(a^k*x, L).

k is the integer stored in first K (or ncbit) qubits and the rest N-K qubits stores a. Notice it is not a basic gate, it should have been compiled to multiple gates, which is not implemented in Yao for the moment. To learn more about implementing arithmatics on a quantum circuit, please read this paper.

  1. Inverse quantum fourier transformation.

Run

Factorizing 15, you should see 3 or 5, please report a bug if it is not...

shor(15, Val(:quantum))
3

This page was generated using Literate.jl.

diff --git a/dev/generated/examples/5.shor-9-code/index.html b/dev/generated/examples/5.shor-9-code/index.html index 32fa2a61..3db319a8 100644 --- a/dev/generated/examples/5.shor-9-code/index.html +++ b/dev/generated/examples/5.shor-9-code/index.html @@ -16,4 +16,4 @@ )
shor (generic function with 1 method)

Now we can check whether it can correct a given error by doing symbolic computation on an arbitrary 1-qubit pure quantum state $α|0⟩ + β|1⟩$ and a specific weight-9 error.

@vars α β
 s = α * ket"0" + β * ket"1" |> append_qudits!(8)
 E = kron(1=>X, 2=>Z, 3=>Z, 4=>X, 5=>Z, 6=>Z, 7=>X, 8=>Z, 9=>Z);
-s |> shor(E) |> expand
α|110110110⟩ + β|110110111⟩

This page was generated using Literate.jl.

+s |> shor(E) |> expand
α|110110110⟩ + β|110110111⟩

This page was generated using Literate.jl.

diff --git a/dev/generated/examples/6.quantum-circuit-born-machine/index.html b/dev/generated/examples/6.quantum-circuit-born-machine/index.html index c483ac19..5fde0330 100644 --- a/dev/generated/examples/6.quantum-circuit-born-machine/index.html +++ b/dev/generated/examples/6.quantum-circuit-born-machine/index.html @@ -6,53 +6,53 @@ pg = gaussian_pdf(1:1<<6, 1<<5-0.5, 1<<4);

We can plot the distribution, it looks like

Plots.plot(pg)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Create the Circuit

A quantum circuit born machine looks like the following:

differentiable ciruit

It is composited by two different layers: rotation layer and entangler layer.

Rotation Layer

Arbitrary rotation is built with Rotation Gate on Z, X, Z axis with parameters.

\[Rz(\theta) \cdot Rx(\theta) \cdot Rz(\theta)\]

Since our input will be a $|0\dots 0\rangle$ state. The first layer of arbitrary rotation can just use $Rx(\theta) \cdot Rz(\theta)$ and the last layer of arbitrary rotation could just use $Rz(\theta)\cdot Rx(\theta)$

In , every Hilbert operator is a block type, this ncludes all quantum gates and quantum oracles. In general, operators appears in a quantum circuit can be divided into Composite Blocks and Primitive Blocks.

We follow the low abstraction principle and thus each block represents a certain approach of calculation. The simplest Composite Block is a Chain Block, which chains other blocks (oracles) with the same number of qubits together. It is just a simple mathematical composition of operators with same size. e.g.

\[\text{chain(X, Y, Z)} \iff X \cdot Y \cdot Z\]

We can construct an arbitrary rotation block by chain $Rz$, $Rx$, $Rz$ together.

chain(Rz(0.0), Rx(0.0), Rz(0.0))
nqubits: 1
 chain
 ├─ rot(Z, 0.0)
@@ -175,170 +175,170 @@ 

64-element Vector{Float64}: - 0.004133486523101152 - 0.004841758195470542 - 0.0053638198800351165 - 0.006014067209381298 - 0.006577475953851315 - 0.007340590841432222 - 0.007987709345414127 - 0.009017039314901651 - 0.009645340650396284 - 0.010435751908475167 - 0.011647409377713726 - 0.01234765457502382 - 0.013336669977445042 - 0.014496200812926885 - 0.015452937863625204 - 0.016292488172597357 - 0.01740118188567342 - 0.018234802654645856 - 0.019294135340699466 - 0.020094759064642604 - 0.021122612861327484 - 0.02180597955896689 - 0.02275092787008356 - 0.0235220107001656 - 0.024084383489436055 - 0.024627480682834234 - 0.02516504040700968 - 0.025344694045761448 - 0.02583276823274501 - 0.026160935182472235 - 0.02618172063179388 - 0.02604922109724038 - 0.025985431670209357 - 0.02580315288488768 - 0.02552154780137255 - 0.025153477382960497 - 0.024554110325239527 - 0.023948712361655324 - 0.02341735029755776 - 0.022662641242418135 - 0.021884914051207897 - 0.021071310646725787 - 0.020227089865122772 - 0.01929684901543418 - 0.018289729491622553 - 0.017302671908413825 - 0.016438647016922305 - 0.015377155726144263 - 0.01437055843498409 - 0.013359817682805902 - 0.01246175003383155 - 0.011442304670168494 - 0.010721036557505368 - 0.009607224243172417 - 0.008870469764915647 - 0.008073664088723587 - 0.007367475157463305 - 0.00660278960091021 - 0.006039481228193021 - 0.005422775746160495 - 0.0046450367009025105 - 0.004197972807648939 - 0.00388346230413649 - 0.003396334983295141

The history of training looks like below

title!("training history")
+ 0.004446054657298753
+ 0.004331157645300311
+ 0.005835850732537775
+ 0.005836326060827502
+ 0.006572217842013155
+ 0.0075577836174582904
+ 0.008049808007401531
+ 0.008851524894909079
+ 0.009743607822144324
+ 0.010528610129109328
+ 0.011478611161272094
+ 0.012431473989718075
+ 0.013292480438956596
+ 0.014546249912351756
+ 0.01525412618005244
+ 0.016560007178163545
+ 0.017336804464180428
+ 0.018419677210259496
+ 0.019281125874896513
+ 0.020026705759927953
+ 0.020943354659739614
+ 0.021945779730180776
+ 0.02265330315848815
+ 0.023451074736356034
+ 0.02395534540947105
+ 0.02455544195711308
+ 0.024956887715311314
+ 0.025591250870995643
+ 0.025880777464795172
+ 0.02601395500724068
+ 0.026055570857316045
+ 0.026017126001370815
+ 0.026024252450169285
+ 0.025849329915048843
+ 0.02560132889392464
+ 0.025129103668838446
+ 0.024634149085080933
+ 0.023981785924987162
+ 0.023328590610284416
+ 0.022669945822563688
+ 0.022006605927837153
+ 0.020996101110117016
+ 0.020020881452901977
+ 0.019331699335207675
+ 0.018092360081346556
+ 0.017423526856525047
+ 0.016177651572765794
+ 0.015236136561980132
+ 0.014483802363532233
+ 0.01345447804491319
+ 0.012658255566757901
+ 0.011566055592914945
+ 0.010704366966141325
+ 0.009898455311057716
+ 0.00867751468056457
+ 0.008222897629418413
+ 0.007283275767419372
+ 0.006682452030052422
+ 0.006074115300337746
+ 0.005354124439857948
+ 0.00433052204952558
+ 0.004399982209411372
+ 0.003744869866319961
+ 0.0035613117650391936

The history of training looks like below

title!("training history")
 xlabel!("steps"); ylabel!("loss")
 Plots.plot(history)
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +

And let's check what we got

fig2 = Plots.plot(1:1<<6, trained_pg; label="trained")
 Plots.plot!(fig2, 1:1<<6, pg; label="target")
 title!("distribution")
 xlabel!("x"); ylabel!("p")
- + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

So within 50 steps, we got a pretty close estimation of our target distribution!


This page was generated using Literate.jl.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

So within 50 steps, we got a pretty close estimation of our target distribution!


This page was generated using Literate.jl.

diff --git a/dev/generated/examples/7.variation-quantum-eigen-solver/index.html b/dev/generated/examples/7.variation-quantum-eigen-solver/index.html index 81bac0e0..0ef1d66d 100644 --- a/dev/generated/examples/7.variation-quantum-eigen-solver/index.html +++ b/dev/generated/examples/7.variation-quantum-eigen-solver/index.html @@ -79,4 +79,4 @@ 0.288675+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.866025+0.0im 0.0+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im -0.707107+0.0im 0.0+0.0im 0.0+0.0im -4.71028e-16+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5-0.0im 0.0+0.0im - 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 1.0+0.0im

This page was generated using Literate.jl.

+ 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 1.0+0.0im

This page was generated using Literate.jl.

diff --git a/dev/generated/examples/8.riemannian-gradient-flow/index.html b/dev/generated/examples/8.riemannian-gradient-flow/index.html index 6be08077..e71db4c7 100644 --- a/dev/generated/examples/8.riemannian-gradient-flow/index.html +++ b/dev/generated/examples/8.riemannian-gradient-flow/index.html @@ -19,46 +19,46 @@ ylabel!("energy") - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +

Let's now consider the energy cost function directly over the special unitary group $\mathcal{L}: \text{SU}(2^n) \rightarrow \mathbb{R}$

\[\mathcal{L}(U) = \text{Tr}\{HU\rho_0U^\dagger\}.\]

To minimize the cost function we can follow the Riemannian gradient flow defined through the following differential equation

\[\dot{U} = -\text{grad}\mathcal{L}(U) = [U\rho_0U^\dagger, H]U.\]

Discretizing the flow we get the following recursive update rule

\[U_{k + 1} = \exp\{\alpha[U_k\rho_0U^\dagger_k, H]\}U_k = \exp\{\alpha[\rho_k, H]\}U_k,\]

where $\alpha$ is the appropriate learning rate and $U_0 = I$.

We can expand the commutator in the exponent in the basis of Pauli strings $P^j$

\[[\rho_k, H] = \frac{1}{2^n}\sum_{j = 1}^{4^n - 1}\omega^j_kP^j,\]

where

\[\omega^j_k = \text{Tr}\{[\rho_k, H]P^j\} = \text{Tr}\{[H, P^j]\rho_k\} = \langle[H, P^j]\rangle_{\rho_k}.\]

It turns out that $\omega^j_k$ can easily be evaluated with the help of a parameter shift rule

\[\omega^j_k = \langle[H, P^j]\rangle_{\rho_k} = -i\langle V^\dagger_j(\pi/4)HV_j(\pi/4) - V^\dagger_j(-\pi/4)HV_j(-\pi/4)\rangle_{\rho_k},\]

where $V_j(t) = \exp\{-itP^j\}$.

Next, we write a function for generation of 2-local Pauli operators. We will restrict the Riemannian gradient to this subspace of the Lie algebra since otherwise the number of parameters to calculate would be $4^8 - 1 = 65535$ which is too much for a reasonable runtime of the algorithm.

function generate_2local_pauli_strings(n)
     pauli_strings = []
@@ -107,4 +107,4 @@
 Plots.plot(history, legend=false)
 Plots.plot!(1:100, [w[1] for i=1:100])
 xlabel!("steps")
-ylabel!("energy")
Riemannian gradient flow

When we compare the final states achieved with the Riemannian gradient flow optimizer and with the standard VQE we can notice that the former has lower quality. This is because the Riemannian gradient flow optimizer has only a local view of the cost landscape while VQE can access these directions since the ansatz we used is universal. However, if we were able to calculate all of the $4^n - 1$ projections, Riemannian gradient flow optimizer would be guaranteed to converge given the appropriate learning rate!


This page was generated using Literate.jl.

+ylabel!("energy")Riemannian gradient flow

When we compare the final states achieved with the Riemannian gradient flow optimizer and with the standard VQE we can notice that the former has lower quality. This is because the Riemannian gradient flow optimizer has only a local view of the cost landscape while VQE can access these directions since the ansatz we used is universal. However, if we were able to calculate all of the $4^n - 1$ projections, Riemannian gradient flow optimizer would be guaranteed to converge given the appropriate learning rate!


This page was generated using Literate.jl.

diff --git a/dev/index.html b/dev/index.html index af0d3cb3..f7bfd105 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -Home · Documentation | Yao

Yao

A General Purpose Quantum Computation Simulation Framework

Welcome to Yao, a Flexible, Extensible, Efficient Framework for Quantum Algorithm Design. Yao (幺) is the Chinese character for normalized but not orthogonal.

We aim to provide a powerful tool for researchers, students to study and explore quantum computing in near term future, before quantum computer being used in large-scale.

Quick Starts

You can learn how to use Yao with some quick examples in this section. There are three badges on the top of each tutorial that allows you to open it in mybinder, preview it in nbviewer or download the tutorial as .zip file, which includes the notebook and the scripts and other related materials.

Contribution

If you are interesting in polishing or contributing our tutorial, you can just open a PR in our tutorial repo.

Syntax

The tutorials are written with Literate.

Pluto Notebooks

There is also a set of Pluto notebooks available in the notebooks folder

Manual

+Home · Documentation | Yao

Yao

A General Purpose Quantum Computation Simulation Framework

Welcome to Yao, a Flexible, Extensible, Efficient Framework for Quantum Algorithm Design. Yao (幺) is the Chinese character for normalized but not orthogonal.

We aim to provide a powerful tool for researchers, students to study and explore quantum computing in near term future, before quantum computer being used in large-scale.

Quick Starts

You can learn how to use Yao with some quick examples in this section. There are three badges on the top of each tutorial that allows you to open it in mybinder, preview it in nbviewer or download the tutorial as .zip file, which includes the notebook and the scripts and other related materials.

Contribution

If you are interesting in polishing or contributing our tutorial, you can just open a PR in our tutorial repo.

Syntax

The tutorials are written with Literate.

Pluto Notebooks

There is also a set of Pluto notebooks available in the notebooks folder

Manual

diff --git a/dev/man/automatic_differentiation.html b/dev/man/automatic_differentiation.html index c6fcab70..c862af02 100644 --- a/dev/man/automatic_differentiation.html +++ b/dev/man/automatic_differentiation.html @@ -1,2 +1,2 @@ -Automatic Differentiation · Documentation | Yao

Automatic Differentiation

Yao currently contains builtin automatic differentiation engine (an operator overloading based) especially for quantum circuits. It uses the reversible context of quantum computation to optimize the performance during simulation, thus you may find this is way faster than any other AD engine at the moment.

Builtin Reverse mode AD engine for simulation

As for expectation, the usage is pretty simple, since the evluation of expectations are just

expect(H, rand_state(10)=>circuit)

to get the gradients, simply add an adjoint

expect'(H, rand_state(10)=>circuit)

which will return the pair of gradients, one is the gradient of input register and the other is the gradient of circuit parameters.

Integration with General purpose AD engine

The builtin AD engine for Yao only provides the differentiation of quantum circuits, but you can plug it into a general AD engine, such as Zygote, since we have ported these rules to ChainRules.

APIs

YaoBlocks.AD.apply_backMethod
apply_back(st::Tuple{<:AbstractArrayReg, <:AbstractArrayReg}, block::AbstractBlock; kwargs...) -> (out, outδ), paramsδ

The backward function of apply!. Returns a tuple of ((input register, gradient of input register), parameter gradients)

source
YaoBlocks.AD.mat_backMethod
mat_back([::Type{T}, ]block::AbstractBlock, adjm::AbstractMatrix) -> Vector

The backward function of mat. Returns the gradients of parameters.

source
+Automatic Differentiation · Documentation | Yao

Automatic Differentiation

Yao currently contains builtin automatic differentiation engine (an operator overloading based) especially for quantum circuits. It uses the reversible context of quantum computation to optimize the performance during simulation, thus you may find this is way faster than any other AD engine at the moment.

Builtin Reverse mode AD engine for simulation

As for expectation, the usage is pretty simple, since the evluation of expectations are just

expect(H, rand_state(10)=>circuit)

to get the gradients, simply add an adjoint

expect'(H, rand_state(10)=>circuit)

which will return the pair of gradients, one is the gradient of input register and the other is the gradient of circuit parameters.

Integration with General purpose AD engine

The builtin AD engine for Yao only provides the differentiation of quantum circuits, but you can plug it into a general AD engine, such as Zygote, since we have ported these rules to ChainRules.

APIs

YaoBlocks.AD.apply_backMethod
apply_back(st::Tuple{<:AbstractArrayReg, <:AbstractArrayReg}, block::AbstractBlock; kwargs...) -> (out, outδ), paramsδ

The backward function of apply!. Returns a tuple of ((input register, gradient of input register), parameter gradients)

source
YaoBlocks.AD.mat_backMethod
mat_back([::Type{T}, ]block::AbstractBlock, adjm::AbstractMatrix) -> Vector

The backward function of mat. Returns the gradients of parameters.

source
diff --git a/dev/man/bitbasis.html b/dev/man/bitbasis.html index 889a7d60..2f2b47d1 100644 --- a/dev/man/bitbasis.html +++ b/dev/man/bitbasis.html @@ -146,4 +146,4 @@ SubDitStr{3, 5, Int64}(02122 ₍₃₎, 1, 4) julia> sx == dit"212;3" -truesource +truesource diff --git a/dev/man/blocks.html b/dev/man/blocks.html index 11101079..83e4ebd5 100644 --- a/dev/man/blocks.html +++ b/dev/man/blocks.html @@ -1,8 +1,8 @@ -Blocks · Documentation | Yao

Blocks

Blocks are the basic building blocks of a quantum circuit in Yao. It simply means a quantum operator, thus, all the blocks have matrices in principal and one can get its matrix by mat. The basic blocks required to build an arbitrary quantum circuit is defined in the component package YaoBlocks.

Block Tree serves as an intermediate representation for Yao to analysis, optimize the circuit, then it will be lowered to instructions like for simulations, blocks will be lowered to instruct! calls.

The structure of blocks is the same with a small type system, it consists of two basic kinds of blocks: CompositeBlock (like composite types), and PrimitiveBlock (like primitive types). By combining these two kinds of blocks together, we'll be able to construct a quantum circuit and represent it in a tree data structure.

YaoAPI.PrimitiveBlockType
PrimitiveBlock{D} <: AbstractBlock{D}

Abstract type that all primitive block will subtype from. A primitive block is a concrete block who can not be decomposed into other blocks. All composite block can be decomposed into several primitive blocks.

Note

subtype for primitive block with parameter should implement hash and == method to enable key value cache.

Required Methods

Optional Methods

source

Primitive Blocks

Primitive blocks are subtypes of PrimitiveBlock, they are the leaf nodes in a block tree, thus primitive types do not have subtypes.

We provide the following primitive blocks:

YaoBlocks.GeneralMatrixBlockType
GeneralMatrixBlock{D, MT} <: PrimitiveBlock{D}
+Blocks · Documentation | Yao

Blocks

Blocks are the basic building blocks of a quantum circuit in Yao. It simply means a quantum operator, thus, all the blocks have matrices in principal and one can get its matrix by mat. The basic blocks required to build an arbitrary quantum circuit is defined in the component package YaoBlocks.

Block Tree serves as an intermediate representation for Yao to analysis, optimize the circuit, then it will be lowered to instructions like for simulations, blocks will be lowered to instruct! calls.

The structure of blocks is the same with a small type system, it consists of two basic kinds of blocks: CompositeBlock (like composite types), and PrimitiveBlock (like primitive types). By combining these two kinds of blocks together, we'll be able to construct a quantum circuit and represent it in a tree data structure.

YaoAPI.PrimitiveBlockType
PrimitiveBlock{D} <: AbstractBlock{D}

Abstract type that all primitive block will subtype from. A primitive block is a concrete block who can not be decomposed into other blocks. All composite block can be decomposed into several primitive blocks.

Note

subtype for primitive block with parameter should implement hash and == method to enable key value cache.

Required Methods

Optional Methods

source

Primitive Blocks

Primitive blocks are subtypes of PrimitiveBlock, they are the leaf nodes in a block tree, thus primitive types do not have subtypes.

We provide the following primitive blocks:

YaoBlocks.GeneralMatrixBlockType
GeneralMatrixBlock{D, MT} <: PrimitiveBlock{D}
 GeneralMatrixBlock{D}(m, n, A, tag="matblock(...)")
-GeneralMatrixBlock(A; nlevel=2, tag="matblock(...)")

General matrix gate wraps a matrix operator to quantum gates. This is the most general form of a quantum gate.

Arguments

  • m and n are the number of dits in row and column.
  • A is a matrix.
  • tag is the printed information.
  • D and nlevel are the number of levels in each qudit.
source
YaoBlocks.MeasureType
Measure{D,K, OT, LT, PT, RNG} <: PrimitiveBlock{D}
-Measure(n::Int; rng=Random.GLOBAL_RNG, operator=ComputationalBasis(), locs=1:n, resetto=nothing, remove=false, nlevel=2)

Measure operator, currently only qudits are supported.

source
YaoBlocks.MeasureMethod
Measure(n::Int; rng=Random.GLOBAL_RNG, operator=ComputationalBasis(), locs=AllLocs(), resetto=nothing, remove=false)

Create a Measure block with number of qudits n.

Examples

You can create a Measure block on given basis (default is the computational basis).

julia> Measure(4)
+GeneralMatrixBlock(A; nlevel=2, tag="matblock(...)")

General matrix gate wraps a matrix operator to quantum gates. This is the most general form of a quantum gate.

Arguments

  • m and n are the number of dits in row and column.
  • A is a matrix.
  • tag is the printed information.
  • D and nlevel are the number of levels in each qudit.
source
YaoBlocks.MeasureType
Measure{D,K, OT, LT, PT, RNG} <: PrimitiveBlock{D}
+Measure(n::Int; rng=Random.GLOBAL_RNG, operator=ComputationalBasis(), locs=1:n, resetto=nothing, remove=false, nlevel=2)

Measure operator, currently only qudits are supported.

source
YaoBlocks.MeasureMethod
Measure(n::Int; rng=Random.GLOBAL_RNG, operator=ComputationalBasis(), locs=AllLocs(), resetto=nothing, remove=false)

Create a Measure block with number of qudits n.

Examples

You can create a Measure block on given basis (default is the computational basis).

julia> Measure(4)
 Measure(4)

Or you could specify which qudits you are going to measure

julia> Measure(4; locs=1:3)
 Measure(4;locs=(1, 2, 3))

by default this will collapse the current register to measure results.

julia> r = normalize!(arrayreg(bit"000") + arrayreg(bit"111"))
 ArrayReg{2, ComplexF64, Array...}
@@ -34,14 +34,14 @@
  0.0 + 0.0im
  0.0 + 0.0im
  0.0 + 0.0im
- 1.0 + 0.0im

But you can also specify the target bit configuration you want to collapse to with keyword resetto.

```jldoctest; setup=:(using Yao) julia> m = Measure(4; resetto=bit"0101") Measure(4;postprocess=ResetTo{BitStr{4,Int64}}(0101 ₍₂₎))

julia> m.postprocess ResetTo{BitStr{4,Int64}}(0101 ₍₂₎)```

source
YaoBlocks.ProjectorType
struct Projector{D, T, AT<:(AbstractArrayReg{D, T})} <: PrimitiveBlock{D}

Projection operator to target state psi.

Definition

projector(s) defines the following operator.

\[|s⟩ → |s⟩⟨s|\]

source
YaoBlocks.ReflectGateType
ReflectGate{D, T, Tt, AT<:AbstractArrayReg{D, T}} = TimeEvolution{D,Tt,Projector{D,T,AT}}

Let |v⟩ be a quantum state vector, a reflection gate is a unitary operator that defined as the following operation.

\[|v⟩ → 1 - (1-exp(-iθ)) |v⟩⟨v|\]

When $θ = π$, it defines a standard reflection gate $1-2|v⟩⟨v|$.

source
YaoBlocks.RotationGateType
RotationGate{D,T,GT<:AbstractBlock{D}} <: PrimitiveBlock{D}

RotationGate, with GT both hermitian and isreflexive.

Definition

Expression rot(G, θ) defines the following gate

\[\cos \frac{\theta}{2}I - i \sin \frac{\theta}{2} G\]

source
YaoBlocks.TimeEvolutionType
TimeEvolution{D, TT, GT} <: PrimitiveBlock{D}

TimeEvolution, where GT is block type. input matrix should be hermitian.

Note

TimeEvolution contructor check hermicity of the input block by default, but sometimes it can be slow. Turn off the check manually by specifying optional parameter check_hermicity = false.

source
YaoBlocks.ConstGate.@const_gateMacro
@const_gate <gate name> = <expr>
+ 1.0 + 0.0im

But you can also specify the target bit configuration you want to collapse to with keyword resetto.

```jldoctest; setup=:(using Yao) julia> m = Measure(4; resetto=bit"0101") Measure(4;postprocess=ResetTo{BitStr{4,Int64}}(0101 ₍₂₎))

julia> m.postprocess ResetTo{BitStr{4,Int64}}(0101 ₍₂₎)```

source
YaoBlocks.ProjectorType
struct Projector{D, T, AT<:(AbstractArrayReg{D, T})} <: PrimitiveBlock{D}

Projection operator to target state psi.

Definition

projector(s) defines the following operator.

\[|s⟩ → |s⟩⟨s|\]

source
YaoBlocks.ReflectGateType
ReflectGate{D, T, Tt, AT<:AbstractArrayReg{D, T}} = TimeEvolution{D,Tt,Projector{D,T,AT}}

Let |v⟩ be a quantum state vector, a reflection gate is a unitary operator that defined as the following operation.

\[|v⟩ → 1 - (1-exp(-iθ)) |v⟩⟨v|\]

When $θ = π$, it defines a standard reflection gate $1-2|v⟩⟨v|$.

source
YaoBlocks.RotationGateType
RotationGate{D,T,GT<:AbstractBlock{D}} <: PrimitiveBlock{D}

RotationGate, with GT both hermitian and isreflexive.

Definition

Expression rot(G, θ) defines the following gate

\[\cos \frac{\theta}{2}I - i \sin \frac{\theta}{2} G\]

source
YaoBlocks.TimeEvolutionType
TimeEvolution{D, TT, GT} <: PrimitiveBlock{D}

TimeEvolution, where GT is block type. input matrix should be hermitian.

Note

TimeEvolution contructor check hermicity of the input block by default, but sometimes it can be slow. Turn off the check manually by specifying optional parameter check_hermicity = false.

source
YaoBlocks.ConstGate.@const_gateMacro
@const_gate <gate name> = <expr>
 @const_gate <gate name>::<type> = <expr>
-@const_gate <gate>::<type>

This macro simplify the definition of a constant gate. It will automatically bind the matrix form to a constant which will reduce memory allocation in the runtime.

Examples

@const_gate X = ComplexF64[0 1;1 0]

or

@const_gate X::ComplexF64 = [0 1;1 0]

You can bind new element types by simply re-declare with a type annotation.

@const_gate X::ComplexF32
source

Composite Blocks

Composite blocks are subtypes of CompositeBlock, they are the composition of blocks.

We provide the following composite blocks:

YaoBlocks.AbstractAddType
AbstractAdd{D} <: CompositeBlock{D}

The abstract add interface, aimed to support Hamiltonian types.

Required Interfaces

  • chsubblocks
  • subblocks

Provides

  • unsafe_apply! and its backward
  • mat and its backward
  • adjoint
  • occupied_locs
  • getindex over dit strings
  • ishermitian
source
YaoBlocks.AddType
Add{D} <: AbstractAdd{D}
+@const_gate <gate>::<type>

This macro simplify the definition of a constant gate. It will automatically bind the matrix form to a constant which will reduce memory allocation in the runtime.

Examples

@const_gate X = ComplexF64[0 1;1 0]

or

@const_gate X::ComplexF64 = [0 1;1 0]

You can bind new element types by simply re-declare with a type annotation.

@const_gate X::ComplexF32
source

Composite Blocks

Composite blocks are subtypes of CompositeBlock, they are the composition of blocks.

We provide the following composite blocks:

YaoBlocks.AbstractAddType
AbstractAdd{D} <: CompositeBlock{D}

The abstract add interface, aimed to support Hamiltonian types.

Required Interfaces

  • chsubblocks
  • subblocks

Provides

  • unsafe_apply! and its backward
  • mat and its backward
  • adjoint
  • occupied_locs
  • getindex over dit strings
  • ishermitian
source
YaoBlocks.AddType
Add{D} <: AbstractAdd{D}
 Add(blocks::AbstractBlock...) -> Add

Type for block addition.

julia> X + X
 nqubits: 1
 +
 ├─ X
-└─ X
source
YaoBlocks.CachedBlockType
CachedBlock{ST, BT, D} <: TagBlock{BT, D}

A label type that tags an instance of type BT. It forwards every methods of the block it contains, except mat and apply!, it will cache the matrix form whenever the program has.

source
YaoBlocks.ChainBlockType
ChainBlock{D} <: CompositeBlock{D}

ChainBlock is a basic construct tool to create user defined blocks horizontically. It is a Vector like composite type.

source
YaoBlocks.ControlBlockType

A control block is a composite block that applies a block when the control qubits are all ones.

Note

If control qubit index is negative, it means the inverse control, i.e., the block is applied when the control qubit is zero.

Fields

  • n::Int64

  • ctrl_locs::NTuple{C, Int64} where C

  • ctrl_config::NTuple{C, Int64} where C

  • content::AbstractBlock

  • locs::NTuple{M, Int64} where M

source
YaoBlocks.DaggeredType
Daggered{BT, D} <: TagBlock{BT,D}

Wrapper block allowing to execute the inverse of a block of quantum circuit.

source
YaoBlocks.DaggeredMethod
Daggered(block)

Create a Daggered block. Let $G$ be a input block, G' or Daggered(block) in code represents $G^\dagger$.

Examples

The inverse QFT is not hermitian, thus it will be tagged with a Daggered block.

julia> A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1))));
+└─ X
source
YaoBlocks.CachedBlockType
CachedBlock{ST, BT, D} <: TagBlock{BT, D}

A label type that tags an instance of type BT. It forwards every methods of the block it contains, except mat and apply!, it will cache the matrix form whenever the program has.

source
YaoBlocks.ChainBlockType
ChainBlock{D} <: CompositeBlock{D}

ChainBlock is a basic construct tool to create user defined blocks horizontically. It is a Vector like composite type.

source
YaoBlocks.ControlBlockType

A control block is a composite block that applies a block when the control qubits are all ones.

Note

If control qubit index is negative, it means the inverse control, i.e., the block is applied when the control qubit is zero.

Fields

  • n::Int64

  • ctrl_locs::NTuple{C, Int64} where C

  • ctrl_config::NTuple{C, Int64} where C

  • content::AbstractBlock

  • locs::NTuple{M, Int64} where M

source
YaoBlocks.DaggeredType
Daggered{BT, D} <: TagBlock{BT,D}

Wrapper block allowing to execute the inverse of a block of quantum circuit.

source
YaoBlocks.DaggeredMethod
Daggered(block)

Create a Daggered block. Let $G$ be a input block, G' or Daggered(block) in code represents $G^\dagger$.

Examples

The inverse QFT is not hermitian, thus it will be tagged with a Daggered block.

julia> A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1))));
 
 julia> B(n, i) = chain(n, i==j ? put(i=>H) : A(j, i) for j in i:n);
 
@@ -57,8 +57,8 @@
 julia> YaoBlocks.mat(x::QFT) = mat(circuit(x));
 
 julia> QFT(2)'
- [†]QFT
source
YaoBlocks.KronBlockType
KronBlock{D,M,MT<:NTuple{M,Any}} <: CompositeBlock{D}

composite block that combine blocks by kronecker product.

source
YaoBlocks.OnLevelsType
OnLevels{D, Ds, T <: AbstractBlock{Ds}} <: TagBlock{T, D}

Define a gate that is applied to a subset of levels.

Fields

  • gate: the gate to be applied.
  • levels: the levels to apply the gate to.
source
YaoBlocks.PSwapType
PSwap = PutBlock{2,2,RotationGate{2,T,G}} where {G<:ConstGate.SWAPGate}
-PSwap(n::Int, locs::Tuple{Int,Int}, θ::Real)

Parametrized swap gate that swaps two qubits with a phase, defined as

\[{\rm SWAP}(θ) = e^{-iθ{\rm SWAP}/2}\]

source
YaoBlocks.PutBlockType
PutBlock{D,C,GT<:AbstractBlock} <: AbstractContainer{GT,D}

Type for putting a block at given locations.

source
YaoBlocks.ScaleType
Scale{S <: Union{Number, Val}, D, BT <: AbstractBlock{D}} <: TagBlock{BT, D}
+ [†]QFT
source
YaoBlocks.KronBlockType
KronBlock{D,M,MT<:NTuple{M,Any}} <: CompositeBlock{D}

composite block that combine blocks by kronecker product.

source
YaoBlocks.OnLevelsType
OnLevels{D, Ds, T <: AbstractBlock{Ds}} <: TagBlock{T, D}

Define a gate that is applied to a subset of levels.

Fields

  • gate: the gate to be applied.
  • levels: the levels to apply the gate to.
source
YaoBlocks.PSwapType
PSwap = PutBlock{2,2,RotationGate{2,T,G}} where {G<:ConstGate.SWAPGate}
+PSwap(n::Int, locs::Tuple{Int,Int}, θ::Real)

Parametrized swap gate that swaps two qubits with a phase, defined as

\[{\rm SWAP}(θ) = e^{-iθ{\rm SWAP}/2}\]

source
YaoBlocks.PutBlockType
PutBlock{D,C,GT<:AbstractBlock} <: AbstractContainer{GT,D}

Type for putting a block at given locations.

source
YaoBlocks.ScaleType
Scale{S <: Union{Number, Val}, D, BT <: AbstractBlock{D}} <: TagBlock{BT, D}
 Scale(factor, block)

Multiply a block with a scalar factor, which can be a number or a Val. If the factor is a number, it is regarded as a parameter that can be changed dynamically. If the factor is a Val, it is regarded as a constant.

Examples

julia> 2 * X
 [scale: 2] X
 
@@ -69,9 +69,9 @@
 [-im] Z
 
 julia> -Z
-[-] Z
source
YaoBlocks.SubroutineType
Subroutine{D, BT <: AbstractBlock, C} <: AbstractContainer{BT, D}

Subroutine node on given locations. This allows you to shoehorn a smaller circuit to a larger one.

source
YaoBlocks.SwapType
Swap = PutBlock{2,2,G} where {G<:ConstGate.SWAPGate}
-Swap(n::Int, locs::Tuple{Int,Int})

Swap gate, which swaps two qubits.

source
YaoBlocks.UnitaryChannelType
UnitaryChannel{D, W<:AbstractVector} <: CompositeBlock{D}
-UnitaryChannel(operators, probs)

Create a unitary channel, where probs is a real vector that sum up to 1.

source

Operations on Blocks

YaoAPI.unsafe_apply!Function
unsafe_apply!(r, block)

Similar to apply!, but will not check the size of the register and block, this is mainly used for overloading new blocks, use at your own risk.

source
YaoAPI.apply!Function
apply!(register, block)

Apply a block (of quantum circuit) to a quantum register.

Note

to overload apply! for a new block, please overload the unsafe_apply! function with same interface. Then the apply! interface will do the size checks on inputs automatically.

Examples

julia> r = zero_state(2)
+[-] Z
source
YaoBlocks.SubroutineType
Subroutine{D, BT <: AbstractBlock, C} <: AbstractContainer{BT, D}

Subroutine node on given locations. This allows you to shoehorn a smaller circuit to a larger one.

source
YaoBlocks.SwapType
Swap = PutBlock{2,2,G} where {G<:ConstGate.SWAPGate}
+Swap(n::Int, locs::Tuple{Int,Int})

Swap gate, which swaps two qubits.

source
YaoBlocks.UnitaryChannelType
UnitaryChannel{D, W<:AbstractVector} <: CompositeBlock{D}
+UnitaryChannel(operators, probs)

Create a unitary channel, where probs is a real vector that sum up to 1.

source

Operations on Blocks

YaoAPI.unsafe_apply!Function
unsafe_apply!(r, block)

Similar to apply!, but will not check the size of the register and block, this is mainly used for overloading new blocks, use at your own risk.

source
YaoAPI.apply!Function
apply!(register, block)

Apply a block (of quantum circuit) to a quantum register.

Note

to overload apply! for a new block, please overload the unsafe_apply! function with same interface. Then the apply! interface will do the size checks on inputs automatically.

Examples

julia> r = zero_state(2)
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 2/2
     nlevel: 2
@@ -92,20 +92,20 @@
  01 ₍₂₎
  01 ₍₂₎
  01 ₍₂₎
- 01 ₍₂₎
source
YaoBlocks.applyFunction
apply(register, block)

The non-inplace version of applying a block (of quantum circuit) to a quantum register. Check apply! for the faster inplace version.

source
YaoAPI.getiparamsFunction
getiparams(block)

Returns the intrinsic parameters of node block, default is an empty tuple.

Examples

julia> getiparams(Rx(0.1))
-0.1
source
YaoAPI.render_paramsFunction
render_params(r::AbstractBlock, params)

This function renders the input parameter to a consumable type to r. params can be a number or a symbol like :zero and :random.

Examples

julia> collect(render_params(Rx(0.1), :zero))
+ 01 ₍₂₎
source
YaoBlocks.applyFunction
apply(register, block)

The non-inplace version of applying a block (of quantum circuit) to a quantum register. Check apply! for the faster inplace version.

source
YaoAPI.getiparamsFunction
getiparams(block)

Returns the intrinsic parameters of node block, default is an empty tuple.

Examples

julia> getiparams(Rx(0.1))
+0.1
source
YaoAPI.render_paramsFunction
render_params(r::AbstractBlock, params)

This function renders the input parameter to a consumable type to r. params can be a number or a symbol like :zero and :random.

Examples

julia> collect(render_params(Rx(0.1), :zero))
 1-element Vector{Float64}:
- 0.0
source
YaoAPI.nparametersFunction
nparameters(block) -> Int

Return number of parameters in block. See also niparams.

Examples

julia> nparameters(chain(Rx(0.1), Rz(0.2)))
-2
source
YaoAPI.occupied_locsFunction
occupied_locs(x)

Return a tuple of occupied locations of x.

Examples

julia> occupied_locs(kron(5, 1=>X, 3=>X))
+ 0.0
source
YaoAPI.nparametersFunction
nparameters(block) -> Int

Return number of parameters in block. See also niparams.

Examples

julia> nparameters(chain(Rx(0.1), Rz(0.2)))
+2
source
YaoAPI.occupied_locsFunction
occupied_locs(x)

Return a tuple of occupied locations of x.

Examples

julia> occupied_locs(kron(5, 1=>X, 3=>X))
 (1, 3)
 
 julia> occupied_locs(kron(5, 1=>X, 3=>I2))
-(1,)
source
YaoAPI.print_blockFunction
print_block(io, block)

Define how blocks are printed as text in one line.

Examples

julia> print_block(stdout, X)
+(1,)
source
YaoAPI.print_blockFunction
print_block(io, block)

Define how blocks are printed as text in one line.

Examples

julia> print_block(stdout, X)
 X
 
 julia> print_block(stdout, put(2, 1=>X))
-put on (1)
source
YaoAPI.apply_back!Function
apply_back!((ψ, ∂L/∂ψ*), circuit::AbstractBlock, collector) -> AbstractRegister

back propagate and calculate the gradient ∂L/∂θ = 2Re(∂L/∂ψ⋅∂ψ/∂θ), given ∂L/∂ψ. ψ is the output register, ∂L/∂ψ* should also be register type.

Note: gradients are stored in Diff blocks, it can be access by either diffblock.grad or gradient(circuit). Note2: now apply_back! returns the inversed gradient!

source
YaoAPI.mat_back!Function
mat_back!(T, rb::AbstractBlock, adjy, collector)

Back propagate the matrix gradients.

source

Error and Exceptions

Extending Blocks

Blocks are defined as a sub-type system inside Julia, you could extend it by defining new Julia types by subtyping abstract types we provide. But we also provide some handy tools to help you create your own blocks.

Define Custom Constant Blocks

Constant blocks are used quite often and in numerical simulation we would expect it to be a real constant in the program, which means it won't allocate new memory when we try to get its matrix for several times, and it won't change with parameters.

In Yao, you can simply define a constant block with @const_gate, with the corresponding matrix:


julia> @const_gate Rand = rand(ComplexF64, 4, 4)

This will automatically create a type RandGate{T} and a constant binding Rand to the instance of RandGate{ComplexF64}, and it will also bind a Julia constant for the given matrix, so when you call mat(Rand), no allocation will happen.

julia> @allocated mat(Rand)ERROR: UndefVarError: `mat` not defined in `Main`
+put on (1)
source
YaoAPI.apply_back!Function
apply_back!((ψ, ∂L/∂ψ*), circuit::AbstractBlock, collector) -> AbstractRegister

back propagate and calculate the gradient ∂L/∂θ = 2Re(∂L/∂ψ⋅∂ψ/∂θ), given ∂L/∂ψ. ψ is the output register, ∂L/∂ψ* should also be register type.

Note: gradients are stored in Diff blocks, it can be access by either diffblock.grad or gradient(circuit). Note2: now apply_back! returns the inversed gradient!

source
YaoAPI.mat_back!Function
mat_back!(T, rb::AbstractBlock, adjy, collector)

Back propagate the matrix gradients.

source

Error and Exceptions

Extending Blocks

Blocks are defined as a sub-type system inside Julia, you could extend it by defining new Julia types by subtyping abstract types we provide. But we also provide some handy tools to help you create your own blocks.

Define Custom Constant Blocks

Constant blocks are used quite often and in numerical simulation we would expect it to be a real constant in the program, which means it won't allocate new memory when we try to get its matrix for several times, and it won't change with parameters.

In Yao, you can simply define a constant block with @const_gate, with the corresponding matrix:


julia> @const_gate Rand = rand(ComplexF64, 4, 4)

This will automatically create a type RandGate{T} and a constant binding Rand to the instance of RandGate{ComplexF64}, and it will also bind a Julia constant for the given matrix, so when you call mat(Rand), no allocation will happen.

julia> @allocated mat(Rand)ERROR: UndefVarError: `mat` not defined in `Main`
 Suggestion: check for spelling errors or missing imports.
 Hint: a global variable of this name also exists in YaoAPI.
 Hint: a global variable of this name also exists in YaoBlocks.
@@ -130,18 +130,18 @@
     return r
 end

In Yao, this interface allows us to provide more aggressive specialization on different patterns of quantum circuits to accelerate the simulation etc.

Define Parameters

If you want to use some member of the block to be parameters, you need to declare them explicitly

niparams(::Type{<:PhaseGate}) = 1
 getiparams(x::PhaseGate) = x.theta
-setiparams!(r::PhaseGate, param::Real) = (r.theta = param; r)

Define Adjoint

Since blocks are actually quantum operators, it makes sense to call their adjoint as well. We provide Daggered for general purpose, but some blocks may have more specific transformation rules for adjoints, e.g

Base.adjoint(x::PhaseGate) = PhaseGate(-x.theta)

Define Cache Keys

To enable cache, you should define cache_key, e.g for phase gate, we only cares about its phase, instead of the whole instance

cache_key(gate::PhaseGate) = gate.theta

APIs

Base.:|>Method
|>(register, circuit) -> register

Apply a quantum circuits to register, which modifies the register directly.

Example

julia> arrayreg(bit"0") |> X |> Y
Warning

|> is equivalent to apply!, which means it has side effects. You need to use apply if you do not want to change it in-place.

source
Base.kronMethod
kron(n, locs_and_blocks::Pair{<:Any, <:AbstractBlock}...) -> KronBlock

Returns a n-qudit KronBlock. The inputs contains a list of location-block pairs, where a location can be an integer or a range. It is conceptually a chain of put block without address conflicts, but it has a richer type information that can be useful for various purposes such as more efficient mat function.

Let $I$ be a $2\times 2$ identity matrix, $G$ and $H$ be two $2\times 2$ matrix, the matrix representation of kron(n, i=>G, j=>H) (assume $j > i$) is defined as

\[I^{\otimes n-j} \otimes H \otimes I^{\otimes j-i-1} \otimes G \otimes I^{i-1}\]

For multiple locations, the expression can be complicated.

Examples

Use kron to construct a KronBlock, it will put an X gate on the 1st qubit, and a Y gate on the 3rd qubit.

julia> kron(4, 1=>X, 3=>Y)
+setiparams!(r::PhaseGate, param::Real) = (r.theta = param; r)

Define Adjoint

Since blocks are actually quantum operators, it makes sense to call their adjoint as well. We provide Daggered for general purpose, but some blocks may have more specific transformation rules for adjoints, e.g

Base.adjoint(x::PhaseGate) = PhaseGate(-x.theta)

Define Cache Keys

To enable cache, you should define cache_key, e.g for phase gate, we only cares about its phase, instead of the whole instance

cache_key(gate::PhaseGate) = gate.theta

APIs

Base.:|>Method
|>(register, circuit) -> register

Apply a quantum circuits to register, which modifies the register directly.

Example

julia> arrayreg(bit"0") |> X |> Y
Warning

|> is equivalent to apply!, which means it has side effects. You need to use apply if you do not want to change it in-place.

source
Base.kronMethod
kron(n, locs_and_blocks::Pair{<:Any, <:AbstractBlock}...) -> KronBlock

Returns a n-qudit KronBlock. The inputs contains a list of location-block pairs, where a location can be an integer or a range. It is conceptually a chain of put block without address conflicts, but it has a richer type information that can be useful for various purposes such as more efficient mat function.

Let $I$ be a $2\times 2$ identity matrix, $G$ and $H$ be two $2\times 2$ matrix, the matrix representation of kron(n, i=>G, j=>H) (assume $j > i$) is defined as

\[I^{\otimes n-j} \otimes H \otimes I^{\otimes j-i-1} \otimes G \otimes I^{i-1}\]

For multiple locations, the expression can be complicated.

Examples

Use kron to construct a KronBlock, it will put an X gate on the 1st qubit, and a Y gate on the 3rd qubit.

julia> kron(4, 1=>X, 3=>Y)
 nqubits: 4
 kron
 ├─ 1=>X
-└─ 3=>Y
source
Base.kronMethod
kron(blocks::AbstractBlock...)
 kron(n, itr)

Return a KronBlock, with total number of qubits n, and blocks should use all the locations on n wires in quantum circuits.

Examples

You can use kronecker product to composite small blocks to a large blocks.

julia> kron(X, Y, Z, Z)
 nqubits: 4
 kron
 ├─ 1=>X
 ├─ 2=>Y
 ├─ 3=>Z
-└─ 4=>Z
source
Base.kronMethod
kron(blocks...) -> f(n)
 kron(itr) -> f(n)

Return a lambda, which will take the total number of qubits as input.

Examples

If you don't know the number of qubit yet, or you are just too lazy, it is fine.

julia> kron(put(1=>X) for _ in 1:2)
 (n -> kron(n, ((n  ->  put(n, 1 => X)), (n  ->  put(n, 1 => X)))...))
 
@@ -152,7 +152,7 @@
 └─ 2=>X
 
 julia> kron(1=>X, 3=>Y)
-(n -> kron(n, (1 => X, 3 => Y)...))
source
Base.repeatMethod
repeat(n, subblock::AbstractBlock[, locs]) -> RepeatedBlock{n}

Create a n-qudit RepeatedBlock block, which is conceptually a [kron] block with all gates being the same. If locs is provided, repeat on locs, otherwise repeat on all locations. Let $G$ be a $2\times 2$ matrix, the matrix representation of repeat(n, X) is

\[X^{\otimes n}\]

The RepeatedBlock can be used to accelerate repeated applying certain gate types: X, Y, Z, S, T, Sdag, and Tdag.

Examples

This will create a repeat block which puts 4 X gates on each location.

julia> repeat(4, X)
+(n -> kron(n, (1 => X, 3 => Y)...))
source
Base.repeatMethod
repeat(n, subblock::AbstractBlock[, locs]) -> RepeatedBlock{n}

Create a n-qudit RepeatedBlock block, which is conceptually a [kron] block with all gates being the same. If locs is provided, repeat on locs, otherwise repeat on all locations. Let $G$ be a $2\times 2$ matrix, the matrix representation of repeat(n, X) is

\[X^{\otimes n}\]

The RepeatedBlock can be used to accelerate repeated applying certain gate types: X, Y, Z, S, T, Sdag, and Tdag.

Examples

This will create a repeat block which puts 4 X gates on each location.

julia> repeat(4, X)
 nqubits: 4
 repeat on (1, 2, 3, 4)
 └─ X

You can also specify the location

julia> repeat(4, X, (1, 2))
@@ -178,13 +178,13 @@
   0.002252 seconds (5 allocations: 656 bytes)
 
 julia> @time apply!(reg, chain([put(20, i=>X) for i=1:20]));
-  0.049362 seconds (82.48 k allocations: 4.694 MiB, 47.11% compilation time)
source
YaoAPI.dispatch!Method
dispatch!(x::AbstractBlock, collection)

Dispatch parameters in collection to block tree x.

Note

it will try to dispatch the parameters in collection first.

source
YaoAPI.expectMethod
expect(op::AbstractBlock, reg) -> Real
+  0.049362 seconds (82.48 k allocations: 4.694 MiB, 47.11% compilation time)
source
YaoAPI.dispatch!Method
dispatch!(x::AbstractBlock, collection)

Dispatch parameters in collection to block tree x.

Note

it will try to dispatch the parameters in collection first.

source
YaoAPI.expectMethod
expect(op::AbstractBlock, reg) -> Real
 expect(op::AbstractBlock, reg => circuit) -> Real
-expect(op::AbstractBlock, density_matrix) -> Real

Get the expectation value of an operator, the second parameter can be a register reg or a pair of input register and circuit reg => circuit.

expect'(op::AbstractBlock, reg=>circuit) -> Pair expect'(op::AbstractBlock, reg) -> AbstracRegister

Obtain the gradient with respect to registers and circuit parameters. For pair input, the second return value is a pair of gψ=>gparams, with the gradient of input state and gparams the gradients of circuit parameters. For register input, the return value is a register.

Note

For batched register, expect(op, reg=>circuit) returns a vector of size number of batch as output. However, one can not differentiate over a vector loss, so expect'(op, reg=>circuit) accumulates the gradient over batch, rather than returning a batched gradient of parameters.

source
YaoAPI.getiparamsMethod
getiparams(block)

Returns the intrinsic parameters of node block, default is an empty tuple.

source
YaoAPI.matMethod
mat([T=ComplexF64], blk)

Returns the matrix form of given block.

source
YaoAPI.matMethod
mat(A::GeneralMatrixBlock)

Return the matrix of general matrix block.

Warn

Instead of converting it to the default data type ComplexF64, this will return its contained matrix.

source
YaoAPI.operator_fidelityMethod
operator_fidelity(b1::AbstractBlock, b2::AbstractBlock) -> Number

Operator fidelity defined as

\[F^2 = \frac{1}{d}\left[{\rm Tr}(b1^\dagger b2)\right]\]

Here, d is the size of the Hilbert space. Note this quantity is independant to global phase. See arXiv: 0803.2940v2, Equation (2) for reference.

source
YaoAPI.parametersMethod
parameters(block)

Returns all the parameters contained in block tree with given root block.

source
YaoAPI.setiparams!Function
setiparams!([f], block, itr)
-setiparams!([f], block, params...)

Set the parameters of block. When f is provided, set parameters of block to the value in collection mapped by f. iter can be an iterator or a symbol, the symbol can be :zero, :random.

source
YaoAPI.subblocksMethod
subblocks(x)

Returns an iterator of the sub-blocks of a composite block. Default is empty.

source
YaoBlocks.applyMethod
apply(register, block)

The non-inplace version of applying a block (of quantum circuit) to a quantum register. Check apply! for the faster inplace version.

source
YaoBlocks.applymatrixMethod
applymatrix(g::AbstractBlock) -> Matrix

Transform the apply! function of specific block to dense matrix.

source
YaoBlocks.cacheFunction
cache(x[, level=1; recursive=false])

Create a CachedBlock with given block x, which will cache the matrix of x for the first time it calls mat, and use the cached matrix in the following calculations.

Examples

julia> cache(control(3, 1, 2=>X))
+expect(op::AbstractBlock, density_matrix) -> Real

Get the expectation value of an operator, the second parameter can be a register reg or a pair of input register and circuit reg => circuit.

expect'(op::AbstractBlock, reg=>circuit) -> Pair expect'(op::AbstractBlock, reg) -> AbstracRegister

Obtain the gradient with respect to registers and circuit parameters. For pair input, the second return value is a pair of gψ=>gparams, with the gradient of input state and gparams the gradients of circuit parameters. For register input, the return value is a register.

Note

For batched register, expect(op, reg=>circuit) returns a vector of size number of batch as output. However, one can not differentiate over a vector loss, so expect'(op, reg=>circuit) accumulates the gradient over batch, rather than returning a batched gradient of parameters.

source
YaoAPI.getiparamsMethod
getiparams(block)

Returns the intrinsic parameters of node block, default is an empty tuple.

source
YaoAPI.matMethod
mat([T=ComplexF64], blk)

Returns the matrix form of given block.

source
YaoAPI.matMethod
mat(A::GeneralMatrixBlock)

Return the matrix of general matrix block.

Warn

Instead of converting it to the default data type ComplexF64, this will return its contained matrix.

source
YaoAPI.operator_fidelityMethod
operator_fidelity(b1::AbstractBlock, b2::AbstractBlock) -> Number

Operator fidelity defined as

\[F^2 = \frac{1}{d}\left[{\rm Tr}(b1^\dagger b2)\right]\]

Here, d is the size of the Hilbert space. Note this quantity is independant to global phase. See arXiv: 0803.2940v2, Equation (2) for reference.

source
YaoAPI.parametersMethod
parameters(block)

Returns all the parameters contained in block tree with given root block.

source
YaoAPI.setiparams!Function
setiparams!([f], block, itr)
+setiparams!([f], block, params...)

Set the parameters of block. When f is provided, set parameters of block to the value in collection mapped by f. iter can be an iterator or a symbol, the symbol can be :zero, :random.

source
YaoAPI.subblocksMethod
subblocks(x)

Returns an iterator of the sub-blocks of a composite block. Default is empty.

source
YaoBlocks.applyMethod
apply(register, block)

The non-inplace version of applying a block (of quantum circuit) to a quantum register. Check apply! for the faster inplace version.

source
YaoBlocks.applymatrixMethod
applymatrix(g::AbstractBlock) -> Matrix

Transform the apply! function of specific block to dense matrix.

source
YaoBlocks.cacheFunction
cache(x[, level=1; recursive=false])

Create a CachedBlock with given block x, which will cache the matrix of x for the first time it calls mat, and use the cached matrix in the following calculations.

Examples

julia> cache(control(3, 1, 2=>X))
 nqubits: 3
 [cached] control(1)
    └─ (2,) X
@@ -195,7 +195,7 @@
 chain
 └─ [cached] control(1)
       └─ (2,) X
-
source
YaoBlocks.chainMethod
chain(n)

Return an empty ChainBlock which can be used like a list of blocks.

Examples

julia> chain(2)
 nqubits: 2
 chain
 
@@ -204,7 +204,7 @@
 nqudits: 2
 chain
 
-
source
YaoBlocks.chainMethod
chain(blocks...) -> ChainBlock
 chain(n) -> ChainBlock

Return a ChainBlock which chains a list of blocks with the same number of qudits. Let $G_i$ be a sequence of n-qudit blocks, the matrix representation of block chain(G_1, G_2, ..., G_m) is

\[G_m G_{m-1}\ldots G_1\]

It is almost equivalent to matrix multiplication except the order is reversed. We make its order different from regular matrix multiplication because quantum circuits can be represented more naturally in this form.

Examples

julia> chain(X, Y, Z)
 nqubits: 1
 chain
@@ -220,7 +220,7 @@
 ├─ put on (2)
 │  └─ Y
 └─ control(2)
-   └─ (1,) X
source
YaoBlocks.chmeasureoperatorMethod
chmeasureoperator(m::Measure, op::AbstractBlock)

change the measuring operator. It will also discard existing measuring results.

source
YaoBlocks.cleanupMethod
cleanup(entries::EntryTable; zero_threshold=0.0)

Clean up the entry table by 1) sort entries, 2) merge items and 3) clean up zeros. Any value with amplitude ≤ zero_threshold will be regarded as zero.

julia> et = EntryTable([bit"000",bit"011",bit"101",bit"101",bit"011",bit"110",bit"110",bit"011",], [1.0 + 0.0im,-1, 1,1,1,-1,1,1,-1])
+   └─ (1,) X
source
YaoBlocks.chmeasureoperatorMethod
chmeasureoperator(m::Measure, op::AbstractBlock)

change the measuring operator. It will also discard existing measuring results.

source
YaoBlocks.cleanupMethod
cleanup(entries::EntryTable; zero_threshold=0.0)

Clean up the entry table by 1) sort entries, 2) merge items and 3) clean up zeros. Any value with amplitude ≤ zero_threshold will be regarded as zero.

julia> et = EntryTable([bit"000",bit"011",bit"101",bit"101",bit"011",bit"110",bit"110",bit"011",], [1.0 + 0.0im,-1, 1,1,1,-1,1,1,-1])
 EntryTable{DitStr{2, 3, Int64}, ComplexF64}:
   000 ₍₂₎   1.0 + 0.0im
   011 ₍₂₎   -1.0 + 0.0im
@@ -236,17 +236,17 @@
 EntryTable{DitStr{2, 3, Int64}, ComplexF64}:
   000 ₍₂₎   1.0 + 0.0im
   011 ₍₂₎   1.0 + 0.0im
-  101 ₍₂₎   2.0 + 0.0im
source
YaoBlocks.cnotMethod
cnot([n, ]ctrl_locs, location)

Return a speical ControlBlock, aka CNOT gate with number of active qubits n and locs of control qubits ctrl_locs, and location of X gate.

Examples

julia> cnot(3, (2, 3), 1)
+  101 ₍₂₎   2.0 + 0.0im
source
YaoBlocks.cnotMethod
cnot([n, ]ctrl_locs, location)

Return a speical ControlBlock, aka CNOT gate with number of active qubits n and locs of control qubits ctrl_locs, and location of X gate.

Examples

julia> cnot(3, (2, 3), 1)
 nqubits: 3
 control(2, 3)
 └─ (1,) X
 
 julia> cnot(2, 1)
-(n -> cnot(n, 2, 1))
source
YaoBlocks.controlMethod
control(ctrl_locs, target) -> f(n)

Return a lambda that takes the number of total active qubits as input. See also control.

Examples

julia> control((2, 3), 1=>X)
+(n -> cnot(n, 2, 1))
source
YaoBlocks.controlMethod
control(ctrl_locs, target) -> f(n)

Return a lambda that takes the number of total active qubits as input. See also control.

Examples

julia> control((2, 3), 1=>X)
 (n -> control(n, (2, 3), 1 => X))
 
 julia> control(2, 1=>X)
-(n -> control(n, 2, 1 => X))
source
YaoBlocks.controlMethod
control(n, ctrl_locs, locations => subblock)

Return a n-qubit ControlBlock, where the control locations ctrl_locs and the subblock locations in the third argument can be an integer, a tuple or a range, and the size of the subblock should match the length of locations. Let $I$ be the $2 \times 2$ identity matrix, $G$ be a $2 \times 2$ subblock, $P_0=|0\rangle\langle 0|$ and $P_1=|1\rangle\langle 1|$ be two single qubit projection operators to subspace $|0\rangle$ and $|1\rangle$, $i$ and $j$ be two integers that $i>j$. The matrix representation of control(n, i, j=>G) is

\[\begin{align} +(n -> control(n, 2, 1 => X))

source
YaoBlocks.controlMethod
control(n, ctrl_locs, locations => subblock)

Return a n-qubit ControlBlock, where the control locations ctrl_locs and the subblock locations in the third argument can be an integer, a tuple or a range, and the size of the subblock should match the length of locations. Let $I$ be the $2 \times 2$ identity matrix, $G$ be a $2 \times 2$ subblock, $P_0=|0\rangle\langle 0|$ and $P_1=|1\rangle\langle 1|$ be two single qubit projection operators to subspace $|0\rangle$ and $|1\rangle$, $i$ and $j$ be two integers that $i>j$. The matrix representation of control(n, i, j=>G) is

\[\begin{align} &I^{\otimes n-i} P_0 \otimes I^{\otimes i-j-1} \otimes I\otimes I^{\otimes j-1} +\\ & I^{\otimes n-i} P_1 \otimes I^{\otimes i-j-1} \otimes G\otimes I^{\otimes j-1} @@ -258,14 +258,14 @@ julia> control(4, 1, 3=>X) nqubits: 4 control(1) -└─ (3,) X

source
YaoBlocks.cunmatFunction
cunmat(nbit::Int, cbits::NTuple{C, Int}, cvals::NTuple{C, Int}, U0::AbstractMatrix, locs::NTuple{M, Int}) where {C, M} -> AbstractMatrix

control-unitary matrix

source
YaoBlocks.czMethod
cz([n, ]ctrl_locs, location)

Return a special ControlBlock, aka CZ gate with number of active qubits n and locs of control qubits ctrl_locs, and location of Z gate. See also cnot.

Examples

julia> cz(2, 1, 2)
+└─ (3,) X
source
YaoBlocks.cunmatFunction
cunmat(nbit::Int, cbits::NTuple{C, Int}, cvals::NTuple{C, Int}, U0::AbstractMatrix, locs::NTuple{M, Int}) where {C, M} -> AbstractMatrix

control-unitary matrix

source
YaoBlocks.czMethod
cz([n, ]ctrl_locs, location)

Return a special ControlBlock, aka CZ gate with number of active qubits n and locs of control qubits ctrl_locs, and location of Z gate. See also cnot.

Examples

julia> cz(2, 1, 2)
 nqubits: 2
 control(1)
-└─ (2,) Z
source
YaoBlocks.dispatchMethod
dispatch(x::AbstractBlock, collection)

Dispatch parameters in collection to block tree x, the generic non-inplace version.

Note

it will try to dispatch the parameters in collection first.

source
YaoBlocks.dump_gateFunction
dump_gate(blk::AbstractBlock) -> Expr

convert a gate to a YaoScript expression for serization. The fallback is GateTypeName(fields...)

source
YaoBlocks.eigenbasisMethod
eigenbasis(op::AbstractBlock)

Return the eigenvalue and eigenvectors of target operator. By applying eigenvector' to target state, one can swith the basis to the eigenbasis of this operator. However, eigenvalues does not have a specific form.

source
YaoBlocks.gate_exprMethod
gate_expr(::Val{G}, args, info)

Obtain the gate constructior from its YaoScript expression. G is a symbol for the gate type, the default constructor is G(args...). info contains the informations about the number of qubit and Yao version.

source
YaoBlocks.getcolMethod
getcol(csc::SDparseMatrixCSC, icol::Int) -> (View, View)

get specific col of a CSC matrix, returns a slice of (rowval, nzval)

source
YaoBlocks.igateMethod
igate(n::Int; nlevel=2)

The constructor for IdentityGate. Let $I_d$ be a $d \times d$ identity matrix, igate(n; nlevel=d) is defined as $I_d^{\otimes n}$.

Examples

julia> igate(2)
+└─ (2,) Z
source
YaoBlocks.dispatchMethod
dispatch(x::AbstractBlock, collection)

Dispatch parameters in collection to block tree x, the generic non-inplace version.

Note

it will try to dispatch the parameters in collection first.

source
YaoBlocks.dump_gateFunction
dump_gate(blk::AbstractBlock) -> Expr

convert a gate to a YaoScript expression for serization. The fallback is GateTypeName(fields...)

source
YaoBlocks.eigenbasisMethod
eigenbasis(op::AbstractBlock)

Return the eigenvalue and eigenvectors of target operator. By applying eigenvector' to target state, one can swith the basis to the eigenbasis of this operator. However, eigenvalues does not have a specific form.

source
YaoBlocks.gate_exprMethod
gate_expr(::Val{G}, args, info)

Obtain the gate constructior from its YaoScript expression. G is a symbol for the gate type, the default constructor is G(args...). info contains the informations about the number of qubit and Yao version.

source
YaoBlocks.getcolMethod
getcol(csc::SDparseMatrixCSC, icol::Int) -> (View, View)

get specific col of a CSC matrix, returns a slice of (rowval, nzval)

source
YaoBlocks.igateMethod
igate(n::Int; nlevel=2)

The constructor for IdentityGate. Let $I_d$ be a $d \times d$ identity matrix, igate(n; nlevel=d) is defined as $I_d^{\otimes n}$.

Examples

julia> igate(2)
 igate(2)
 
 julia> igate(2; nlevel=3)
-igate(2;nlevel=3)
source
YaoBlocks.iscleanMethod
isclean(entries::EntryTable; zero_threshold=0.0)

Return true if the entries are ordered, unique and amplitudes are nonzero. Any value with amplitude ≤ zero_threshold will be regarded as zero.

source
YaoBlocks.map_addressFunction
map_address(block::AbstractBlock, info::AddressInfo) -> AbstractBlock

map the locations in block to target locations.

Example

map_address can be used to embed a sub-circuit to a larger one.

julia> c = chain(5, repeat(H, 1:5), put(2=>X), kron(1=>X, 3=>Y))
+igate(2;nlevel=3)
source
YaoBlocks.iscleanMethod
isclean(entries::EntryTable; zero_threshold=0.0)

Return true if the entries are ordered, unique and amplitudes are nonzero. Any value with amplitude ≤ zero_threshold will be regarded as zero.

source
YaoBlocks.map_addressFunction
map_address(block::AbstractBlock, info::AddressInfo) -> AbstractBlock

map the locations in block to target locations.

Example

map_address can be used to embed a sub-circuit to a larger one.

julia> c = chain(5, repeat(H, 1:5), put(2=>X), kron(1=>X, 3=>Y))
 nqubits: 5
 chain
 ├─ repeat on (1, 2, 3, 4, 5)
@@ -286,19 +286,19 @@
 │  └─ X
 └─ kron
    ├─ 6=>X
-   └─ 8=>Y
source
YaoBlocks.matblockMethod
matblock(mat_or_block; nlevel=2, tag="matblock(...)")

Create a GeneralMatrixBlock with a matrix m.

Examples

julia> matblock(ComplexF64[0 1;1 0])
 matblock(...)

!!!warn

Instead of converting it to the default data type `ComplexF64`,
-this will return its contained matrix when calling `mat`.
source
YaoBlocks.num_nonzeroFunction
num_nonzero(nbits, nctrls, U, [N])

Return number of nonzero entries of the matrix form of control-U gate. nbits is the number of qubits, and nctrls is the number of control qubits.

source
YaoBlocks.parameters!Method
parameters!(out, block)

Append all the parameters contained in block tree with given root block to out.

source
YaoBlocks.parameters_rangeMethod
parameters_range(block)

Return the range of real parameters present in block.

Note

It may not be the case that length(parameters_range(block)) == nparameters(block).

Example

julia> YaoBlocks.parameters_range(RotationGate(X, 0.1))
+this will return its contained matrix when calling `mat`.
source
YaoBlocks.num_nonzeroFunction
num_nonzero(nbits, nctrls, U, [N])

Return number of nonzero entries of the matrix form of control-U gate. nbits is the number of qubits, and nctrls is the number of control qubits.

source
YaoBlocks.parameters!Method
parameters!(out, block)

Append all the parameters contained in block tree with given root block to out.

source
YaoBlocks.parameters_rangeMethod
parameters_range(block)

Return the range of real parameters present in block.

Note

It may not be the case that length(parameters_range(block)) == nparameters(block).

Example

julia> YaoBlocks.parameters_range(RotationGate(X, 0.1))
 1-element Vector{Tuple{Float64, Float64}}:
- (0.0, 6.283185307179586)
source
YaoBlocks.parse_blockFunction
parse_block(n, ex)

This function parse the julia object ex to a quantum block, it defines the syntax of high level interfaces. ex can be a function takes number of qubits n as input or it can be a pair.

source
YaoBlocks.phaseMethod
phase(theta)

Returns a global phase gate. Defined with following matrix form:

\[e^{iθ} I\]

Examples

You can create a global phase gate with a phase (a real number).

julia> phase(0.1)
-phase(0.1)
source
YaoBlocks.postwalkMethod
postwalk(f, src::AbstractBlock)

Walk the tree and call f after the children are visited.

source
YaoBlocks.print_annotationMethod
print_annotation(io, root, node, child, k)

Print the annotation of k-th child of node, aka the k-th element of subblocks(node).

source
YaoBlocks.print_treeFunction
print_tree(io, root, node[, depth=1, active_levels=()]; kwargs...)

Print the block tree.

Keywords

  • maxdepth: max tree depth to print
  • charset: default is ('├','└','│','─'). See also YaoBlocks.BlockTreeCharSet.
  • title: control whether to print the title, true or false, default is true
source
YaoBlocks.projectionMethod
projection(y::AbstractMatrix, op::AbstractMatrix) -> typeof(y)

Project op to sparse matrix with same sparsity as y.

source
YaoBlocks.parse_blockFunction
parse_block(n, ex)

This function parse the julia object ex to a quantum block, it defines the syntax of high level interfaces. ex can be a function takes number of qubits n as input or it can be a pair.

source
YaoBlocks.phaseMethod
phase(theta)

Returns a global phase gate. Defined with following matrix form:

\[e^{iθ} I\]

Examples

You can create a global phase gate with a phase (a real number).

julia> phase(0.1)
+phase(0.1)
source
YaoBlocks.postwalkMethod
postwalk(f, src::AbstractBlock)

Walk the tree and call f after the children are visited.

source
YaoBlocks.print_annotationMethod
print_annotation(io, root, node, child, k)

Print the annotation of k-th child of node, aka the k-th element of subblocks(node).

source
YaoBlocks.print_treeFunction
print_tree(io, root, node[, depth=1, active_levels=()]; kwargs...)

Print the block tree.

Keywords

  • maxdepth: max tree depth to print
  • charset: default is ('├','└','│','─'). See also YaoBlocks.BlockTreeCharSet.
  • title: control whether to print the title, true or false, default is true
source
YaoBlocks.projectionMethod
projection(y::AbstractMatrix, op::AbstractMatrix) -> typeof(y)

Project op to sparse matrix with same sparsity as y.

source
YaoBlocks.projectorMethod
projector(v::AbstractArrayReg) -> Projector
 

Create a Projector with an quantum state vector v.

Example

julia> projector(rand_state(3))
-|s⟩⟨s|, nqudits = 3
source
YaoBlocks.pswapMethod
pswap(n::Int, i::Int, j::Int, α::Real)
 pswap(i::Int, j::Int, α::Real) -> f(n)

parametrized swap gate.

Examples

julia> pswap(2, 1, 2, 0.1)
 nqubits: 2
 put on (1, 2)
-└─ rot(SWAP, 0.1)
source
YaoBlocks.putMethod
put(pair) -> f(n)

Lazy curried version of put.

Examples

julia> put(1=>X)
-(n -> put(n, 1 => X))
source
YaoBlocks.putMethod
put(n::Int, locations => subblock) => PutBlock

Create a n-qudit PutBlock. The second argument is a pair of locations and subblock, where the locations can be a tuple, an integer or a range and the subblock size should match the length of locations. Let $I$ be a $2\times 2$ identity matrix and $G$ be a $2\times 2$ matrix, the matrix representation of put(n, i=>G) is defined as

\[I^{\otimes n-i} \otimes G \otimes I^{\otimes i-1}\]

For multiple locations, the expression can be complicated, which corresponds to the matrix representation of multi-qubit gate applied on n-qubit space in quantum computing.

Examples

julia> put(4, 1=>X)
+└─ rot(SWAP, 0.1)
source
YaoBlocks.putMethod
put(pair) -> f(n)

Lazy curried version of put.

Examples

julia> put(1=>X)
+(n -> put(n, 1 => X))
source
YaoBlocks.putMethod
put(n::Int, locations => subblock) => PutBlock

Create a n-qudit PutBlock. The second argument is a pair of locations and subblock, where the locations can be a tuple, an integer or a range and the subblock size should match the length of locations. Let $I$ be a $2\times 2$ identity matrix and $G$ be a $2\times 2$ matrix, the matrix representation of put(n, i=>G) is defined as

\[I^{\otimes n-i} \otimes G \otimes I^{\otimes i-1}\]

For multiple locations, the expression can be complicated, which corresponds to the matrix representation of multi-qubit gate applied on n-qubit space in quantum computing.

Examples

julia> put(4, 1=>X)
 nqubits: 4
 put on (1)
 └─ X

If you want to put a multi-qubit gate on specific locations, you need to write down all possible locations.

julia> put(4, (1, 3)=>kron(X, Y))
@@ -306,12 +306,12 @@
 put on (1, 3)
 └─ kron
    ├─ 1=>X
-   └─ 2=>Y

The outter locations creates a scope which make it seems to be a contiguous two qubits for the block inside PutBlock.

Tips

It is better to use subroutine instead of put for large blocks, since put will use the matrix of its contents directly instead of making use of what's in it. put is more efficient for small blocks.

source
YaoBlocks.rand_hermitianMethod
rand_hermitian([T=ComplexF64], N::Int) -> Matrix

Create a random hermitian matrix.

julia> ishermitian(rand_hermitian(2))
-true
source
YaoBlocks.rand_unitaryMethod
rand_unitary([T=ComplexF64], N::Int) -> Matrix

Create a random unitary matrix.

Examples

julia> isunitary(rand_unitary(2))
+   └─ 2=>Y

The outter locations creates a scope which make it seems to be a contiguous two qubits for the block inside PutBlock.

Tips

It is better to use subroutine instead of put for large blocks, since put will use the matrix of its contents directly instead of making use of what's in it. put is more efficient for small blocks.

source
YaoBlocks.rand_hermitianMethod
rand_hermitian([T=ComplexF64], N::Int) -> Matrix

Create a random hermitian matrix.

julia> ishermitian(rand_hermitian(2))
+true
source
YaoBlocks.rand_unitaryMethod
rand_unitary([T=ComplexF64], N::Int) -> Matrix

Create a random unitary matrix.

Examples

julia> isunitary(rand_unitary(2))
 true
 
 julia> eltype(rand_unitary(ComplexF32, 2))
-ComplexF32 (alias for Complex{Float32})
source
YaoBlocks.reflectFunction
reflect(
     v::AbstractArrayReg
 ) -> ReflectGate{D, T, Irrational{:π}, AT} where {D, T, AT<:(AbstractArrayReg{D, T})}
 reflect(
@@ -320,12 +320,12 @@
 ) -> ReflectGate{_A, T, Tt, AT} where {_A, Tt<:Real, T, AT<:(AbstractArrayReg{_A, T})}
 

Create a ReflectGate with respect to an quantum state vector v.

Example

julia> reflect(rand_state(3))
 Time Evolution Δt = π, tol = 1.0e-7
-|s⟩⟨s|, nqudits = 3
source
YaoBlocks.sandwichMethod
sandwich(bra::AbstractRegister, op::AbstractBlock, ket::AbstracRegister) -> Complex

Compute the sandwich function ⟨bra|op|ket⟩.

source
YaoBlocks.setcol!Method
setcol!(csc::SparseMatrixCSC, icol::Int, rowval::AbstractVector, nzval) -> SparseMatrixCSC

set specific col of a CSC matrix

source
YaoBlocks.setiparamsFunction
setiparams([f], block, itr)
-setiparams([f], block, params...)

Set the parameters of block, the non-inplace version. When f is provided, set parameters of block to the value in collection mapped by f. iter can be an iterator or a symbol, the symbol can be :zero, :random.

source
YaoBlocks.sandwichMethod
sandwich(bra::AbstractRegister, op::AbstractBlock, ket::AbstracRegister) -> Complex

Compute the sandwich function ⟨bra|op|ket⟩.

source
YaoBlocks.setcol!Method
setcol!(csc::SparseMatrixCSC, icol::Int, rowval::AbstractVector, nzval) -> SparseMatrixCSC

set specific col of a CSC matrix

source
YaoBlocks.setiparamsFunction
setiparams([f], block, itr)
+setiparams([f], block, params...)

Set the parameters of block, the non-inplace version. When f is provided, set parameters of block to the value in collection mapped by f. iter can be an iterator or a symbol, the symbol can be :zero, :random.

source
YaoBlocks.shiftMethod
shift(θ)

Create a ShiftGate with phase θ.

\[\begin{pmatrix} 1 & 0\\ 0 & e^{i\theta} \end{pmatrix}\]

Examples

julia> shift(0.1)
-shift(0.1)
source
YaoBlocks.single_qubit_depolarizing_channelMethod
single_qubit_depolarizing_channel(p::Real)

Create a single-qubit depolarizing channel.

The factor of 3/4 in front of p ensures that single_qubit_depolarizing_channel(p) == depolarizing_channel(1, p)

\[(1 - 3p/4 ⋅ρ) + p/4⋅(XρX + YρY + ZρZ)\]

source
YaoBlocks.subroutineMethod
subroutine(n, block, locs)

Create a n-qudit Subroutine block, where the subblock is a subprogram of size m, and locs is a tuple or range of length m. It runs a quantum subprogram with smaller size on a subset of locations. While its mathematical definition is the same as the put block, while it is more suited for running a larger chunk of circuit.

Examples

Subroutine is equivalent to put a block on given position mathematically, but more efficient and convenient for large blocks.

julia> r = rand_state(3)
+shift(0.1)
source
YaoBlocks.single_qubit_depolarizing_channelMethod
single_qubit_depolarizing_channel(p::Real)

Create a single-qubit depolarizing channel.

The factor of 3/4 in front of p ensures that single_qubit_depolarizing_channel(p) == depolarizing_channel(1, p)

\[(1 - 3p/4 ⋅ρ) + p/4⋅(XρX + YρY + ZρZ)\]

source
YaoBlocks.subroutineMethod
subroutine(n, block, locs)

Create a n-qudit Subroutine block, where the subblock is a subprogram of size m, and locs is a tuple or range of length m. It runs a quantum subprogram with smaller size on a subset of locations. While its mathematical definition is the same as the put block, while it is more suited for running a larger chunk of circuit.

Examples

Subroutine is equivalent to put a block on given position mathematically, but more efficient and convenient for large blocks.

julia> r = rand_state(3)
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 3/3
     nlevel: 2
@@ -352,18 +352,18 @@
    └─ Y
 
 julia> apply!(copy(r), cc) ≈ apply!(copy(r), pp)
-true
source
YaoBlocks.swapMethod
swap(n, loc1, loc2)

Create a n-qubit Swap gate which swap loc1 and loc2.

Examples

julia> swap(4, 1, 2)
+true
source
YaoBlocks.swapMethod
swap(n, loc1, loc2)

Create a n-qubit Swap gate which swap loc1 and loc2.

Examples

julia> swap(4, 1, 2)
 nqubits: 4
 put on (1, 2)
-└─ SWAP
source
YaoBlocks.swapMethod
swap(loc1, loc2) -> f(n)

Create a lambda that takes the total number of active qubits as input. Lazy curried version of swap(n, loc1, loc2). See also Swap.

Examples

julia> swap(1, 2)
-(n -> swap(n, 1, 2))
source
YaoBlocks.time_evolveMethod
time_evolve(H, dt[; tol=1e-7, check_hermicity=true])

Create a TimeEvolution block with Hamiltonian H and time step dt. The TimeEvolution block will use Krylove based expv to calculate time propagation. TimeEvolution block can also be used for imaginary time evolution if dt is complex. Let $H$ be a hamiltonian and $t$ be a time, the matrix representation of time_evolve(H, t) is $e^{-iHt}$.

Arguments

  • H the hamiltonian represented as an AbstractBlock.
  • dt: the evolution duration (start time is zero).

Keyword Arguments

  • tol::Real=1e-7: error tolerance.
  • check_hermicity=true: check hermicity or not.

Examples

julia> time_evolve(kron(2, 1=>X, 2=>X), 0.1)
+└─ SWAP
source
YaoBlocks.swapMethod
swap(loc1, loc2) -> f(n)

Create a lambda that takes the total number of active qubits as input. Lazy curried version of swap(n, loc1, loc2). See also Swap.

Examples

julia> swap(1, 2)
+(n -> swap(n, 1, 2))
source
YaoBlocks.time_evolveMethod
time_evolve(H, dt[; tol=1e-7, check_hermicity=true])

Create a TimeEvolution block with Hamiltonian H and time step dt. The TimeEvolution block will use Krylove based expv to calculate time propagation. TimeEvolution block can also be used for imaginary time evolution if dt is complex. Let $H$ be a hamiltonian and $t$ be a time, the matrix representation of time_evolve(H, t) is $e^{-iHt}$.

Arguments

  • H the hamiltonian represented as an AbstractBlock.
  • dt: the evolution duration (start time is zero).

Keyword Arguments

  • tol::Real=1e-7: error tolerance.
  • check_hermicity=true: check hermicity or not.

Examples

julia> time_evolve(kron(2, 1=>X, 2=>X), 0.1)
 Time Evolution Δt = 0.1, tol = 1.0e-7
 kron
 ├─ 1=>X
-└─ 2=>X
source
YaoBlocks.two_qubit_depolarizing_channelMethod
two_qubit_depolarizing_channel(p::Real)

Create a two-qubit depolarizing channel. Note that this is not the same as kron(single_qubit_depolarizing_channel(p), single_qubit_depolarizing_channel(p)).

source
YaoBlocks.u1ij!Function
u1ij!(target, i, j, a, b, c, d)

single u1 matrix into a target matrix.

Note

For coo, we take an additional parameter * ptr: starting position to store new data.

source
YaoBlocks.unitary_channelMethod
unitary_channel(operators, probs) -> UnitaryChannel

Returns a UnitaryChannel instance, where `operators is a list of operators, probs is a real vector that sum up to 1. The unitary channel is defined as below

\[\phi(\rho) = \sum_i p_i U_i ρ U_i^\dagger,\]

where $\rho$ in a DensityMatrix as the register to apply on, $p_i$ is the i-th element in probs, U_i is the i-th operator in operators.

Examples

julia> unitary_channel([X, Y, Z], [0.1, 0.2, 0.7])
+└─ 2=>X
source
YaoBlocks.two_qubit_depolarizing_channelMethod
two_qubit_depolarizing_channel(p::Real)

Create a two-qubit depolarizing channel. Note that this is not the same as kron(single_qubit_depolarizing_channel(p), single_qubit_depolarizing_channel(p)).

source
YaoBlocks.u1ij!Function
u1ij!(target, i, j, a, b, c, d)

single u1 matrix into a target matrix.

Note

For coo, we take an additional parameter * ptr: starting position to store new data.

source
YaoBlocks.unitary_channelMethod
unitary_channel(operators, probs) -> UnitaryChannel

Returns a UnitaryChannel instance, where `operators is a list of operators, probs is a real vector that sum up to 1. The unitary channel is defined as below

\[\phi(\rho) = \sum_i p_i U_i ρ U_i^\dagger,\]

where $\rho$ in a DensityMatrix as the register to apply on, $p_i$ is the i-th element in probs, U_i is the i-th operator in operators.

Examples

julia> unitary_channel([X, Y, Z], [0.1, 0.2, 0.7])
 nqubits: 1
 unitary_channel
 ├─ [0.1] X
 ├─ [0.2] Y
-└─ [0.7] Z
source
YaoBlocks.unmatMethod
unmat(::Val{D}, nbit::Int, U::AbstractMatrix, locs::NTuple) -> AbstractMatrix

Return the matrix representation of putting matrix at locs.

source
+└─ [0.7] Zsource
YaoBlocks.unmatMethod
unmat(::Val{D}, nbit::Int, U::AbstractMatrix, locs::NTuple) -> AbstractMatrix

Return the matrix representation of putting matrix at locs.

source
diff --git a/dev/man/cuda.html b/dev/man/cuda.html index 8e3b5879..d6860571 100644 --- a/dev/man/cuda.html +++ b/dev/man/cuda.html @@ -18,4 +18,4 @@ 000100110 ₍₂₎ # download the register to CPU -julia> reg = cureg |> cpu;

Features

Supported gates:

  • general U(N) gate
  • general U(1) gate
  • X, Y, Z gate
  • T, S gate
  • SWAP gate
  • control gates

Supported register operations:

  • measure!, measurereset!, measureremove!, select
  • appendqudits!, appendqubits!
  • insertqudit!, insertqubits!
  • focus!, relax!
  • join
  • density_matrix
  • fidelity
  • expect

Autodiff:

  • autodiff is supported when the only parameterized gates are rotation gates in a circuit.

API

Yao.cpuFunction
cpu(cureg)

Download the register state from GPU to CPU.

source
Note

the cu function is not documented in this module, but it is used to upload a register to GPU.

+julia> reg = cureg |> cpu;

Features

Supported gates:

  • general U(N) gate
  • general U(1) gate
  • X, Y, Z gate
  • T, S gate
  • SWAP gate
  • control gates

Supported register operations:

  • measure!, measurereset!, measureremove!, select
  • appendqudits!, appendqubits!
  • insertqudit!, insertqubits!
  • focus!, relax!
  • join
  • density_matrix
  • fidelity
  • expect

Autodiff:

  • autodiff is supported when the only parameterized gates are rotation gates in a circuit.

API

Yao.cpuFunction
cpu(cureg)

Download the register state from GPU to CPU.

source
Note

the cu function is not documented in this module, but it is used to upload a register to GPU.

diff --git a/dev/man/plot.html b/dev/man/plot.html index 7d1e4ba1..e85d37a9 100644 --- a/dev/man/plot.html +++ b/dev/man/plot.html @@ -18,10 +18,10 @@ vizcircuit(chain(3, put(1=>X), repeat(3, H), put(2=>Y), repeat(3, Rx(π/2))))Example block output

Circuit Visualization

YaoPlots.vizcircuitFunction
vizcircuit(circuit; w_depth=0.85, w_line=0.75, format=:svg, filename=nothing,
     show_ending_bar=false, starting_texts=nothing, starting_offset=-0.3,
-    ending_texts=nothing, ending_offset=0.3)

Visualize a Yao quantum circuit.

Keyword Arguments

  • w_depth is the circuit column width.
  • w_line is the circuit row width.
  • format can be :svg, :png or :pdf.
  • filename can be "*.svg", "*.png", "*.pdf" or nothing (not saving to a file).
  • starting_texts and ending_texts are texts shown before and after the circuit.
  • starting_offset and end_offset are offsets (real values) for starting and ending texts.
  • show_ending_bar is a boolean switch to show ending bar.

Styles

To change the gates styles like colors and lines, please modify the constants in submodule CircuitStyles. They are defined as:

  • CircuitStyles.unit = Ref(60) # number of points in a unit
  • CircuitStyles.r = Ref(0.2) # size of nodes
  • CircuitStyles.lw = Ref(1.0) # line width
  • CircuitStyles.textsize = Ref(16.0) # text size
  • CircuitStyles.paramtextsize = Ref(10.0) # text size (longer texts)
  • CircuitStyles.fontfamily = Ref("JuliaMono") # font family
  • CircuitStyles.linecolor = Ref("#000000") # line color
  • CircuitStyles.gate_bgcolor = Ref("transparent") # gate background color
  • CircuitStyles.textcolor = Ref("#000000") # text color
source

Bloch Sphere Visualization

YaoPlots.CircuitStylesModule
CircuitStyles

A module to define the styles of the circuit visualization. To change the styles, please modify the variables in this module, e.g.

julia> using YaoPlots
+    ending_texts=nothing, ending_offset=0.3)

Visualize a Yao quantum circuit.

Keyword Arguments

  • w_depth is the circuit column width.
  • w_line is the circuit row width.
  • format can be :svg, :png or :pdf.
  • filename can be "*.svg", "*.png", "*.pdf" or nothing (not saving to a file).
  • starting_texts and ending_texts are texts shown before and after the circuit.
  • starting_offset and end_offset are offsets (real values) for starting and ending texts.
  • show_ending_bar is a boolean switch to show ending bar.

Styles

To change the gates styles like colors and lines, please modify the constants in submodule CircuitStyles. They are defined as:

  • CircuitStyles.unit = Ref(60) # number of points in a unit
  • CircuitStyles.r = Ref(0.2) # size of nodes
  • CircuitStyles.lw = Ref(1.0) # line width
  • CircuitStyles.textsize = Ref(16.0) # text size
  • CircuitStyles.paramtextsize = Ref(10.0) # text size (longer texts)
  • CircuitStyles.fontfamily = Ref("JuliaMono") # font family
  • CircuitStyles.linecolor = Ref("#000000") # line color
  • CircuitStyles.gate_bgcolor = Ref("transparent") # gate background color
  • CircuitStyles.textcolor = Ref("#000000") # text color
source

Bloch Sphere Visualization

YaoPlots.CircuitStylesModule
CircuitStyles

A module to define the styles of the circuit visualization. To change the styles, please modify the variables in this module, e.g.

julia> using YaoPlots
 
 julia> YaoPlots.CircuitStyles.unit[] = 40
-40

Style variables

Sizes

  • unit is the number of pixels in a unit.
  • r is the size of nodes.
  • lw is the line width.

Texts

  • textsize is the text size.
  • paramtextsize is the text size for longer texts.
  • fontfamily is the font family.

Colors

  • linecolor is the line color.
  • gate_bgcolor is the gate background color.
  • textcolor is the text color.
source
YaoPlots.bloch_sphereFunction
bloch_sphere(
+40

Style variables

Sizes

  • unit is the number of pixels in a unit.
  • r is the size of nodes.
  • lw is the line width.

Texts

  • textsize is the text size.
  • paramtextsize is the text size for longer texts.
  • fontfamily is the font family.

Colors

  • linecolor is the line color.
  • gate_bgcolor is the gate background color.
  • textcolor is the text color.
source
YaoPlots.bloch_sphereFunction
bloch_sphere(
     states...;
     textsize,
     color,
@@ -38,5 +38,5 @@
 ) -> Luxor.Drawing
 

Draw a bloch sphere, with the inputs being a list of string => state pairs, where the string is a label for the state and a state can be a complex vector of size 2, a Yao register or DensityMatrix. If you want to get a raw drawing, use draw_bloch_sphere instead.

Keyword Arguments

Note: The default values can be specified in submodule BlochStyles.

  • textsize: the size of the text
  • color: the color of the drawing
  • drawing_size: the size of the drawing
  • offset_x: the offset of the drawing in x direction
  • offset_y: the offset of the drawing in y direction
  • filename: the filename of the output file, if not specified, a temporary file will be used
  • format: the format of the output file, if not specified, the format will be inferred from the filename
  • fontfamily: the font family of the text
  • background_color: the background color of the drawing
  • lw: the line width of the drawing
  • eye_point: the eye point of the drawing
  • extra_kwargs: extra keyword arguments passed to draw_bloch_sphere
    • dot_size: the size of the dot
    • ball_size: the size of the ball
    • show_projection_lines: whether to show the projection lines
    • show_angle_texts: whether to show the angle texts
    • show_line: whether to show the line
    • show01: whether to show the 0 and 1 states
    • colors: the colors of the states
    • axes_lw: the line width of the axes
    • axes_textsize: the size of the axes texts
    • axes_colors: the colors of the axes
    • axes_texts: the texts of the axes

Examples

julia> using YaoPlots, YaoArrayRegister
 
-julia> bloch_sphere("|ψ⟩"=>rand_state(1), "ρ"=>density_matrix(rand_state(2), 1));
source
YaoPlots.BlochStylesModule
BlochStyles

The module to define the default styles for bloch sphere drawing. To change the default styles, you can modify the values in this module, e.g.

using YaoPlots
-YaoPlots.BlochStyles.lw[] = 2.0

Style variables

Generic

  • lw: the line width of the drawing
  • textsize: the size of the text
  • fontfamily: the font family of the text
  • background_color: the background color of the drawing
  • color: the color of the drawing

Sphere

  • ball_size: the size of the ball
  • dot_size: the size of the dot
  • eye_point: the eye point of the drawing

Axis

  • axes_lw: the line width of the axes
  • axes_colors: the colors of the axes
  • axes_texts: the texts of the axes, default to ["x", "y", "z"]

State display

  • show_projection_lines: whether to show the projection lines
  • show_angle_texts: whether to show the angle texts
  • show_line: whether to show the line
  • show01: whether to show the 0 and 1 states
source

Themes

+julia> bloch_sphere("|ψ⟩"=>rand_state(1), "ρ"=>density_matrix(rand_state(2), 1));source
YaoPlots.BlochStylesModule
BlochStyles

The module to define the default styles for bloch sphere drawing. To change the default styles, you can modify the values in this module, e.g.

using YaoPlots
+YaoPlots.BlochStyles.lw[] = 2.0

Style variables

Generic

  • lw: the line width of the drawing
  • textsize: the size of the text
  • fontfamily: the font family of the text
  • background_color: the background color of the drawing
  • color: the color of the drawing

Sphere

  • ball_size: the size of the ball
  • dot_size: the size of the dot
  • eye_point: the eye point of the drawing

Axis

  • axes_lw: the line width of the axes
  • axes_colors: the colors of the axes
  • axes_texts: the texts of the axes, default to ["x", "y", "z"]

State display

  • show_projection_lines: whether to show the projection lines
  • show_angle_texts: whether to show the angle texts
  • show_line: whether to show the line
  • show01: whether to show the 0 and 1 states
source

Themes

diff --git a/dev/man/registers.html b/dev/man/registers.html index 5e326010..82161acf 100644 --- a/dev/man/registers.html +++ b/dev/man/registers.html @@ -159,12 +159,12 @@ active qubits: 2/2 nlevel: 2
julia> purify(rho) # purify the stateArrayReg{2, ComplexF64, Array...} active qubits: 3/6 - nlevel: 2
julia> von_neumann_entropy(rho) # von Neumann entropy5.624513604281401e-14
julia> mutual_information(rho, 1, 2) # mutual information between qubits 1 and 20.2659095304711605

API

The constructors and functions for quantum registers are listed below.

YaoArrayRegister.ArrayRegType
ArrayReg{D,T,MT<:AbstractMatrix{T}} <: AbstractArrayRegister{D}
+    nlevel: 2
julia> von_neumann_entropy(rho) # von Neumann entropy5.624513604281401e-14
julia> mutual_information(rho, 1, 2) # mutual information between qubits 1 and 20.2659095304711605

API

The constructors and functions for quantum registers are listed below.

YaoArrayRegister.ArrayRegType
ArrayReg{D,T,MT<:AbstractMatrix{T}} <: AbstractArrayRegister{D}
 ArrayReg{D}(raw)
 ArrayReg(raw::AbstractVecOrMat; nlevel=2)
-ArrayReg(r::ArrayReg)

Simulated full amplitude register type, it uses an array to represent corresponding one or a batch of quantum states. T is the numerical type for each amplitude, it is ComplexF64 by default.

Warning

ArrayReg constructor will not normalize the quantum state. If you need a normalized quantum state remember to use normalize!(register) on the register.

source
YaoArrayRegister.BatchedArrayRegType
BatchedArrayReg{D,T,MT<:AbstractMatrix{T}} <: AbstractArrayReg{D}
+ArrayReg(r::ArrayReg)

Simulated full amplitude register type, it uses an array to represent corresponding one or a batch of quantum states. T is the numerical type for each amplitude, it is ComplexF64 by default.

Warning

ArrayReg constructor will not normalize the quantum state. If you need a normalized quantum state remember to use normalize!(register) on the register.

source
YaoArrayRegister.BatchedArrayRegType
BatchedArrayReg{D,T,MT<:AbstractMatrix{T}} <: AbstractArrayReg{D}
 BatchedArrayReg(raw, nbatch; nlevel=2)
-BatchedArrayReg{D}(raw, nbatch)

Simulated batched full amplitude register type, it uses an array to represent corresponding one or a batch of quantum states. T is the numerical type for each amplitude, it is ComplexF64 by default.

Warning

BatchedArrayReg constructor will not normalize the quantum state. If you need a normalized quantum state remember to use normalize!(register) on the register.

source
YaoArrayRegister.arrayregFunction
arrayreg(state; nbatch::Union{Integer,NoBatch}=NoBatch(), nlevel::Integer=2)

Create an array register, if nbatch is a integer, it will return a BatchedArrayReg.

source
arrayreg([T=ComplexF64], bit_str; nbatch=NoBatch())

Construct an array register from bit string literal. For bit string literal please read @bit_str.

Examples

julia> arrayreg(bit"1010")
+BatchedArrayReg{D}(raw, nbatch)

Simulated batched full amplitude register type, it uses an array to represent corresponding one or a batch of quantum states. T is the numerical type for each amplitude, it is ComplexF64 by default.

Warning

BatchedArrayReg constructor will not normalize the quantum state. If you need a normalized quantum state remember to use normalize!(register) on the register.

source
YaoArrayRegister.arrayregFunction
arrayreg(state; nbatch::Union{Integer,NoBatch}=NoBatch(), nlevel::Integer=2)

Create an array register, if nbatch is a integer, it will return a BatchedArrayReg.

source
arrayreg([T=ComplexF64], bit_str; nbatch=NoBatch())

Construct an array register from bit string literal. For bit string literal please read @bit_str.

Examples

julia> arrayreg(bit"1010")
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 4/4
     nlevel: 2
@@ -172,7 +172,7 @@
 julia> arrayreg(ComplexF32, bit"1010")
 ArrayReg{2, ComplexF32, Array...}
     active qubits: 4/4
-    nlevel: 2
source
YaoArrayRegister.product_stateFunction
product_state([T=ComplexF64], dit_str; nbatch=NoBatch(), no_transpose_storage=false)
 product_state([T=ComplexF64], nbits::Int, val::Int; nbatch=NoBatch(), nlevel=2, no_transpose_storage=false)
 product_state([T=ComplexF64], vector; nbatch=NoBatch(), nlevel=2, no_transpose_storage=false)

Create an ArrayReg of product state. The configuration can be specified with a dit string, which can be defined with @bit_str or @dit_str. Or equivalently, it can be specified explicitly with nbits, val and nlevel. See also zero_state, rand_state, uniform_state.

Examples

julia> reg = product_state(dit"120;3"; nbatch=2)
 BatchedArrayReg{3, ComplexF64, Transpose...}
@@ -196,7 +196,7 @@
 true
 
 julia> r1 ≈ r3
-true
source
YaoArrayRegister.zero_state_likeFunction
zero_state_like(register, n) -> AbstractRegister

Create a register initialized to zero from an existing one.

Examples

julia> reg = rand_state(3; nbatch=2);
+    nbatch: 3
source
YaoArrayRegister.zero_state_likeFunction
zero_state_like(register, n) -> AbstractRegister

Create a register initialized to zero from an existing one.

Examples

julia> reg = rand_state(3; nbatch=2);
 
 julia> zero_state_like(reg, 2)
 BatchedArrayReg{2, ComplexF64, Array...}
     active qubits: 2/2
     nlevel: 2
-    nbatch: 2
source
YaoArrayRegister.rand_stateFunction
rand_state([T=ComplexF64], n::Int; nbatch=NoBatch(), no_transpose_storage=false)

Create a random AbstractArrayReg with total number of qudits n.

Examples

julia> rand_state(4)
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 4/4
     nlevel: 2
@@ -230,7 +230,7 @@
 BatchedArrayReg{2, ComplexF64, Transpose...}
     active qubits: 4/4
     nlevel: 2
-    nbatch: 2
source
YaoArrayRegister.uniform_stateFunction
uniform_state([T=ComplexF64], n; nbatch=NoBatch(), no_transpose_storage=false)

Create a uniform state:

\[\frac{1}{\sqrt{2^n}} \sum_{k=0}^{2^{n}-1} |k\rangle.\]

This state can also be created by applying H (Hadmard gate) on $|00⋯00⟩$ state.

Example

julia> uniform_state(4; nbatch=2)
+    nbatch: 2
source
YaoArrayRegister.uniform_stateFunction
uniform_state([T=ComplexF64], n; nbatch=NoBatch(), no_transpose_storage=false)

Create a uniform state:

\[\frac{1}{\sqrt{2^n}} \sum_{k=0}^{2^{n}-1} |k\rangle.\]

This state can also be created by applying H (Hadmard gate) on $|00⋯00⟩$ state.

Example

julia> uniform_state(4; nbatch=2)
 BatchedArrayReg{2, ComplexF64, Transpose...}
     active qubits: 4/4
     nlevel: 2
@@ -240,15 +240,15 @@
 BatchedArrayReg{2, ComplexF32, Transpose...}
     active qubits: 4/4
     nlevel: 2
-    nbatch: 2
source
YaoArrayRegister.ghz_stateFunction
ghz_state([T=ComplexF64], n::Int; nbatch::Int=NoBatch())

Create a GHZ state (or a cat state) that defined as

\[\frac{|0\rangle^{\otimes n} + |1\rangle^{\otimes n}}{\sqrt{2}}.\]

Examples

julia> ghz_state(4)
+    nbatch: 2
source
YaoArrayRegister.ghz_stateFunction
ghz_state([T=ComplexF64], n::Int; nbatch::Int=NoBatch())

Create a GHZ state (or a cat state) that defined as

\[\frac{|0\rangle^{\otimes n} + |1\rangle^{\otimes n}}{\sqrt{2}}.\]

Examples

julia> ghz_state(4)
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 4/4
-    nlevel: 2
source
YaoAPI.cloneFunction
clone(register, n)

Create an ArrayReg by cloning the original register for n times on batch dimension. This function is only for emulation.

Example

julia> clone(arrayreg(bit"101"; nbatch=3), 4)
+    nlevel: 2
source
YaoAPI.cloneFunction
clone(register, n)

Create an ArrayReg by cloning the original register for n times on batch dimension. This function is only for emulation.

Example

julia> clone(arrayreg(bit"101"; nbatch=3), 4)
 BatchedArrayReg{2, ComplexF64, Array...}
     active qubits: 3/3
     nlevel: 2
-    nbatch: 12
source

The following functions are for querying the properties of a quantum register.

YaoAPI.nquditsFunction
nqudits(register) -> Int

Returns the total number of qudits in register.

source
YaoAPI.nactiveFunction
nactive(register) -> Int

Returns the number of active qudits in register. Here, active qudits means the system qubits that operators can be applied on.

source
YaoAPI.nlevelFunction
nlevel(x)

Number of levels in each qudit.

Examples

julia> nlevel(X)
-2
source

The following functions are for querying the properties of a quantum register.

YaoAPI.nquditsFunction
nqudits(register) -> Int

Returns the total number of qudits in register.

source
YaoAPI.nactiveFunction
nactive(register) -> Int

Returns the number of active qudits in register. Here, active qudits means the system qubits that operators can be applied on.

source
YaoAPI.nlevelFunction
nlevel(x)

Number of levels in each qudit.

Examples

julia> nlevel(X)
+2
source
YaoAPI.focus!Function
focus!(register, locs) -> register
 focus!(locs...) -> f(register) -> register

Set the active qubits to focused locations, usually used to execute a subroutine. If register is not provided, returns a lambda that takes a register as input.

Examples

julia> reg = product_state(bit"01101")
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 5/5
@@ -269,7 +269,7 @@
 3-element Vector{DitStr{2, 3, Int64}}:
  101 ₍₂₎
  101 ₍₂₎
- 101 ₍₂₎

Here, we prepare a product state and only look at the qubits 1, 3 and 4. The measurement results are all ones. With the focued register, we can apply a block of size 3 on it, even though the number of qubits is 5.

source
YaoAPI.focusFunction
focus(f, register, locs)

Call a callable f under the context of focus. See also focus!.

Examples

To print the focused register

julia> r = arrayreg(bit"101100")
+ 101 ₍₂₎

Here, we prepare a product state and only look at the qubits 1, 3 and 4. The measurement results are all ones. With the focued register, we can apply a block of size 3 on it, even though the number of qubits is 5.

source
YaoAPI.focusFunction
focus(f, register, locs)

Call a callable f under the context of focus. See also focus!.

Examples

To print the focused register

julia> r = arrayreg(bit"101100")
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 6/6
     nlevel: 2
@@ -277,7 +277,7 @@
 julia> focus(x->(println(x);x), r, (1, 2));
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 2/6
-    nlevel: 2
source
YaoAPI.relax!Function
relax!(register[, locs]; to_nactive=nqudits(register)) -> register
+    nlevel: 2
source
YaoAPI.relax!Function
relax!(register[, locs]; to_nactive=nqudits(register)) -> register
 relax!(locs::Int...; to_nactive=nqudits(register)) -> f(register) -> register

Inverse transformation of focus!, where to_nactive is the number of active bits for target register. If the register is not provided, returns a lambda function that takes a register as input.

Examples

julia> reg = product_state(bit"01101")
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 5/5
@@ -291,7 +291,7 @@
 julia> relax!(reg, (1,3,4))
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 5/5
-    nlevel: 2
source
YaoArrayRegister.exchange_sysenvFunction
exchange_sysenv(reg::AbstractArrayReg) -> AbstractRegister

Exchange system (focused qubits) and environment (remaining qubits).

julia> reg = rand_state(5)
+    nlevel: 2
source
YaoArrayRegister.exchange_sysenvFunction
exchange_sysenv(reg::AbstractArrayReg) -> AbstractRegister

Exchange system (focused qubits) and environment (remaining qubits).

julia> reg = rand_state(5)
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 5/5
     nlevel: 2
@@ -304,7 +304,7 @@
 julia> exchange_sysenv(reg)
 ArrayReg{2, ComplexF64, Adjoint...}
     active qubits: 3/5
-    nlevel: 2
source

The following functions are for querying the state of a quantum register.

YaoArrayRegister.stateFunction
state(register::AbstractArrayReg) -> Matrix

Returns the raw array storage of register. See also statevec.

source
state(ρ::DensityMatrix) -> Matrix

Return the raw state of density matrix ρ.

source

The following functions are for querying the state of a quantum register.

YaoArrayRegister.stateFunction
state(register::AbstractArrayReg) -> Matrix

Returns the raw array storage of register. See also statevec.

source
state(ρ::DensityMatrix) -> Matrix

Return the raw state of density matrix ρ.

source
BitBasis.basisFunction
basis(ditstr) -> UnitRange{DitStr{D,N,T}}
 basis(DitStr{D,N,T}) -> UnitRange{DitStr{D,N,T}}

Returns the UnitRange for basis in Hilbert Space of qudits.

source
basis(register) -> UnitRange

Returns an UnitRange of the all the bits in the Hilbert space of given register.

julia> collect(basis(rand_state(3)))
 8-element Vector{DitStr{2, 3, Int64}}:
  000 ₍₂₎
@@ -314,7 +314,7 @@
  100 ₍₂₎
  101 ₍₂₎
  110 ₍₂₎
- 111 ₍₂₎
source
YaoArrayRegister.statevecFunction
statevec(r::ArrayReg) -> array

Return a state matrix/vector by droping the last dimension of size 1 (i.e. nactive(r) = nqudits(r)). See also state.

Warning

statevec is not type stable. It may cause performance slow down.

source
BitBasis.hypercubicFunction
hypercubic(A::Array) -> Array

get the hypercubic representation for an array.

source
hypercubic(r::ArrayReg) -> AbstractArray

Return the hypercubic representation (high dimensional tensor) of this register, only active qudits are considered. See also rank3 and state.

source
YaoAPI.viewbatchFunction
viewbatch(register, i::Int) -> AbstractRegister

Returns the i-th single register of a batched register. The returned instance is a view of the original register, i.e. inplace operation changes the original register directly.

Examples

julia> reg = zero_state(5; nbatch=2);
+ 111 ₍₂₎
source
YaoArrayRegister.statevecFunction
statevec(r::ArrayReg) -> array

Return a state matrix/vector by droping the last dimension of size 1 (i.e. nactive(r) = nqudits(r)). See also state.

Warning

statevec is not type stable. It may cause performance slow down.

source
BitBasis.hypercubicFunction
hypercubic(A::Array) -> Array

get the hypercubic representation for an array.

source
hypercubic(r::ArrayReg) -> AbstractArray

Return the hypercubic representation (high dimensional tensor) of this register, only active qudits are considered. See also rank3 and state.

source
YaoAPI.viewbatchFunction
viewbatch(register, i::Int) -> AbstractRegister

Returns the i-th single register of a batched register. The returned instance is a view of the original register, i.e. inplace operation changes the original register directly.

Examples

julia> reg = zero_state(5; nbatch=2);
 
 julia> apply!(viewbatch(reg, 2), put(5, 2=>X));
 
@@ -322,7 +322,7 @@
 3×2 Matrix{DitStr{2, 5, Int64}}:
  00000 ₍₂₎  00010 ₍₂₎
  00000 ₍₂₎  00010 ₍₂₎
- 00000 ₍₂₎  00010 ₍₂₎
source
YaoArrayRegister.transpose_storageFunction
transpose_storage(register) -> register

Transpose the register storage. Sometimes transposed storage provides better performance for batched simulation.

source

The following functions are for arithmetic operations on quantum registers.

YaoArrayRegister.AdjointArrayRegType
AdjointArrayReg{D,T,MT} = AdjointRegister{D,<:AbstractArrayReg{D,T,MT}}

Adjoint array register type, it is used to represent the bra in the Dirac notation.

source

We also have some faster inplace versions of arithematic operations

We also define the following functions for state normalization, and distance measurement.

LinearAlgebra.normalize!Function
normalize!(r::AbstractArrayReg)

Normalize the register r by its 2-norm. It changes the register directly.

Examples

The following code creates a normalized GHZ state.

julia> reg = product_state(bit"000") + product_state(bit"111");
+ 00000 ₍₂₎  00010 ₍₂₎
source
YaoArrayRegister.transpose_storageFunction
transpose_storage(register) -> register

Transpose the register storage. Sometimes transposed storage provides better performance for batched simulation.

source

The following functions are for arithmetic operations on quantum registers.

YaoArrayRegister.AdjointArrayRegType
AdjointArrayReg{D,T,MT} = AdjointRegister{D,<:AbstractArrayReg{D,T,MT}}

Adjoint array register type, it is used to represent the bra in the Dirac notation.

source

We also have some faster inplace versions of arithematic operations

We also define the following functions for state normalization, and distance measurement.

LinearAlgebra.normalize!Function
normalize!(r::AbstractArrayReg)

Normalize the register r by its 2-norm. It changes the register directly.

Examples

The following code creates a normalized GHZ state.

julia> reg = product_state(bit"000") + product_state(bit"111");
 
 julia> norm(reg)
 1.4142135623730951
@@ -333,18 +333,18 @@
 julia> normalize!(reg);
 
 julia> isnormalized(reg)
-true
source
YaoAPI.fidelityFunction
fidelity(register1, register2) -> Real/Vector{<:Real}
 fidelity'(pair_or_reg1, pair_or_reg2) -> (g1, g2)

Return the fidelity between two states. Calcuate the fidelity between r1 and r2, if r1 or r2 is not pure state (nactive(r) != nqudits(r)), the fidelity is calcuated by purification. See also: http://iopscience.iop.org/article/10.1088/1367-2630/aa6a4b/meta

Obtain the gradient with respect to registers and circuit parameters. For pair input ψ=>circuit, the returned gradient is a pair of gψ=>gparams, with the gradient of input state and gparams the gradients of circuit parameters. For register input, the return value is a register.

Definition

The fidelity of two quantum state for qudits is defined as:

\[F(ρ, σ) = tr(\sqrt{\sqrt{ρ}σ\sqrt{ρ}})\]

Note

This definition is different from the one in Wiki by a square.

Examples

julia> reg1 = uniform_state(3);
 
 julia> reg2 = zero_state(3);
 
 julia> fidelity(reg1, reg2)
-0.35355339059327373

References

  • Jozsa R. Fidelity for mixed quantum states[J]. Journal of modern optics, 1994, 41(12): 2315-2323.
  • Nielsen M A, Chuang I. Quantum computation and quantum information[J]. 2002.
Note

The original definition of fidelity $F$ was from "transition probability", defined by Jozsa in 1994, it is the square of what we use here.

source
YaoAPI.tracedistFunction
tracedist(register1, register2)

Return the trace distance of register1 and register2.

Definition

Trace distance is defined as following:

\[\frac{1}{2} || A - B ||_{\rm tr}\]

It takes values between 0 and 1.

Examples

julia> reg1 = uniform_state(3);
+0.35355339059327373

References

  • Jozsa R. Fidelity for mixed quantum states[J]. Journal of modern optics, 1994, 41(12): 2315-2323.
  • Nielsen M A, Chuang I. Quantum computation and quantum information[J]. 2002.
Note

The original definition of fidelity $F$ was from "transition probability", defined by Jozsa in 1994, it is the square of what we use here.

source
YaoAPI.tracedistFunction
tracedist(register1, register2)

Return the trace distance of register1 and register2.

Definition

Trace distance is defined as following:

\[\frac{1}{2} || A - B ||_{\rm tr}\]

It takes values between 0 and 1.

Examples

julia> reg1 = uniform_state(3);
 
 julia> reg2 = zero_state(3);
 
 julia> tracedist(reg1, reg2)
-0.9354143466934852

References

  • https://en.wikipedia.org/wiki/Trace_distance
source

The following functions are for adding and reordering qubits in a quantum register.

YaoAPI.insert_qudits!Function
insert_qudits!(register, loc::Int, nqudits::Int) -> register
+0.9354143466934852

References

  • https://en.wikipedia.org/wiki/Trace_distance
source

The following functions are for adding and reordering qubits in a quantum register.

YaoAPI.insert_qudits!Function
insert_qudits!(register, loc::Int, nqudits::Int) -> register
 insert_qudits!(loc::Int, nqudits::Int) -> λ(register)

Insert qudits to given register in state |0>. i.e. |psi> -> join(|psi>, |0...>, |psi>), increased bits have higher indices.

Examples

julia> reg = product_state(bit"01101")
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 5/5
@@ -359,8 +359,8 @@
 3-element Vector{DitStr{2, 7, Int64}}:
  0110001 ₍₂₎
  0110001 ₍₂₎
- 0110001 ₍₂₎
source
YaoAPI.insert_qubits!Function
insert_qubits!(register, loc::Int, nqubits::Int=1) -> register
-insert_qubits!(loc::Int, nqubits::Int=1) -> λ(register)

Insert n qubits to given register in state |0>. It is an alias of insert_qudits! function.

source
YaoAPI.insert_qubits!Function
insert_qubits!(register, loc::Int, nqubits::Int=1) -> register
+insert_qubits!(loc::Int, nqubits::Int=1) -> λ(register)

Insert n qubits to given register in state |0>. It is an alias of insert_qudits! function.

source
YaoAPI.append_qudits!Function
append_qudits!(register, n::Int) -> register
 append_qudits!(n::Int) -> λ(register)

Add n qudits to given register in state |0>. i.e. |psi> -> |000> ⊗ |psi>, increased bits have higher indices.

If only an integer is provided, then returns a lambda function.

Examples

julia> reg = product_state(bit"01101")
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 5/5
@@ -375,14 +375,14 @@
 3-element Vector{DitStr{2, 7, Int64}}:
  0001101 ₍₂₎
  0001101 ₍₂₎
- 0001101 ₍₂₎

Note here, we read the bit string from right to left.

source
YaoAPI.append_qubits!Function
append_qubits!(register, n::Int) -> register
-append_qubits!(n::Int) -> λ(register)

Add n qudits to given register in state |0>. It is an alias of append_qudits! function.

source
YaoAPI.reorder!Function
reorder!(reigster, orders)

Reorder the locations of register by input orders. For a 3-qubit register, an order (i, j, k) specifies the following reordering of qubits

  • move the first qubit go to i,
  • move the second qubit go to j,
  • move the third qubit go to k.
Note

The convention of reorder! is different from the permutedims function, one can use the sortperm function to relate the permutation order and the order in this function.

Examples

julia> reg = product_state(bit"010101");
+ 0001101 ₍₂₎

Note here, we read the bit string from right to left.

source
YaoAPI.append_qubits!Function
append_qubits!(register, n::Int) -> register
+append_qubits!(n::Int) -> λ(register)

Add n qudits to given register in state |0>. It is an alias of append_qudits! function.

source
YaoAPI.reorder!Function
reorder!(reigster, orders)

Reorder the locations of register by input orders. For a 3-qubit register, an order (i, j, k) specifies the following reordering of qubits

  • move the first qubit go to i,
  • move the second qubit go to j,
  • move the third qubit go to k.
Note

The convention of reorder! is different from the permutedims function, one can use the sortperm function to relate the permutation order and the order in this function.

Examples

julia> reg = product_state(bit"010101");
 
 julia> reorder!(reg, (1,4,2,5,3,6));
 
 julia> measure(reg)
 1-element Vector{DitStr{2, 6, Int64}}:
- 000111 ₍₂₎
source
YaoAPI.invorder!Function
invorder!(register)

Inverse the locations of the register.

Examples

julia> reg = product_state(bit"010101")
+ 000111 ₍₂₎
source
YaoAPI.invorder!Function
invorder!(register)

Inverse the locations of the register.

Examples

julia> reg = product_state(bit"010101")
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 6/6
     nlevel: 2
@@ -391,7 +391,7 @@
 3-element Vector{DitStr{2, 6, Int64}}:
  101010 ₍₂₎
  101010 ₍₂₎
- 101010 ₍₂₎
source

The instruct! function is for applying quantum operators on a quantum register.

YaoAPI.instruct!Function
instruct!([nlevel=Val(2), ]state, operator, locs[, control_locs, control_configs, theta])

Unified interface for applying an operator to a quantum state. It modifies the state directly.

Arguments

  • nlevel is the number of levels in each qudit,
  • state is a vector or matrix representing the quantum state, where the first dimension is the active qubit dimension, the second is the batch dimension.
  • operator is a quantum operator, which can be Val(GATE_SYMBOL) or a matrix.
  • locs::Tuple is a tuple for specifying the locations this gate applied.
  • control_locs::Tuple and control_configs are tuples for specifying the control locations and control values.
  • theta::Real is the parameter for the gate, e.g. Val(:Rx) gate takes a real number of its parameter.
source

The following functions are for measurement and post-selection.

YaoAPI.measure!Function
measure!([postprocess,] [operator, ]register[, locs]; rng=Random.GLOBAL_RNG)

Measure current active qudits or qudits at locs. If the operator is not provided, it will measure on the computational basis and collapse to a product state. Otherwise, the quantum state collapse to the subspace corresponds to the resulting eigenvalue of the observable.

Arguments

  • postprocess is the postprocessing method, it can be
    • NoPostProcess() (default).
    • ResetTo(config), reset to result state to config. It can not be used if operator is provided, because measuring an operator in general does not return a product state.
    • RemoveMeasured(), remove the measured qudits from the register. It is also incompatible with the operator argument.
  • operator::AbstractBlock is the operator to measure.
  • register::AbstractRegister is the quantum state.
  • locs is the qubits to performance the measurement. If locs is not provided, all current active qudits are measured (regarding to active qudits,

see focus! and relax!).

Keyword arguments

  • rng is the random number generator.

Examples

The following example measures a random state on the computational basis and reset it to a certain bitstring value.

julia> reg = rand_state(3);
+ 101010 ₍₂₎
source

The instruct! function is for applying quantum operators on a quantum register.

YaoAPI.instruct!Function
instruct!([nlevel=Val(2), ]state, operator, locs[, control_locs, control_configs, theta])

Unified interface for applying an operator to a quantum state. It modifies the state directly.

Arguments

  • nlevel is the number of levels in each qudit,
  • state is a vector or matrix representing the quantum state, where the first dimension is the active qubit dimension, the second is the batch dimension.
  • operator is a quantum operator, which can be Val(GATE_SYMBOL) or a matrix.
  • locs::Tuple is a tuple for specifying the locations this gate applied.
  • control_locs::Tuple and control_configs are tuples for specifying the control locations and control values.
  • theta::Real is the parameter for the gate, e.g. Val(:Rx) gate takes a real number of its parameter.
source

The following functions are for measurement and post-selection.

YaoAPI.measure!Function
measure!([postprocess,] [operator, ]register[, locs]; rng=Random.GLOBAL_RNG)

Measure current active qudits or qudits at locs. If the operator is not provided, it will measure on the computational basis and collapse to a product state. Otherwise, the quantum state collapse to the subspace corresponds to the resulting eigenvalue of the observable.

Arguments

  • postprocess is the postprocessing method, it can be
    • NoPostProcess() (default).
    • ResetTo(config), reset to result state to config. It can not be used if operator is provided, because measuring an operator in general does not return a product state.
    • RemoveMeasured(), remove the measured qudits from the register. It is also incompatible with the operator argument.
  • operator::AbstractBlock is the operator to measure.
  • register::AbstractRegister is the quantum state.
  • locs is the qubits to performance the measurement. If locs is not provided, all current active qudits are measured (regarding to active qudits,

see focus! and relax!).

Keyword arguments

  • rng is the random number generator.

Examples

The following example measures a random state on the computational basis and reset it to a certain bitstring value.

julia> reg = rand_state(3);
 
 julia> measure!(ResetTo(bit"011"), reg)
 110 ₍₂₎
@@ -434,7 +434,7 @@
 100 ₍₂₎   0.5 + 0.0im
 101 ₍₂₎   0.0 + 0.0im
 110 ₍₂₎   0.0 + 0.0im
-111 ₍₂₎   0.5 + 0.0im

Here, we measured the parity operator, as a result, the resulting state collapsed to the subspace with either even or odd parity.

source
YaoAPI.measureFunction
measure([, operator], register[, locs]; nshots=1, rng=Random.GLOBAL_RNG) -> Vector{Int}

Measure a quantum state and return measurement results of qudits. This measurement function a cheating version of measure! that does not collapse the input state. It also does not need to recompute the quantum state for performing multiple shots measurement.

Arguments

  • operator::AbstractBlock is the operator to measure.
  • register::AbstractRegister is the quantum state.
  • locs is the qubits to performance the measurement. If locs is not provided, all current active qudits are measured (regarding to active qudits,

see focus! and relax!).

Keyword arguments

  • nshots::Int is the number of shots.
  • rng is the random number generator.

Examples

julia> reg = product_state(bit"110")
+111 ₍₂₎   0.5 + 0.0im

Here, we measured the parity operator, as a result, the resulting state collapsed to the subspace with either even or odd parity.

source
YaoAPI.measureFunction
measure([, operator], register[, locs]; nshots=1, rng=Random.GLOBAL_RNG) -> Vector{Int}

Measure a quantum state and return measurement results of qudits. This measurement function a cheating version of measure! that does not collapse the input state. It also does not need to recompute the quantum state for performing multiple shots measurement.

Arguments

  • operator::AbstractBlock is the operator to measure.
  • register::AbstractRegister is the quantum state.
  • locs is the qubits to performance the measurement. If locs is not provided, all current active qudits are measured (regarding to active qudits,

see focus! and relax!).

Keyword arguments

  • nshots::Int is the number of shots.
  • rng is the random number generator.

Examples

julia> reg = product_state(bit"110")
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 3/3
     nlevel: 2
@@ -469,7 +469,7 @@
 3-element Vector{ComplexF64}:
  1.0 - 0.0im
  1.0 - 0.0im
- 1.0 - 0.0im
source
YaoAPI.select!Function
select!(dest::AbstractRegister, src::AbstractRegister, bits::Integer...) -> AbstractRegister
+ 1.0 - 0.0im
source
YaoAPI.select!Function
select!(dest::AbstractRegister, src::AbstractRegister, bits::Integer...) -> AbstractRegister
 select!(register::AbstractRegister, bits::Integer...) -> register
 select!(b::Integer) -> f(register)

select a subspace of given quantum state based on input eigen state bits. See also select for the non-inplace version. If the register is not provided, it returns a lambda expression that takes a register as the input.

Examples

julia> reg = ghz_state(3)
 ArrayReg{2, ComplexF64, Array...}
@@ -494,11 +494,11 @@
 
 julia> statevec(reg)
 1×2 Matrix{ComplexF64}:
- 0.0+0.0im  0.707107+0.0im
Tip

Developers should overload select!(r::RegisterType, bits::NTuple{N, <:Integer}) and do not assume bits has specific number of bits (e.g Int64), or it will restrict the its maximum available number of qudits.

source
YaoAPI.collapseto!Function
collapseto!(register, config)

Set the register to bit string literal bit_str (or an equivalent integer). About bit string literal, see more in @bit_str. This interface is only for emulation.

Examples

The following code collapse a random state to a certain state.

julia> measure(collapseto!(rand_state(3), bit"001"); nshots=3)
+ 0.0+0.0im  0.707107+0.0im
Tip

Developers should overload select!(r::RegisterType, bits::NTuple{N, <:Integer}) and do not assume bits has specific number of bits (e.g Int64), or it will restrict the its maximum available number of qudits.

source
YaoAPI.collapseto!Function
collapseto!(register, config)

Set the register to bit string literal bit_str (or an equivalent integer). About bit string literal, see more in @bit_str. This interface is only for emulation.

Examples

The following code collapse a random state to a certain state.

julia> measure(collapseto!(rand_state(3), bit"001"); nshots=3)
 3-element Vector{DitStr{2, 3, Int64}}:
  001 ₍₂₎
  001 ₍₂₎
- 001 ₍₂₎
source
YaoAPI.probsFunction
probs(register) -> Vector

Returns the probability distribution of computation basis, aka $|<x|ψ>|^2$.

Examples

julia> reg = product_state(bit"101");
+ 001 ₍₂₎
source
YaoAPI.probsFunction
probs(register) -> Vector

Returns the probability distribution of computation basis, aka $|<x|ψ>|^2$.

Examples

julia> reg = product_state(bit"101");
 
 julia> reg |> probs
 8-element Vector{Float64}:
@@ -509,13 +509,13 @@
  0.0
  1.0
  0.0
- 0.0
source
YaoArrayRegister.most_probableFunction
most_probable(reg::ArrayReg{D, T} where T, n::Int64) -> Any
 

Find n most probable qubit configurations in a quantum register and return these configurations as a vector of DitStr instances.

Example

julia> most_probable(ghz_state(3), 2)
 2-element Vector{DitStr{2, 3, Int64}}:
  000 ₍₂₎
- 111 ₍₂₎
source

The following functions are for density matrices.

The following functions are for density matrices.

YaoAPI.DensityMatrixType
DensityMatrix{D,T,MT<:AbstractMatrix{T}} <: AbstractRegister{D}
 DensityMatrix{D}(state::AbstractMatrix)
-DensityMatrix(state::AbstractMatrix; nlevel=2)

Density matrix type, where state is a matrix. Type parameter D is the number of levels, it can also be specified by a keyword argument nlevel.

source
YaoAPI.density_matrixFunction
density_matrix(register_or_rho[, locations])

Returns the reduced density matrix for qubits at locations (default: all qubits).

Examples

The following code gets the single site reduce density matrix for the GHZ state.

julia> reg = ghz_state(3)
+DensityMatrix(state::AbstractMatrix; nlevel=2)

Density matrix type, where state is a matrix. Type parameter D is the number of levels, it can also be specified by a keyword argument nlevel.

source
YaoAPI.density_matrixFunction
density_matrix(register_or_rho[, locations])

Returns the reduced density matrix for qubits at locations (default: all qubits).

Examples

The following code gets the single site reduce density matrix for the GHZ state.

julia> reg = ghz_state(3)
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 3/3
     nlevel: 2
@@ -523,7 +523,7 @@
 julia> density_matrix(reg, (2,)).state
 2×2 Matrix{ComplexF64}:
  0.5+0.0im  0.0+0.0im
- 0.0-0.0im  0.5+0.0im
source
YaoArrayRegister.rand_density_matrixFunction
rand_density_matrix([T=ComplexF64], n::Int; nlevel::Int=2, pure::Bool=false)

Generate a random density matrix by partial tracing half of the pure state.

Note

The generated density matrix is not strict hermitian due to rounding error. If you need to check hermicity, do not use ishermitian consider using isapprox(dm.state, dm.state') or explicit mark it as Hermitian.

source
YaoAPI.partial_trFunction
partial_tr(ρ, locs) -> DensityMatrix

Return a density matrix which is the partial traced on locs.

source
YaoAPI.purifyFunction
purify(r::DensityMatrix; nbit_env::Int=nactive(r)) -> ArrayReg

Get a purification of target density matrix.

Examples

The following example shows how to measure a local operator on the register, reduced density matrix and the purified register. Their results should be consistent.

julia> reg = ghz_state(3)
+ 0.0-0.0im  0.5+0.0im
source
YaoArrayRegister.rand_density_matrixFunction
rand_density_matrix([T=ComplexF64], n::Int; nlevel::Int=2, pure::Bool=false)

Generate a random density matrix by partial tracing half of the pure state.

Note

The generated density matrix is not strict hermitian due to rounding error. If you need to check hermicity, do not use ishermitian consider using isapprox(dm.state, dm.state') or explicit mark it as Hermitian.

source
YaoAPI.partial_trFunction
partial_tr(ρ, locs) -> DensityMatrix

Return a density matrix which is the partial traced on locs.

source
YaoAPI.purifyFunction
purify(r::DensityMatrix; nbit_env::Int=nactive(r)) -> ArrayReg

Get a purification of target density matrix.

Examples

The following example shows how to measure a local operator on the register, reduced density matrix and the purified register. Their results should be consistent.

julia> reg = ghz_state(3)
 ArrayReg{2, ComplexF64, Array...}
     active qubits: 3/3
     nlevel: 2
@@ -542,7 +542,7 @@
 true
 
 julia> isapprox(expect(put(3, 2=>(Z + Y)), reg), 0.0; atol=1e-10)
-true
source
YaoArrayRegister.von_neumann_entropyFunction
von_neumann_entropy(reg::AbstractArrayReg, part)
 von_neumann_entropy(ρ::DensityMatrix)

The entanglement entropy between part and the rest part in quantum state reg. If the input is a density matrix, it returns the entropy of a mixed state.

Example

The Von Neumann entropy of any segment of GHZ state is $\log 2$.

julia> von_neumann_entropy(ghz_state(3), (1,2))
-0.6931471805599612
source
von_neumann_entropy(rho) -> Real

Return the von-Neumann entropy for the input density matrix:

\[-{\rm Tr}(\rho\ln\rho)\]

source
YaoArrayRegister.mutual_informationFunction
mutual_information(register_or_rho, part1, part2)

Returns the mutual information between subsystems part1 and part2 of the input quantum register or density matrix:

\[S(\rho_A) + S(\rho_B) - S(\rho_{AB})\]

Example

The mutual information of a GHZ state of any two disjoint parts is always equal to $\log 2$.

julia> mutual_information(ghz_state(4), (1,), (3,4))
-0.6931471805599132
source
+0.6931471805599612source
von_neumann_entropy(rho) -> Real

Return the von-Neumann entropy for the input density matrix:

\[-{\rm Tr}(\rho\ln\rho)\]

source
YaoArrayRegister.mutual_informationFunction
mutual_information(register_or_rho, part1, part2)

Returns the mutual information between subsystems part1 and part2 of the input quantum register or density matrix:

\[S(\rho_A) + S(\rho_B) - S(\rho_{AB})\]

Example

The mutual information of a GHZ state of any two disjoint parts is always equal to $\log 2$.

julia> mutual_information(ghz_state(4), (1,), (3,4))
+0.6931471805599132
source
diff --git a/dev/man/simplification.html b/dev/man/simplification.html index 779370ef..3d1b28d9 100644 --- a/dev/man/simplification.html +++ b/dev/man/simplification.html @@ -1,5 +1,5 @@ -Simplification · Documentation | Yao

Simplification

The simplification for YaoBlocks is currently implemented in a limited and straightforward fashion, there is only one interface simplify to call.

APIs

YaoBlocks.Optimise.replace_blockMethod
replace_block(actor, tree::AbstractBlock) -> AbstractBlock
-replace_block(pair::Pair{Type{ST}, TT}, tree::AbstractBlock) -> AbstractBlock

replace blocks in a circuit, where actor is a function that given input block, returns the block to replace, or nothing for skip replacing and visit sibling. If pair is provided, then replace original block with type ST with new block (pair.second).

source
YaoBlocks.Optimise.simplifyMethod
simplify(block[; rules=__default_simplification_rules__])

Simplify a block tree accroding to given rules, default to use YaoBlocks.Optimise.__default_simplification_rules__.

source
YaoBlocks.Optimise.to_basictypesFunction
to_basictypes(block::AbstractBlock)

convert gates to basic types

* ChainBlock
+Simplification · Documentation | Yao

Simplification

The simplification for YaoBlocks is currently implemented in a limited and straightforward fashion, there is only one interface simplify to call.

APIs

YaoBlocks.Optimise.replace_blockMethod
replace_block(actor, tree::AbstractBlock) -> AbstractBlock
+replace_block(pair::Pair{Type{ST}, TT}, tree::AbstractBlock) -> AbstractBlock

replace blocks in a circuit, where actor is a function that given input block, returns the block to replace, or nothing for skip replacing and visit sibling. If pair is provided, then replace original block with type ST with new block (pair.second).

source
YaoBlocks.Optimise.simplifyMethod
simplify(block[; rules=__default_simplification_rules__])

Simplify a block tree accroding to given rules, default to use YaoBlocks.Optimise.__default_simplification_rules__.

source
+* PrimitiveBlock
source
diff --git a/dev/man/symbolic.html b/dev/man/symbolic.html index 5b20c126..d6a26730 100644 --- a/dev/man/symbolic.html +++ b/dev/man/symbolic.html @@ -19,8 +19,8 @@ (0.353553390593274 + -0.0*im)*sqrt(2) 0.353553390593274*sqrt(2) (0.353553390593274 + -0.0*im)*sqrt(2) -0.353553390593274*sqrt(2)

API

The following functions are for working with symbolic states.

YaoSym.@ket_strMacro
@ket_str

Create a ket register. See also @bra_str.

Examples

a symbolic quantum state can be created simply by

julia> ket"110" + 2ket"111"
 |110⟩ + 2.0|111⟩

qubits can be partially actived by focus!

julia> ket"100" + ket"111" |> focus!(1:2)
-|100⟩ + |111⟩
source
YaoSym.@bra_strMacro
@bra_str

Create a bra register. See also @ket_str.

Examples

Similar to @ket_str literal, a symbolic quantum state can be created by

julia> bra"111" + 2bra"101"
+|100⟩ + |111⟩
source
YaoSym.@bra_strMacro
@bra_str

Create a bra register. See also @ket_str.

Examples

Similar to @ket_str literal, a symbolic quantum state can be created by

julia> bra"111" + 2bra"101"
 2.0⟨101| + ⟨111|
 
 julia> bra"111" * (ket"101" + ket"111")
-1
source
YaoSym.szero_stateFunction
szero_state(n; nbatch=1)

Create a symbolic zero state, same as ket"000", but allows you use an integer.

source
+1source
YaoSym.szero_stateFunction
szero_state(n; nbatch=1)

Create a symbolic zero state, same as ket"000", but allows you use an integer.

source
diff --git a/dev/man/yao2einsum.html b/dev/man/yao2einsum.html index 473d5c65..92af730b 100644 --- a/dev/man/yao2einsum.html +++ b/dev/man/yao2einsum.html @@ -25,4 +25,4 @@ TensorNetwork Time complexity: 2^4.700439718141093 Space complexity: 2^2.0 -Read-write complexity: 2^6.0source
YaoToEinsum.TensorNetworkType
TensorNetwork

A (generalized) tensor network representation of a quantum circuit.

Fields

  • code::AbstractEinsum: The einsum code.
  • tensors::Vector: The tensors in the network.
source

References

  • Pan2022Pan, Feng, and Pan Zhang. "Simulation of quantum circuits using the big-batch tensor network method." Physical Review Letters 128.3 (2022): 030501.
  • Kalachev2021Kalachev, Gleb, Pavel Panteleev, and Man-Hong Yung. "Recursive multi-tensor contraction for xeb verification of quantum circuits." arXiv preprint arXiv:2108.05665 (2021).
  • Markov2008Markov, Igor L., and Yaoyun Shi. "Simulating quantum computation by contracting tensor networks." SIAM Journal on Computing 38.3 (2008): 963-981.
  • Liu2023Liu, Jin-Guo, et al. "Computing solution space properties of combinatorial optimization problems via generic tensor networks." SIAM Journal on Scientific Computing 45.3 (2023): A1239-A1270.
+Read-write complexity: 2^6.0source
YaoToEinsum.TensorNetworkType
TensorNetwork

A (generalized) tensor network representation of a quantum circuit.

Fields

  • code::AbstractEinsum: The einsum code.
  • tensors::Vector: The tensors in the network.
source

References

  • Pan2022Pan, Feng, and Pan Zhang. "Simulation of quantum circuits using the big-batch tensor network method." Physical Review Letters 128.3 (2022): 030501.
  • Kalachev2021Kalachev, Gleb, Pavel Panteleev, and Man-Hong Yung. "Recursive multi-tensor contraction for xeb verification of quantum circuits." arXiv preprint arXiv:2108.05665 (2021).
  • Markov2008Markov, Igor L., and Yaoyun Shi. "Simulating quantum computation by contracting tensor networks." SIAM Journal on Computing 38.3 (2008): 963-981.
  • Liu2023Liu, Jin-Guo, et al. "Computing solution space properties of combinatorial optimization problems via generic tensor networks." SIAM Journal on Scientific Computing 45.3 (2023): A1239-A1270.
diff --git a/dev/notes.html b/dev/notes.html index c45b5cd4..4b495697 100644 --- a/dev/notes.html +++ b/dev/notes.html @@ -1,3 +1,3 @@ How to overload exist method for a block · Documentation | Yao

How to overload exist method for a block

every block has two method: mat & apply!, overload mat to define how to gather this block's matrix form, overload apply! to define how to apply this block to a register.

Prototypes:

apply!(reg, block)
-mat(block)
+mat(block) diff --git a/dev/performancetips.html b/dev/performancetips.html index 70971081..05a51b67 100644 --- a/dev/performancetips.html +++ b/dev/performancetips.html @@ -22,4 +22,4 @@ julia> apply!(reg, circ) ArrayReg{2, ComplexF64, CuArray...} active qubits: 20/20 - nlevel: 2 + nlevel: 2 diff --git a/dev/quick-start.html b/dev/quick-start.html index 6aab25bd..709e87a5 100644 --- a/dev/quick-start.html +++ b/dev/quick-start.html @@ -93,4 +93,4 @@ using Compose # show a qft circuit -vizcircuit(qft_circuit(5))Example block output

More details about the plotting can be found in the manual: Quantum Circuit Visualization.

+vizcircuit(qft_circuit(5))Example block output

More details about the plotting can be found in the manual: Quantum Circuit Visualization.

diff --git a/dev/search_index.js b/dev/search_index.js index c218ce9d..37f29754 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"CurrentModule = YaoBlocks\nDocTestSetup = quote\n using Yao\n using Yao: YaoBlocks, YaoArrayRegister\n using YaoBlocks\n using YaoArrayRegister\nend","category":"page"},{"location":"man/blocks.html#Blocks","page":"Blocks","title":"Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Blocks are the basic building blocks of a quantum circuit in Yao. It simply means a quantum operator, thus, all the blocks have matrices in principal and one can get its matrix by mat. The basic blocks required to build an arbitrary quantum circuit is defined in the component package YaoBlocks.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Block Tree serves as an intermediate representation for Yao to analysis, optimize the circuit, then it will be lowered to instructions like for simulations, blocks will be lowered to instruct! calls.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"The structure of blocks is the same with a small type system, it consists of two basic kinds of blocks: CompositeBlock (like composite types), and PrimitiveBlock (like primitive types). By combining these two kinds of blocks together, we'll be able to construct a quantum circuit and represent it in a tree data structure.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"AbstractBlock\nPrimitiveBlock\nCompositeBlock","category":"page"},{"location":"man/blocks.html#YaoAPI.AbstractBlock","page":"Blocks","title":"YaoAPI.AbstractBlock","text":"AbstractBlock{D}\n\nAbstract type for quantum circuit blocks. while D is the number level in each qudit.\n\nRequired Methods\n\napply!.\nmat.\noccupied_locs.\nprint_block\n\nOptional Methods\n\ncontent\nchcontent\nsubblocks.\nchsubblocks.\nBase.hash\nBase.:(==)\nnlevel.\ngetiparams.\nsetiparams!.\nparameters.\nnparameters.\niparams_eltype.\nparameters_eltype.\ndispatch!.\nrender_params.\napply_back!.\nmat_back!.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoAPI.PrimitiveBlock","page":"Blocks","title":"YaoAPI.PrimitiveBlock","text":"PrimitiveBlock{D} <: AbstractBlock{D}\n\nAbstract type that all primitive block will subtype from. A primitive block is a concrete block who can not be decomposed into other blocks. All composite block can be decomposed into several primitive blocks.\n\nnote: Note\nsubtype for primitive block with parameter should implement hash and == method to enable key value cache.\n\nRequired Methods\n\napply!\nmat\nprint_block\nBase.hash\nBase.:(==)\n\nOptional Methods\n\nnlevel.\ngetiparams.\nsetiparams!.\nparameters.\nnparameters.\niparams_eltype.\nparameters_eltype.\ndispatch!.\nrender_params.\napply_back!.\nmat_back!.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoAPI.CompositeBlock","page":"Blocks","title":"YaoAPI.CompositeBlock","text":"CompositeBlock{D} <: AbstractBlock{D}\n\nAbstract supertype which composite blocks will inherit from. Composite blocks are blocks composited from other AbstractBlocks, thus it is a AbstractBlock as well.\n\nRequired Methods\n\napply!\nmat\noccupied_locs.\nsubblocks.\nchsubblocks.\n\nOptional Methods\n\nnlevel.\ngetiparams.\nsetiparams!.\nparameters.\nnparameters.\niparams_eltype.\nparameters_eltype.\ndispatch!.\nrender_params.\napply_back!.\nmat_back!.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#Primitive-Blocks","page":"Blocks","title":"Primitive Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Primitive blocks are subtypes of PrimitiveBlock, they are the leaf nodes in a block tree, thus primitive types do not have subtypes.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"We provide the following primitive blocks:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Modules = [YaoBlocks]\nFilter = t ->(t isa Type && t <: YaoBlocks.PrimitiveBlock)","category":"page"},{"location":"man/blocks.html#YaoBlocks.GeneralMatrixBlock","page":"Blocks","title":"YaoBlocks.GeneralMatrixBlock","text":"GeneralMatrixBlock{D, MT} <: PrimitiveBlock{D}\nGeneralMatrixBlock{D}(m, n, A, tag=\"matblock(...)\")\nGeneralMatrixBlock(A; nlevel=2, tag=\"matblock(...)\")\n\nGeneral matrix gate wraps a matrix operator to quantum gates. This is the most general form of a quantum gate.\n\nArguments\n\nm and n are the number of dits in row and column.\nA is a matrix.\ntag is the printed information.\nD and nlevel are the number of levels in each qudit.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.IdentityGate","page":"Blocks","title":"YaoBlocks.IdentityGate","text":"IdentityGate{D} <: TrivialGate{D}\n\nThe identity gate.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Measure","page":"Blocks","title":"YaoBlocks.Measure","text":"Measure{D,K, OT, LT, PT, RNG} <: PrimitiveBlock{D}\nMeasure(n::Int; rng=Random.GLOBAL_RNG, operator=ComputationalBasis(), locs=1:n, resetto=nothing, remove=false, nlevel=2)\n\nMeasure operator, currently only qudits are supported.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Measure-Union{Tuple{Int64}, Tuple{RNG}, Tuple{OT}} where {OT, RNG}","page":"Blocks","title":"YaoBlocks.Measure","text":"Measure(n::Int; rng=Random.GLOBAL_RNG, operator=ComputationalBasis(), locs=AllLocs(), resetto=nothing, remove=false)\n\nCreate a Measure block with number of qudits n.\n\nExamples\n\nYou can create a Measure block on given basis (default is the computational basis).\n\njulia> Measure(4)\nMeasure(4)\n\nOr you could specify which qudits you are going to measure\n\njulia> Measure(4; locs=1:3)\nMeasure(4;locs=(1, 2, 3))\n\nby default this will collapse the current register to measure results.\n\njulia> r = normalize!(arrayreg(bit\"000\") + arrayreg(bit\"111\"))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> state(r)\n8×1 Matrix{ComplexF64}:\n 0.7071067811865475 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.7071067811865475 + 0.0im\n\njulia> r |> Measure(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> state(r)\n8×1 Matrix{ComplexF64}:\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 1.0 + 0.0im\n\nBut you can also specify the target bit configuration you want to collapse to with keyword resetto.\n\n```jldoctest; setup=:(using Yao) julia> m = Measure(4; resetto=bit\"0101\") Measure(4;postprocess=ResetTo{BitStr{4,Int64}}(0101 ₍₂₎))\n\njulia> m.postprocess ResetTo{BitStr{4,Int64}}(0101 ₍₂₎)```\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.PhaseGate","page":"Blocks","title":"YaoBlocks.PhaseGate","text":"PhaseGate\n\nGlobal phase gate.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Projector","page":"Blocks","title":"YaoBlocks.Projector","text":"struct Projector{D, T, AT<:(AbstractArrayReg{D, T})} <: PrimitiveBlock{D}\n\nProjection operator to target state psi.\n\nDefinition\n\nprojector(s) defines the following operator.\n\ns ss\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.ReflectGate","page":"Blocks","title":"YaoBlocks.ReflectGate","text":"ReflectGate{D, T, Tt, AT<:AbstractArrayReg{D, T}} = TimeEvolution{D,Tt,Projector{D,T,AT}}\n\nLet |v⟩ be a quantum state vector, a reflection gate is a unitary operator that defined as the following operation.\n\nv 1 - (1-exp(-iθ)) vv\n\nWhen θ = π, it defines a standard reflection gate 1-2vv.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.RotationGate","page":"Blocks","title":"YaoBlocks.RotationGate","text":"RotationGate{D,T,GT<:AbstractBlock{D}} <: PrimitiveBlock{D}\n\nRotationGate, with GT both hermitian and isreflexive.\n\nDefinition\n\nExpression rot(G, θ) defines the following gate\n\ncos fractheta2I - i sin fractheta2 G\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.ShiftGate","page":"Blocks","title":"YaoBlocks.ShiftGate","text":"ShiftGate <: PrimitiveBlock\n\nPhase shift gate.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.TimeEvolution","page":"Blocks","title":"YaoBlocks.TimeEvolution","text":"TimeEvolution{D, TT, GT} <: PrimitiveBlock{D}\n\nTimeEvolution, where GT is block type. input matrix should be hermitian.\n\nnote: Note\nTimeEvolution contructor check hermicity of the input block by default, but sometimes it can be slow. Turn off the check manually by specifying optional parameter check_hermicity = false.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"@const_gate","category":"page"},{"location":"man/blocks.html#YaoBlocks.ConstGate.@const_gate","page":"Blocks","title":"YaoBlocks.ConstGate.@const_gate","text":"@const_gate = \n@const_gate :: = \n@const_gate ::\n\nThis macro simplify the definition of a constant gate. It will automatically bind the matrix form to a constant which will reduce memory allocation in the runtime.\n\nExamples\n\n@const_gate X = ComplexF64[0 1;1 0]\n\nor\n\n@const_gate X::ComplexF64 = [0 1;1 0]\n\nYou can bind new element types by simply re-declare with a type annotation.\n\n@const_gate X::ComplexF32\n\n\n\n\n\n","category":"macro"},{"location":"man/blocks.html#Composite-Blocks","page":"Blocks","title":"Composite Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Composite blocks are subtypes of CompositeBlock, they are the composition of blocks.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"We provide the following composite blocks:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Modules = [YaoBlocks]\nFilter = t -> t isa Type && t <: YaoBlocks.CompositeBlock","category":"page"},{"location":"man/blocks.html#YaoBlocks.AbstractAdd","page":"Blocks","title":"YaoBlocks.AbstractAdd","text":"AbstractAdd{D} <: CompositeBlock{D}\n\nThe abstract add interface, aimed to support Hamiltonian types.\n\nRequired Interfaces\n\nchsubblocks\nsubblocks\n\nProvides\n\nunsafe_apply! and its backward\nmat and its backward\nadjoint\noccupied_locs\ngetindex over dit strings\nishermitian\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Add","page":"Blocks","title":"YaoBlocks.Add","text":"Add{D} <: AbstractAdd{D}\nAdd(blocks::AbstractBlock...) -> Add\n\nType for block addition.\n\njulia> X + X\nnqubits: 1\n+\n├─ X\n└─ X\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.CachedBlock","page":"Blocks","title":"YaoBlocks.CachedBlock","text":"CachedBlock{ST, BT, D} <: TagBlock{BT, D}\n\nA label type that tags an instance of type BT. It forwards every methods of the block it contains, except mat and apply!, it will cache the matrix form whenever the program has.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.ChainBlock","page":"Blocks","title":"YaoBlocks.ChainBlock","text":"ChainBlock{D} <: CompositeBlock{D}\n\nChainBlock is a basic construct tool to create user defined blocks horizontically. It is a Vector like composite type.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.ControlBlock","page":"Blocks","title":"YaoBlocks.ControlBlock","text":"A control block is a composite block that applies a block when the control qubits are all ones.\n\nnote: Note\nIf control qubit index is negative, it means the inverse control, i.e., the block is applied when the control qubit is zero.\n\nFields\n\nn::Int64\nctrl_locs::NTuple{C, Int64} where C\nctrl_config::NTuple{C, Int64} where C\ncontent::AbstractBlock\nlocs::NTuple{M, Int64} where M\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Daggered","page":"Blocks","title":"YaoBlocks.Daggered","text":"Daggered{BT, D} <: TagBlock{BT,D}\n\nWrapper block allowing to execute the inverse of a block of quantum circuit.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Daggered-Union{Tuple{BT}, Tuple{D}} where {D, BT<:AbstractBlock{D}}","page":"Blocks","title":"YaoBlocks.Daggered","text":"Daggered(block)\n\nCreate a Daggered block. Let G be a input block, G' or Daggered(block) in code represents G^dagger.\n\nExamples\n\nThe inverse QFT is not hermitian, thus it will be tagged with a Daggered block.\n\njulia> A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1))));\n\njulia> B(n, i) = chain(n, i==j ? put(i=>H) : A(j, i) for j in i:n);\n\njulia> qft(n) = chain(B(n, i) for i in 1:n);\n\njulia> struct QFT <: PrimitiveBlock{2} n::Int end\n\njulia> YaoBlocks.nqudits(q::QFT) = q.n\n\n\njulia> circuit(q::QFT) = qft(nqubits(q));\n\njulia> YaoBlocks.mat(x::QFT) = mat(circuit(x));\n\njulia> QFT(2)'\n [†]QFT\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.KronBlock","page":"Blocks","title":"YaoBlocks.KronBlock","text":"KronBlock{D,M,MT<:NTuple{M,Any}} <: CompositeBlock{D}\n\ncomposite block that combine blocks by kronecker product.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.OnLevels","page":"Blocks","title":"YaoBlocks.OnLevels","text":"OnLevels{D, Ds, T <: AbstractBlock{Ds}} <: TagBlock{T, D}\n\nDefine a gate that is applied to a subset of levels.\n\nFields\n\ngate: the gate to be applied.\nlevels: the levels to apply the gate to.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.PSwap","page":"Blocks","title":"YaoBlocks.PSwap","text":"PSwap = PutBlock{2,2,RotationGate{2,T,G}} where {G<:ConstGate.SWAPGate}\nPSwap(n::Int, locs::Tuple{Int,Int}, θ::Real)\n\nParametrized swap gate that swaps two qubits with a phase, defined as\n\nrm SWAP(θ) = e^-iθrm SWAP2\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.PutBlock","page":"Blocks","title":"YaoBlocks.PutBlock","text":"PutBlock{D,C,GT<:AbstractBlock} <: AbstractContainer{GT,D}\n\nType for putting a block at given locations.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.RepeatedBlock","page":"Blocks","title":"YaoBlocks.RepeatedBlock","text":"RepeatedBlock{D,C,GT<:AbstractBlock} <: AbstractContainer{GT,D}\n\nRepeat the same block on given locations.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Scale","page":"Blocks","title":"YaoBlocks.Scale","text":"Scale{S <: Union{Number, Val}, D, BT <: AbstractBlock{D}} <: TagBlock{BT, D}\nScale(factor, block)\n\nMultiply a block with a scalar factor, which can be a number or a Val. If the factor is a number, it is regarded as a parameter that can be changed dynamically. If the factor is a Val, it is regarded as a constant.\n\nExamples\n\njulia> 2 * X\n[scale: 2] X\n\njulia> im * Z\n[+im] Z\n\njulia> -im * Z\n[-im] Z\n\njulia> -Z\n[-] Z\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Subroutine","page":"Blocks","title":"YaoBlocks.Subroutine","text":"Subroutine{D, BT <: AbstractBlock, C} <: AbstractContainer{BT, D}\n\nSubroutine node on given locations. This allows you to shoehorn a smaller circuit to a larger one.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Swap","page":"Blocks","title":"YaoBlocks.Swap","text":"Swap = PutBlock{2,2,G} where {G<:ConstGate.SWAPGate}\nSwap(n::Int, locs::Tuple{Int,Int})\n\nSwap gate, which swaps two qubits.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.UnitaryChannel","page":"Blocks","title":"YaoBlocks.UnitaryChannel","text":"UnitaryChannel{D, W<:AbstractVector} <: CompositeBlock{D}\nUnitaryChannel(operators, probs)\n\nCreate a unitary channel, where probs is a real vector that sum up to 1.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#Operations-on-Blocks","page":"Blocks","title":"Operations on Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"unsafe_apply!\napply!\napply\n\nniparams\ngetiparams\nrender_params\nnparameters\n\noccupied_locs\nprint_block\n\napply_back!\nmat_back!","category":"page"},{"location":"man/blocks.html#YaoAPI.unsafe_apply!","page":"Blocks","title":"YaoAPI.unsafe_apply!","text":"unsafe_apply!(r, block)\n\nSimilar to apply!, but will not check the size of the register and block, this is mainly used for overloading new blocks, use at your own risk.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.apply!","page":"Blocks","title":"YaoAPI.apply!","text":"apply!(register, block)\n\nApply a block (of quantum circuit) to a quantum register.\n\nnote: Note\nto overload apply! for a new block, please overload the unsafe_apply! function with same interface. Then the apply! interface will do the size checks on inputs automatically.\n\nExamples\n\njulia> r = zero_state(2)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/2\n nlevel: 2\n\njulia> apply!(r, put(2, 1=>X))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/2\n nlevel: 2\n\njulia> measure(r;nshots=10)\n10-element Vector{DitStr{2, 2, Int64}}:\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.apply","page":"Blocks","title":"YaoBlocks.apply","text":"apply(register, block)\n\nThe non-inplace version of applying a block (of quantum circuit) to a quantum register. Check apply! for the faster inplace version.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.niparams","page":"Blocks","title":"YaoAPI.niparams","text":"niparam(block) -> Int\n\nReturn number of intrinsic parameters in block. See also nparameters.\n\nExamples\n\njulia> niparams(Rx(0.1))\n1\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.getiparams","page":"Blocks","title":"YaoAPI.getiparams","text":"getiparams(block)\n\nReturns the intrinsic parameters of node block, default is an empty tuple.\n\nExamples\n\njulia> getiparams(Rx(0.1))\n0.1\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.render_params","page":"Blocks","title":"YaoAPI.render_params","text":"render_params(r::AbstractBlock, params)\n\nThis function renders the input parameter to a consumable type to r. params can be a number or a symbol like :zero and :random.\n\nExamples\n\njulia> collect(render_params(Rx(0.1), :zero))\n1-element Vector{Float64}:\n 0.0\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.nparameters","page":"Blocks","title":"YaoAPI.nparameters","text":"nparameters(block) -> Int\n\nReturn number of parameters in block. See also niparams.\n\nExamples\n\njulia> nparameters(chain(Rx(0.1), Rz(0.2)))\n2\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.occupied_locs","page":"Blocks","title":"YaoAPI.occupied_locs","text":"occupied_locs(x)\n\nReturn a tuple of occupied locations of x.\n\nExamples\n\njulia> occupied_locs(kron(5, 1=>X, 3=>X))\n(1, 3)\n\njulia> occupied_locs(kron(5, 1=>X, 3=>I2))\n(1,)\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.print_block","page":"Blocks","title":"YaoAPI.print_block","text":"print_block(io, block)\n\nDefine how blocks are printed as text in one line.\n\nExamples\n\njulia> print_block(stdout, X)\nX\n\njulia> print_block(stdout, put(2, 1=>X))\nput on (1)\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.apply_back!","page":"Blocks","title":"YaoAPI.apply_back!","text":"apply_back!((ψ, ∂L/∂ψ*), circuit::AbstractBlock, collector) -> AbstractRegister\n\nback propagate and calculate the gradient ∂L/∂θ = 2Re(∂L/∂ψ⋅∂ψ/∂θ), given ∂L/∂ψ. ψ is the output register, ∂L/∂ψ* should also be register type.\n\nNote: gradients are stored in Diff blocks, it can be access by either diffblock.grad or gradient(circuit). Note2: now apply_back! returns the inversed gradient!\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.mat_back!","page":"Blocks","title":"YaoAPI.mat_back!","text":"mat_back!(T, rb::AbstractBlock, adjy, collector)\n\nBack propagate the matrix gradients.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#Error-and-Exceptions","page":"Blocks","title":"Error and Exceptions","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Modules = [YaoBlocks]\nPages = [\"error.jl\"]","category":"page"},{"location":"man/blocks.html#Extending-Blocks","page":"Blocks","title":"Extending Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Blocks are defined as a sub-type system inside Julia, you could extend it by defining new Julia types by subtyping abstract types we provide. But we also provide some handy tools to help you create your own blocks.","category":"page"},{"location":"man/blocks.html#Define-Custom-Constant-Blocks","page":"Blocks","title":"Define Custom Constant Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Constant blocks are used quite often and in numerical simulation we would expect it to be a real constant in the program, which means it won't allocate new memory when we try to get its matrix for several times, and it won't change with parameters.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"In Yao, you can simply define a constant block with @const_gate, with the corresponding matrix:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"using YaoBlocks, BitBasis # hide\n@const_gate Rand = rand(ComplexF64, 4, 4)","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"This will automatically create a type RandGate{T} and a constant binding Rand to the instance of RandGate{ComplexF64}, and it will also bind a Julia constant for the given matrix, so when you call mat(Rand), no allocation will happen.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"@allocated mat(Rand)","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"If you want to use other data type like ComplexF32, you could directly call Rand(ComplexF32), which will create a new instance with data type ComplexF32.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Rand(ComplexF32)","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"But remember this won't bind the matrix, it only binds the matrix you give","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"@allocated mat(Rand(ComplexF32))","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"so if you want to make the matrix call mat for ComplexF32 to have zero allocation as well, you need to do it explicitly.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"@const_gate Rand::ComplexF32","category":"page"},{"location":"man/blocks.html#Define-Custom-Blocks","page":"Blocks","title":"Define Custom Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Primitive blocks are the most basic block to build a quantum circuit, if a primitive block has a certain structure, like containing tweakable parameters, it cannot be defined as a constant, thus create a new type by subtyping PrimitiveBlock is necessary","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"using YaoBlocks\n\nmutable struct PhaseGate{T <: Real} <: PrimitiveBlock{1}\n theta::T\nend","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"If your insterested block is a composition of other blocks, you should define a CompositeBlock, e.g","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"struct ChainBlock{N} <: CompositeBlock{N}\n blocks::Vector{AbstractBlock{N}}\nend","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Besides types, there are several interfaces you could define for a block, but don't worry, they should just error if it doesn't work.","category":"page"},{"location":"man/blocks.html#Define-the-matrix","page":"Blocks","title":"Define the matrix","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"The matrix form of a block is the minimal requirement to make a custom block functional, defining it is super simple, e.g for phase gate:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"mat(::Type{T}, gate::PhaseGate) where T = exp(T(im * gate.theta)) * Matrix{Complex{T}}(I, 2, 2)","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Or for composite blocks, you could just calculate the matrix by call mat on its subblocks.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"mat(::Type{T}, c::ChainBlock) where T = prod(x->mat(T, x), reverse(c.blocks))","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"The rest will just work, but might be slow since you didn't define any specification for this certain block.","category":"page"},{"location":"man/blocks.html#Define-how-blocks-are-applied-to-registers","page":"Blocks","title":"Define how blocks are applied to registers","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Although, having its matrix is already enough for applying a block to register, we could improve the performance or dispatch to other actions by overloading apply! interface, e.g we can use specialized instruction to make X gate (a builtin gate defined @const_gate) faster:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"function apply!(r::ArrayReg, x::XGate)\n nactive(r) == 1 || throw(QubitMismatchError(\"register size $(nactive(r)) mismatch with block size $N\"))\n instruct!(matvec(r.state), Val(:X), (1, ))\n return r\nend","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"In Yao, this interface allows us to provide more aggressive specialization on different patterns of quantum circuits to accelerate the simulation etc.","category":"page"},{"location":"man/blocks.html#Define-Parameters","page":"Blocks","title":"Define Parameters","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"If you want to use some member of the block to be parameters, you need to declare them explicitly","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"niparams(::Type{<:PhaseGate}) = 1\ngetiparams(x::PhaseGate) = x.theta\nsetiparams!(r::PhaseGate, param::Real) = (r.theta = param; r)","category":"page"},{"location":"man/blocks.html#Define-Adjoint","page":"Blocks","title":"Define Adjoint","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Since blocks are actually quantum operators, it makes sense to call their adjoint as well. We provide Daggered for general purpose, but some blocks may have more specific transformation rules for adjoints, e.g","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Base.adjoint(x::PhaseGate) = PhaseGate(-x.theta)","category":"page"},{"location":"man/blocks.html#Define-Cache-Keys","page":"Blocks","title":"Define Cache Keys","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"To enable cache, you should define cache_key, e.g for phase gate, we only cares about its phase, instead of the whole instance","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"cache_key(gate::PhaseGate) = gate.theta","category":"page"},{"location":"man/blocks.html#APIs","page":"Blocks","title":"APIs","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Modules = [YaoBlocks]\nOrder = [:function, :macro]","category":"page"},{"location":"man/blocks.html#Base.:|>-Tuple{AbstractRegister, AbstractBlock}","page":"Blocks","title":"Base.:|>","text":"|>(register, circuit) -> register\n\nApply a quantum circuits to register, which modifies the register directly.\n\nExample\n\njulia> arrayreg(bit\"0\") |> X |> Y\n\nwarning: Warning\n|> is equivalent to apply!, which means it has side effects. You need to use apply if you do not want to change it in-place.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.kron-Tuple{Int64, Vararg{Pair{<:Any, <:AbstractBlock}}}","page":"Blocks","title":"Base.kron","text":"kron(n, locs_and_blocks::Pair{<:Any, <:AbstractBlock}...) -> KronBlock\n\nReturns a n-qudit KronBlock. The inputs contains a list of location-block pairs, where a location can be an integer or a range. It is conceptually a chain of put block without address conflicts, but it has a richer type information that can be useful for various purposes such as more efficient mat function.\n\nLet I be a 2times 2 identity matrix, G and H be two 2times 2 matrix, the matrix representation of kron(n, i=>G, j=>H) (assume j i) is defined as\n\nI^otimes n-j otimes H otimes I^otimes j-i-1 otimes G otimes I^i-1\n\nFor multiple locations, the expression can be complicated.\n\nExamples\n\nUse kron to construct a KronBlock, it will put an X gate on the 1st qubit, and a Y gate on the 3rd qubit.\n\njulia> kron(4, 1=>X, 3=>Y)\nnqubits: 4\nkron\n├─ 1=>X\n└─ 3=>Y\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.kron-Tuple{Vararg{AbstractBlock}}","page":"Blocks","title":"Base.kron","text":"kron(blocks::AbstractBlock...)\nkron(n, itr)\n\nReturn a KronBlock, with total number of qubits n, and blocks should use all the locations on n wires in quantum circuits.\n\nExamples\n\nYou can use kronecker product to composite small blocks to a large blocks.\n\njulia> kron(X, Y, Z, Z)\nnqubits: 4\nkron\n├─ 1=>X\n├─ 2=>Y\n├─ 3=>Z\n└─ 4=>Z\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.kron-Tuple{Vararg{Pair{<:Any, <:AbstractBlock}}}","page":"Blocks","title":"Base.kron","text":"kron(blocks...) -> f(n)\nkron(itr) -> f(n)\n\nReturn a lambda, which will take the total number of qubits as input.\n\nExamples\n\nIf you don't know the number of qubit yet, or you are just too lazy, it is fine.\n\njulia> kron(put(1=>X) for _ in 1:2)\n(n -> kron(n, ((n -> put(n, 1 => X)), (n -> put(n, 1 => X)))...))\n\njulia> kron(X for _ in 1:2)\nnqubits: 2\nkron\n├─ 1=>X\n└─ 2=>X\n\njulia> kron(1=>X, 3=>Y)\n(n -> kron(n, (1 => X, 3 => Y)...))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.repeat-Tuple{AbstractBlock, Any}","page":"Blocks","title":"Base.repeat","text":"repeat(x::AbstractBlock, locs)\n\nLazy curried version of repeat.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.repeat-Tuple{Int64, AbstractBlock, Vararg{Int64}}","page":"Blocks","title":"Base.repeat","text":"repeat(n, subblock::AbstractBlock[, locs]) -> RepeatedBlock{n}\n\nCreate a n-qudit RepeatedBlock block, which is conceptually a [kron] block with all gates being the same. If locs is provided, repeat on locs, otherwise repeat on all locations. Let G be a 2times 2 matrix, the matrix representation of repeat(n, X) is\n\nX^otimes n\n\nThe RepeatedBlock can be used to accelerate repeated applying certain gate types: X, Y, Z, S, T, Sdag, and Tdag.\n\nExamples\n\nThis will create a repeat block which puts 4 X gates on each location.\n\njulia> repeat(4, X)\nnqubits: 4\nrepeat on (1, 2, 3, 4)\n└─ X\n\nYou can also specify the location\n\njulia> repeat(4, X, (1, 2))\nnqubits: 4\nrepeat on (1, 2)\n└─ X\n\nBut repeat won't copy the gate, thus, if it is a gate with parameter, e.g a phase(0.1), the parameter will change simultaneously.\n\njulia> g = repeat(4, phase(0.1))\nnqubits: 4\nrepeat on (1, 2, 3, 4)\n└─ phase(0.1)\n\njulia> g.content\nphase(0.1)\n\njulia> g.content.theta = 0.2\n0.2\n\njulia> g\nnqubits: 4\nrepeat on (1, 2, 3, 4)\n└─ phase(0.2)\n\nRepeat over certain gates will provide speed up.\n\njulia> reg = rand_state(20);\n\njulia> @time apply!(reg, repeat(20, X));\n 0.002252 seconds (5 allocations: 656 bytes)\n\njulia> @time apply!(reg, chain([put(20, i=>X) for i=1:20]));\n 0.049362 seconds (82.48 k allocations: 4.694 MiB, 47.11% compilation time)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#LinearAlgebra.ishermitian-Tuple{Any}","page":"Blocks","title":"LinearAlgebra.ishermitian","text":"ishermitian(op::AbstractBlock) -> Bool\n\nReturns true if op is hermitian.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.chcontent-Tuple{AbstractContainer, Any}","page":"Blocks","title":"YaoAPI.chcontent","text":"chcontent(x, blk)\n\nCreate a similar block of x and change its content to blk.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.chsubblocks-Tuple{AbstractBlock, Any}","page":"Blocks","title":"YaoAPI.chsubblocks","text":"chsubblocks(composite_block, itr)\n\nChange the sub-blocks of a CompositeBlock with given iterator itr.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.content-Tuple{AbstractContainer}","page":"Blocks","title":"YaoAPI.content","text":"content(x)\n\nReturns the content of x.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.dispatch!-Tuple{Union{Nothing, Function}, AbstractBlock, Any}","page":"Blocks","title":"YaoAPI.dispatch!","text":"dispatch!(x::AbstractBlock, collection)\n\nDispatch parameters in collection to block tree x.\n\nnote: Note\nit will try to dispatch the parameters in collection first.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.expect-Tuple{AbstractBlock, AbstractRegister}","page":"Blocks","title":"YaoAPI.expect","text":"expect(op::AbstractBlock, reg) -> Real\nexpect(op::AbstractBlock, reg => circuit) -> Real\nexpect(op::AbstractBlock, density_matrix) -> Real\n\nGet the expectation value of an operator, the second parameter can be a register reg or a pair of input register and circuit reg => circuit.\n\nexpect'(op::AbstractBlock, reg=>circuit) -> Pair expect'(op::AbstractBlock, reg) -> AbstracRegister\n\nObtain the gradient with respect to registers and circuit parameters. For pair input, the second return value is a pair of gψ=>gparams, with gψ the gradient of input state and gparams the gradients of circuit parameters. For register input, the return value is a register.\n\nnote: Note\nFor batched register, expect(op, reg=>circuit) returns a vector of size number of batch as output. However, one can not differentiate over a vector loss, so expect'(op, reg=>circuit) accumulates the gradient over batch, rather than returning a batched gradient of parameters.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.getiparams-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.getiparams","text":"getiparams(block)\n\nReturns the intrinsic parameters of node block, default is an empty tuple.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.iparams_eltype-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.iparams_eltype","text":"iparams_eltype(block)\n\nReturn the element type of getiparams.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.mat-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.mat","text":"mat([T=ComplexF64], blk)\n\nReturns the matrix form of given block.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.mat-Tuple{GeneralMatrixBlock}","page":"Blocks","title":"YaoAPI.mat","text":"mat(A::GeneralMatrixBlock)\n\nReturn the matrix of general matrix block.\n\nwarn: Warn\nInstead of converting it to the default data type ComplexF64, this will return its contained matrix.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.operator_fidelity-Tuple{AbstractBlock, AbstractBlock}","page":"Blocks","title":"YaoAPI.operator_fidelity","text":"operator_fidelity(b1::AbstractBlock, b2::AbstractBlock) -> Number\n\nOperator fidelity defined as\n\nF^2 = frac1dleftrm Tr(b1^dagger b2)right\n\nHere, d is the size of the Hilbert space. Note this quantity is independant to global phase. See arXiv: 0803.2940v2, Equation (2) for reference.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.parameters-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.parameters","text":"parameters(block)\n\nReturns all the parameters contained in block tree with given root block.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.parameters_eltype-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.parameters_eltype","text":"parameters_eltype(x)\n\nReturn the element type of parameters.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.setiparams!","page":"Blocks","title":"YaoAPI.setiparams!","text":"setiparams!([f], block, itr)\nsetiparams!([f], block, params...)\n\nSet the parameters of block. When f is provided, set parameters of block to the value in collection mapped by f. iter can be an iterator or a symbol, the symbol can be :zero, :random.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.subblocks-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.subblocks","text":"subblocks(x)\n\nReturns an iterator of the sub-blocks of a composite block. Default is empty.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.Rx-Tuple{Any}","page":"Blocks","title":"YaoBlocks.Rx","text":"Rx(theta)\n\nReturn a RotationGate on X axis.\n\nExample\n\njulia> Rx(0.1)\nrot(X, 0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.Ry-Tuple{Any}","page":"Blocks","title":"YaoBlocks.Ry","text":"Ry(theta)\n\nReturn a RotationGate on Y axis.\n\nExample\n\njulia> Ry(0.1)\nrot(Y, 0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.Rz-Tuple{Any}","page":"Blocks","title":"YaoBlocks.Rz","text":"Rz(theta)\n\nReturn a RotationGate on Z axis.\n\nExample\n\njulia> Rz(0.1)\nrot(Z, 0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.apply-Union{Tuple{D}, Tuple{AbstractRegister{D}, Any}} where D","page":"Blocks","title":"YaoBlocks.apply","text":"apply(register, block)\n\nThe non-inplace version of applying a block (of quantum circuit) to a quantum register. Check apply! for the faster inplace version.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.applymatrix-Tuple{Any, AbstractBlock}","page":"Blocks","title":"YaoBlocks.applymatrix","text":"applymatrix(g::AbstractBlock) -> Matrix\n\nTransform the apply! function of specific block to dense matrix.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.bit_flip_channel-Tuple{Real}","page":"Blocks","title":"YaoBlocks.bit_flip_channel","text":"bit_flip_channel(p::Real)\n\nCreate a bit flip channel as a UnitaryChannel.\n\n(1-p)ρ + pXρX\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cache","page":"Blocks","title":"YaoBlocks.cache","text":"cache(x[, level=1; recursive=false])\n\nCreate a CachedBlock with given block x, which will cache the matrix of x for the first time it calls mat, and use the cached matrix in the following calculations.\n\nExamples\n\njulia> cache(control(3, 1, 2=>X))\nnqubits: 3\n[cached] control(1)\n └─ (2,) X\n\n\njulia> chain(cache(control(3, 1, 2=>X)), repeat(H))\nnqubits: 3\nchain\n└─ [cached] control(1)\n └─ (2,) X\n\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.cache_key-Tuple{AbstractBlock}","page":"Blocks","title":"YaoBlocks.cache_key","text":"cache_key(block)\n\nReturns the key that identify the matrix cache of this block. By default, we use the returns of parameters as its key.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cache_type-Tuple{Type{<:AbstractBlock}}","page":"Blocks","title":"YaoBlocks.cache_type","text":"cache_type(::Type) -> DataType\n\nReturn the element type that a CacheFragment will use.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.chain-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.chain","text":"chain(n)\n\nReturn an empty ChainBlock which can be used like a list of blocks.\n\nExamples\n\njulia> chain(2)\nnqubits: 2\nchain\n\n\njulia> chain(2; nlevel=3)\nnqudits: 2\nchain\n\n\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.chain-Tuple{}","page":"Blocks","title":"YaoBlocks.chain","text":"chain()\n\nReturn an lambda n->chain(n).\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.chain-Union{Tuple{Vararg{AbstractBlock{D}}}, Tuple{D}} where D","page":"Blocks","title":"YaoBlocks.chain","text":"chain(blocks...) -> ChainBlock\nchain(n) -> ChainBlock\n\nReturn a ChainBlock which chains a list of blocks with the same number of qudits. Let G_i be a sequence of n-qudit blocks, the matrix representation of block chain(G_1, G_2, ..., G_m) is\n\nG_m G_m-1ldots G_1\n\nIt is almost equivalent to matrix multiplication except the order is reversed. We make its order different from regular matrix multiplication because quantum circuits can be represented more naturally in this form.\n\nExamples\n\njulia> chain(X, Y, Z)\nnqubits: 1\nchain\n├─ X\n├─ Y\n└─ Z\n\njulia> chain(2, put(1=>X), put(2=>Y), cnot(2, 1))\nnqubits: 2\nchain\n├─ put on (1)\n│ └─ X\n├─ put on (2)\n│ └─ Y\n└─ control(2)\n └─ (1,) X\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.chmeasureoperator-Union{Tuple{D}, Tuple{Measure{D, K} where K, AbstractBlock}} where D","page":"Blocks","title":"YaoBlocks.chmeasureoperator","text":"chmeasureoperator(m::Measure, op::AbstractBlock)\n\nchange the measuring operator. It will also discard existing measuring results.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cleanup-Tuple{EntryTable}","page":"Blocks","title":"YaoBlocks.cleanup","text":"cleanup(entries::EntryTable; zero_threshold=0.0)\n\nClean up the entry table by 1) sort entries, 2) merge items and 3) clean up zeros. Any value with amplitude ≤ zero_threshold will be regarded as zero.\n\njulia> et = EntryTable([bit\"000\",bit\"011\",bit\"101\",bit\"101\",bit\"011\",bit\"110\",bit\"110\",bit\"011\",], [1.0 + 0.0im,-1, 1,1,1,-1,1,1,-1])\nEntryTable{DitStr{2, 3, Int64}, ComplexF64}:\n 000 ₍₂₎ 1.0 + 0.0im\n 011 ₍₂₎ -1.0 + 0.0im\n 101 ₍₂₎ 1.0 + 0.0im\n 101 ₍₂₎ 1.0 + 0.0im\n 011 ₍₂₎ 1.0 + 0.0im\n 110 ₍₂₎ -1.0 + 0.0im\n 110 ₍₂₎ 1.0 + 0.0im\n 011 ₍₂₎ 1.0 + 0.0im\n\n\njulia> cleanup(et)\nEntryTable{DitStr{2, 3, Int64}, ComplexF64}:\n 000 ₍₂₎ 1.0 + 0.0im\n 011 ₍₂₎ 1.0 + 0.0im\n 101 ₍₂₎ 2.0 + 0.0im\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cnot-Tuple{Int64, Any, Int64}","page":"Blocks","title":"YaoBlocks.cnot","text":"cnot([n, ]ctrl_locs, location)\n\nReturn a speical ControlBlock, aka CNOT gate with number of active qubits n and locs of control qubits ctrl_locs, and location of X gate.\n\nExamples\n\njulia> cnot(3, (2, 3), 1)\nnqubits: 3\ncontrol(2, 3)\n└─ (1,) X\n\njulia> cnot(2, 1)\n(n -> cnot(n, 2, 1))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.collect_blocks-Union{Tuple{T}, Tuple{Type{T}, AbstractBlock}} where T<:AbstractBlock","page":"Blocks","title":"YaoBlocks.collect_blocks","text":"collect_blocks(block_type, root)\n\nReturn a ChainBlock with all block of block_type in root.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.control-Tuple{Any, Pair}","page":"Blocks","title":"YaoBlocks.control","text":"control(ctrl_locs, target) -> f(n)\n\nReturn a lambda that takes the number of total active qubits as input. See also control.\n\nExamples\n\njulia> control((2, 3), 1=>X)\n(n -> control(n, (2, 3), 1 => X))\n\njulia> control(2, 1=>X)\n(n -> control(n, 2, 1 => X))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.control-Tuple{Int64, Any, Pair}","page":"Blocks","title":"YaoBlocks.control","text":"control(n, ctrl_locs, locations => subblock)\n\nReturn a n-qubit ControlBlock, where the control locations ctrl_locs and the subblock locations in the third argument can be an integer, a tuple or a range, and the size of the subblock should match the length of locations. Let I be the 2 times 2 identity matrix, G be a 2 times 2 subblock, P_0=0ranglelangle 0 and P_1=1ranglelangle 1 be two single qubit projection operators to subspace 0rangle and 1rangle, i and j be two integers that ij. The matrix representation of control(n, i, j=>G) is\n\nbeginalign\nI^otimes n-i P_0 otimes I^otimes i-j-1 otimes Iotimes I^otimes j-1\n+\n I^otimes n-i P_1 otimes I^otimes i-j-1 otimes Gotimes I^otimes j-1\nendalign\n\nThe multi-controlled multi-qubit controlled block is more complicated, it means apply the gate when control qubits are all ones. Each control location can take a negative sign to represent the inverse control, meaning only when this qubit is 0, the controlled gate is applied.\n\nExamples\n\njulia> control(4, (1, 2), 3=>X)\nnqubits: 4\ncontrol(1, 2)\n└─ (3,) X\n\njulia> control(4, 1, 3=>X)\nnqubits: 4\ncontrol(1)\n└─ (3,) X\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cunmat","page":"Blocks","title":"YaoBlocks.cunmat","text":"cunmat(nbit::Int, cbits::NTuple{C, Int}, cvals::NTuple{C, Int}, U0::AbstractMatrix, locs::NTuple{M, Int}) where {C, M} -> AbstractMatrix\n\ncontrol-unitary matrix\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.cz-Tuple{Int64, Any, Int64}","page":"Blocks","title":"YaoBlocks.cz","text":"cz([n, ]ctrl_locs, location)\n\nReturn a special ControlBlock, aka CZ gate with number of active qubits n and locs of control qubits ctrl_locs, and location of Z gate. See also cnot.\n\nExamples\n\njulia> cz(2, 1, 2)\nnqubits: 2\ncontrol(1)\n└─ (2,) Z\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.decode_sign-Union{Tuple{NTuple{N, Int64}}, Tuple{N}} where N","page":"Blocks","title":"YaoBlocks.decode_sign","text":"decode_sign(ctrls...)\n\nDecode signs into control sequence on control or inversed control.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.depolarizing_channel-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.depolarizing_channel","text":"depolarizing_channel(n::Int; p::Real)\n\nCreate a global depolarizing channel.\n\nArguments\n\nn: number of qubits.\n\nKeyword Arguments\n\np: probability of this error to occur.\n\nSee also\n\nsingle_qubit_depolarizing_channel and two_qubit_depolarizing_channel for depolarizing channels acting on only one or two qubits.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.dispatch-Tuple{Union{Nothing, Function}, AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.dispatch","text":"dispatch(x::AbstractBlock, collection)\n\nDispatch parameters in collection to block tree x, the generic non-inplace version.\n\nnote: Note\nit will try to dispatch the parameters in collection first.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.dump_gate","page":"Blocks","title":"YaoBlocks.dump_gate","text":"dump_gate(blk::AbstractBlock) -> Expr\n\nconvert a gate to a YaoScript expression for serization. The fallback is GateTypeName(fields...)\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.eigenbasis-Union{Tuple{AbstractBlock{D}}, Tuple{D}} where D","page":"Blocks","title":"YaoBlocks.eigenbasis","text":"eigenbasis(op::AbstractBlock)\n\nReturn the eigenvalue and eigenvectors of target operator. By applying eigenvector' to target state, one can swith the basis to the eigenbasis of this operator. However, eigenvalues does not have a specific form.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.gate_expr-Union{Tuple{G}, Tuple{Val{G}, Any, Any}} where G","page":"Blocks","title":"YaoBlocks.gate_expr","text":"gate_expr(::Val{G}, args, info)\n\nObtain the gate constructior from its YaoScript expression. G is a symbol for the gate type, the default constructor is G(args...). info contains the informations about the number of qubit and Yao version.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.getcol-Tuple{LuxurySparse.SDSparseMatrixCSC, Int64}","page":"Blocks","title":"YaoBlocks.getcol","text":"getcol(csc::SDparseMatrixCSC, icol::Int) -> (View, View)\n\nget specific col of a CSC matrix, returns a slice of (rowval, nzval)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.igate-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.igate","text":"igate(n::Int; nlevel=2)\n\nThe constructor for IdentityGate. Let I_d be a d times d identity matrix, igate(n; nlevel=d) is defined as I_d^otimes n.\n\nExamples\n\njulia> igate(2)\nigate(2)\n\njulia> igate(2; nlevel=3)\nigate(2;nlevel=3)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.isclean-Tuple{EntryTable}","page":"Blocks","title":"YaoBlocks.isclean","text":"isclean(entries::EntryTable; zero_threshold=0.0)\n\nReturn true if the entries are ordered, unique and amplitudes are nonzero. Any value with amplitude ≤ zero_threshold will be regarded as zero.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.map_address","page":"Blocks","title":"YaoBlocks.map_address","text":"map_address(block::AbstractBlock, info::AddressInfo) -> AbstractBlock\n\nmap the locations in block to target locations.\n\nExample\n\nmap_address can be used to embed a sub-circuit to a larger one.\n\njulia> c = chain(5, repeat(H, 1:5), put(2=>X), kron(1=>X, 3=>Y))\nnqubits: 5\nchain\n├─ repeat on (1, 2, 3, 4, 5)\n│ └─ H\n├─ put on (2)\n│ └─ X\n└─ kron\n ├─ 1=>X\n └─ 3=>Y\n\n\njulia> map_address(c, AddressInfo(10, [6,7,8,9,10]))\nnqubits: 10\nchain\n├─ repeat on (6, 7, 8, 9, 10)\n│ └─ H\n├─ put on (7)\n│ └─ X\n└─ kron\n ├─ 6=>X\n └─ 8=>Y\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.matblock-Tuple{AbstractMatrix}","page":"Blocks","title":"YaoBlocks.matblock","text":"matblock(mat_or_block; nlevel=2, tag=\"matblock(...)\")\n\nCreate a GeneralMatrixBlock with a matrix m.\n\nExamples\n\njulia> matblock(ComplexF64[0 1;1 0])\nmatblock(...)\n\n!!!warn\n\nInstead of converting it to the default data type `ComplexF64`,\nthis will return its contained matrix when calling `mat`.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.num_nonzero","page":"Blocks","title":"YaoBlocks.num_nonzero","text":"num_nonzero(nbits, nctrls, U, [N])\n\nReturn number of nonzero entries of the matrix form of control-U gate. nbits is the number of qubits, and nctrls is the number of control qubits.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.parameters!-Tuple{Any, AbstractBlock}","page":"Blocks","title":"YaoBlocks.parameters!","text":"parameters!(out, block)\n\nAppend all the parameters contained in block tree with given root block to out.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.parameters_range-Tuple{AbstractBlock}","page":"Blocks","title":"YaoBlocks.parameters_range","text":"parameters_range(block)\n\nReturn the range of real parameters present in block.\n\nnote: Note\nIt may not be the case that length(parameters_range(block)) == nparameters(block).\n\nExample\n\njulia> YaoBlocks.parameters_range(RotationGate(X, 0.1))\n1-element Vector{Tuple{Float64, Float64}}:\n (0.0, 6.283185307179586)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.parse_block","page":"Blocks","title":"YaoBlocks.parse_block","text":"parse_block(n, ex)\n\nThis function parse the julia object ex to a quantum block, it defines the syntax of high level interfaces. ex can be a function takes number of qubits n as input or it can be a pair.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.pauli_error_channel-Tuple{}","page":"Blocks","title":"YaoBlocks.pauli_error_channel","text":"pauli_error_channel(; px::Real, py::Real=px, pz::Real=px)\n\nCreate the Pauli error channel as a UnitaryChannel\n\n (1 - (p_x + p_y + p_z))ρ + p_xXρX + p_yYρY + p_zZρZ\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.phase-Tuple{Real}","page":"Blocks","title":"YaoBlocks.phase","text":"phase(theta)\n\nReturns a global phase gate. Defined with following matrix form:\n\ne^iθ I\n\nExamples\n\nYou can create a global phase gate with a phase (a real number).\n\njulia> phase(0.1)\nphase(0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.phase_flip_channel-Tuple{Real}","page":"Blocks","title":"YaoBlocks.phase_flip_channel","text":"phase_flip_channel(::Real)\n\nCreate a phase flip channel as UnitaryChannel.\n\n(1-p)ρ + pZρZ\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.popdispatch!-Tuple{AbstractBlock, Vector}","page":"Blocks","title":"YaoBlocks.popdispatch!","text":"popdispatch!(block, list)\n\nPop the first nparameters parameters of list, then dispatch them to the block tree block. See also dispatch!.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.popdispatch!-Tuple{Function, AbstractBlock, Vector}","page":"Blocks","title":"YaoBlocks.popdispatch!","text":"popdispatch!(f, block, list)\n\nPop the first nparameters parameters of list, map them with a function f, then dispatch them to the block tree block. See also dispatch!.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.postwalk-Tuple{Union{Function, Type}, AbstractBlock}","page":"Blocks","title":"YaoBlocks.postwalk","text":"postwalk(f, src::AbstractBlock)\n\nWalk the tree and call f after the children are visited.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.prewalk-Tuple{Union{Function, Type}, AbstractBlock}","page":"Blocks","title":"YaoBlocks.prewalk","text":"prewalk(f, src::AbstractBlock)\n\nWalk the tree and call f once the node is visited.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.print_annotation-Tuple{IO, Vararg{Any, 4}}","page":"Blocks","title":"YaoBlocks.print_annotation","text":"print_annotation(io, root, node, child, k)\n\nPrint the annotation of k-th child of node, aka the k-th element of subblocks(node).\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.print_prefix-Tuple{IO, Any, Any, Any}","page":"Blocks","title":"YaoBlocks.print_prefix","text":"print_prefix(io, depth, charset, active_levels)\n\nprint prefix of a tree node in a single line.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.print_subtypetree","page":"Blocks","title":"YaoBlocks.print_subtypetree","text":"print_subtypetree(::Type[, level=1, indent=4])\n\nPrint subtype tree, level specify the depth of the tree.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.print_title-Tuple{IO, AbstractBlock}","page":"Blocks","title":"YaoBlocks.print_title","text":"print_title(io, block)\n\nPrint the title of given block of an AbstractBlock.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.print_tree","page":"Blocks","title":"YaoBlocks.print_tree","text":"print_tree(io, root, node[, depth=1, active_levels=()]; kwargs...)\n\nPrint the block tree.\n\nKeywords\n\nmaxdepth: max tree depth to print\ncharset: default is ('├','└','│','─'). See also YaoBlocks.BlockTreeCharSet.\ntitle: control whether to print the title, true or false, default is true\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.print_tree-Tuple{Any}","page":"Blocks","title":"YaoBlocks.print_tree","text":"print_tree([io=stdout], root)\n\nPrint the block tree.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.projection-Tuple{AbstractMatrix, AbstractMatrix}","page":"Blocks","title":"YaoBlocks.projection","text":"projection(y::AbstractMatrix, op::AbstractMatrix) -> typeof(y)\n\nProject op to sparse matrix with same sparsity as y.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.projector-Tuple{AbstractArrayReg}","page":"Blocks","title":"YaoBlocks.projector","text":"projector(v::AbstractArrayReg) -> Projector\n\n\nCreate a Projector with an quantum state vector v.\n\nExample\n\njulia> projector(rand_state(3))\n|s⟩⟨s|, nqudits = 3\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.projector-Tuple{Any}","page":"Blocks","title":"YaoBlocks.projector","text":"projector(x)\n\nReturn projector on 0 or projector on 1.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.pswap-Tuple{Int64, Int64, Int64, Real}","page":"Blocks","title":"YaoBlocks.pswap","text":"pswap(n::Int, i::Int, j::Int, α::Real)\npswap(i::Int, j::Int, α::Real) -> f(n)\n\nparametrized swap gate.\n\nExamples\n\njulia> pswap(2, 1, 2, 0.1)\nnqubits: 2\nput on (1, 2)\n└─ rot(SWAP, 0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.put-Tuple{Pair}","page":"Blocks","title":"YaoBlocks.put","text":"put(pair) -> f(n)\n\nLazy curried version of put.\n\nExamples\n\njulia> put(1=>X)\n(n -> put(n, 1 => X))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.put-Union{Tuple{M}, Tuple{Int64, Pair{NTuple{M, Int64}, <:AbstractBlock}}} where M","page":"Blocks","title":"YaoBlocks.put","text":"put(n::Int, locations => subblock) => PutBlock\n\nCreate a n-qudit PutBlock. The second argument is a pair of locations and subblock, where the locations can be a tuple, an integer or a range and the subblock size should match the length of locations. Let I be a 2times 2 identity matrix and G be a 2times 2 matrix, the matrix representation of put(n, i=>G) is defined as\n\nI^otimes n-i otimes G otimes I^otimes i-1\n\nFor multiple locations, the expression can be complicated, which corresponds to the matrix representation of multi-qubit gate applied on n-qubit space in quantum computing.\n\nExamples\n\njulia> put(4, 1=>X)\nnqubits: 4\nput on (1)\n└─ X\n\nIf you want to put a multi-qubit gate on specific locations, you need to write down all possible locations.\n\njulia> put(4, (1, 3)=>kron(X, Y))\nnqubits: 4\nput on (1, 3)\n└─ kron\n ├─ 1=>X\n └─ 2=>Y\n\nThe outter locations creates a scope which make it seems to be a contiguous two qubits for the block inside PutBlock.\n\ntips: Tips\nIt is better to use subroutine instead of put for large blocks, since put will use the matrix of its contents directly instead of making use of what's in it. put is more efficient for small blocks.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.rand_hermitian-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.rand_hermitian","text":"rand_hermitian([T=ComplexF64], N::Int) -> Matrix\n\nCreate a random hermitian matrix.\n\njulia> ishermitian(rand_hermitian(2))\ntrue\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.rand_unitary-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.rand_unitary","text":"rand_unitary([T=ComplexF64], N::Int) -> Matrix\n\nCreate a random unitary matrix.\n\nExamples\n\njulia> isunitary(rand_unitary(2))\ntrue\n\njulia> eltype(rand_unitary(ComplexF32, 2))\nComplexF32 (alias for Complex{Float32})\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.reflect","page":"Blocks","title":"YaoBlocks.reflect","text":"reflect(\n v::AbstractArrayReg\n) -> ReflectGate{D, T, Irrational{:π}, AT} where {D, T, AT<:(AbstractArrayReg{D, T})}\nreflect(\n v::AbstractArrayReg,\n θ::Real\n) -> ReflectGate{_A, T, Tt, AT} where {_A, Tt<:Real, T, AT<:(AbstractArrayReg{_A, T})}\n\n\nCreate a ReflectGate with respect to an quantum state vector v.\n\nExample\n\njulia> reflect(rand_state(3))\nTime Evolution Δt = π, tol = 1.0e-7\n|s⟩⟨s|, nqudits = 3\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.rmlines-Tuple{Expr}","page":"Blocks","title":"YaoBlocks.rmlines","text":"rmlines(ex)\n\nRemove LineNumberNode from an Expr.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.rot-Tuple{AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.rot","text":"rot(U, theta)\n\nReturn a RotationGate on U axis.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.sandwich-Tuple{AbstractArrayReg, AbstractBlock, AbstractArrayReg}","page":"Blocks","title":"YaoBlocks.sandwich","text":"sandwich(bra::AbstractRegister, op::AbstractBlock, ket::AbstracRegister) -> Complex\n\nCompute the sandwich function ⟨bra|op|ket⟩.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.setcol!-Tuple{SparseMatrixCSC, Int64, AbstractVector, Any}","page":"Blocks","title":"YaoBlocks.setcol!","text":"setcol!(csc::SparseMatrixCSC, icol::Int, rowval::AbstractVector, nzval) -> SparseMatrixCSC\n\nset specific col of a CSC matrix\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.setiparams","page":"Blocks","title":"YaoBlocks.setiparams","text":"setiparams([f], block, itr)\nsetiparams([f], block, params...)\n\nSet the parameters of block, the non-inplace version. When f is provided, set parameters of block to the value in collection mapped by f. iter can be an iterator or a symbol, the symbol can be :zero, :random.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.shift-Tuple{Any}","page":"Blocks","title":"YaoBlocks.shift","text":"shift(θ)\n\nCreate a ShiftGate with phase θ.\n\nbeginpmatrix\n1 0\n0 e^itheta\nendpmatrix\n\nExamples\n\njulia> shift(0.1)\nshift(0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.simple_commute_eachother-Union{Tuple{Vector{<:AbstractBlock{D}}}, Tuple{D}} where D","page":"Blocks","title":"YaoBlocks.simple_commute_eachother","text":"Return true if operators commute to each other.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.single_qubit_depolarizing_channel-Tuple{Real}","page":"Blocks","title":"YaoBlocks.single_qubit_depolarizing_channel","text":"single_qubit_depolarizing_channel(p::Real)\n\nCreate a single-qubit depolarizing channel.\n\nThe factor of 3/4 in front of p ensures that single_qubit_depolarizing_channel(p) == depolarizing_channel(1, p)\n\n(1 - 3p4 ρ) + p4(XρX + YρY + ZρZ)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.sprand_hermitian-Tuple{Int64, Any}","page":"Blocks","title":"YaoBlocks.sprand_hermitian","text":"sprand_hermitian([T=ComplexF64], N, density)\n\nCreate a sparse random hermitian matrix.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.sprand_unitary-Tuple{Int64, Real}","page":"Blocks","title":"YaoBlocks.sprand_unitary","text":"sprand_unitary([T=ComplexF64], N::Int, density) -> SparseMatrixCSC\n\nCreate a random sparse unitary matrix.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.subroutine-Tuple{AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.subroutine","text":"subroutine(block, locs) -> f(n)\n\nLazy curried version of subroutine.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.subroutine-Tuple{Int64, AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.subroutine","text":"subroutine(n, block, locs)\n\nCreate a n-qudit Subroutine block, where the subblock is a subprogram of size m, and locs is a tuple or range of length m. It runs a quantum subprogram with smaller size on a subset of locations. While its mathematical definition is the same as the put block, while it is more suited for running a larger chunk of circuit.\n\nExamples\n\nSubroutine is equivalent to put a block on given position mathematically, but more efficient and convenient for large blocks.\n\njulia> r = rand_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> apply!(copy(r), subroutine(X, 1)) ≈ apply!(copy(r), put(1=>X))\ntrue\n\nIt works for in-contigious locs as well\n\njulia> r = rand_state(4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> cc = subroutine(4, kron(X, Y), (1, 3))\nnqubits: 4\nSubroutine: (1, 3)\n└─ kron\n ├─ 1=>X\n └─ 2=>Y\n\njulia> pp = chain(4, put(1=>X), put(3=>Y))\nnqubits: 4\nchain\n├─ put on (1)\n│ └─ X\n└─ put on (3)\n └─ Y\n\njulia> apply!(copy(r), cc) ≈ apply!(copy(r), pp)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.swap-Tuple{Int64, Int64, Int64}","page":"Blocks","title":"YaoBlocks.swap","text":"swap(n, loc1, loc2)\n\nCreate a n-qubit Swap gate which swap loc1 and loc2.\n\nExamples\n\njulia> swap(4, 1, 2)\nnqubits: 4\nput on (1, 2)\n└─ SWAP\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.swap-Tuple{Int64, Int64}","page":"Blocks","title":"YaoBlocks.swap","text":"swap(loc1, loc2) -> f(n)\n\nCreate a lambda that takes the total number of active qubits as input. Lazy curried version of swap(n, loc1, loc2). See also Swap.\n\nExamples\n\njulia> swap(1, 2)\n(n -> swap(n, 1, 2))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.time_evolve-Tuple{AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.time_evolve","text":"time_evolve(H, dt[; tol=1e-7, check_hermicity=true])\n\nCreate a TimeEvolution block with Hamiltonian H and time step dt. The TimeEvolution block will use Krylove based expv to calculate time propagation. TimeEvolution block can also be used for imaginary time evolution if dt is complex. Let H be a hamiltonian and t be a time, the matrix representation of time_evolve(H, t) is e^-iHt.\n\nArguments\n\nH the hamiltonian represented as an AbstractBlock.\ndt: the evolution duration (start time is zero).\n\nKeyword Arguments\n\ntol::Real=1e-7: error tolerance.\ncheck_hermicity=true: check hermicity or not.\n\nExamples\n\njulia> time_evolve(kron(2, 1=>X, 2=>X), 0.1)\nTime Evolution Δt = 0.1, tol = 1.0e-7\nkron\n├─ 1=>X\n└─ 2=>X\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.two_qubit_depolarizing_channel-Tuple{Real}","page":"Blocks","title":"YaoBlocks.two_qubit_depolarizing_channel","text":"two_qubit_depolarizing_channel(p::Real)\n\nCreate a two-qubit depolarizing channel. Note that this is not the same as kron(single_qubit_depolarizing_channel(p), single_qubit_depolarizing_channel(p)).\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.u1ij!","page":"Blocks","title":"YaoBlocks.u1ij!","text":"u1ij!(target, i, j, a, b, c, d)\n\nsingle u1 matrix into a target matrix.\n\nnote: Note\nFor coo, we take an additional parameter * ptr: starting position to store new data.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.unitary_channel-Tuple{Any, AbstractVector}","page":"Blocks","title":"YaoBlocks.unitary_channel","text":"unitary_channel(operators, probs) -> UnitaryChannel\n\nReturns a UnitaryChannel instance, where `operators is a list of operators, probs is a real vector that sum up to 1. The unitary channel is defined as below\n\nphi(rho) = sum_i p_i U_i ρ U_i^dagger\n\nwhere rho in a DensityMatrix as the register to apply on, p_i is the i-th element in probs, U_i is the i-th operator in operators.\n\nExamples\n\njulia> unitary_channel([X, Y, Z], [0.1, 0.2, 0.7])\nnqubits: 1\nunitary_channel\n├─ [0.1] X\n├─ [0.2] Y\n└─ [0.7] Z\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.unmat-Tuple{Val{2}, Int64, AbstractMatrix, NTuple{N, T} where {N, T}}","page":"Blocks","title":"YaoBlocks.unmat","text":"unmat(::Val{D}, nbit::Int, U::AbstractMatrix, locs::NTuple) -> AbstractMatrix\n\nReturn the matrix representation of putting matrix at locs.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.@yao_str-Tuple{String}","page":"Blocks","title":"YaoBlocks.@yao_str","text":"@yao_str\nyao\"...\"\n\nThe mark up language for quantum circuit.\n\n\n\n\n\n","category":"macro"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"CurrentModule = YaoPlots\nDocTestSetup = quote\n using Yao\n using Yao: YaoBlocks, YaoArrayRegister, YaoSym\n using YaoBlocks\n using YaoArrayRegister\n using YaoPlots\nend","category":"page"},{"location":"man/plot.html#Quantum-Circuit-Visualization","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"YaoPlots is the Quantum circuit visualization component for Yao.","category":"page"},{"location":"man/plot.html#Examples","page":"Quantum Circuit Visualization","title":"Examples","text":"","category":"section"},{"location":"man/plot.html#Example-1:-Visualize-a-QBIR-define-in-Yao","page":"Quantum Circuit Visualization","title":"Example 1: Visualize a QBIR define in Yao","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"using Yao.EasyBuild, YaoPlots\n\n# show a qft circuit\nvizcircuit(qft_circuit(5))","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"If you are using a Pluto/Jupyter notebook, Atom/VSCode editor, you should see the above image in your plotting panel.","category":"page"},{"location":"man/plot.html#Example-2:-Visualize-a-single-qubit","page":"Quantum Circuit Visualization","title":"Example 2: Visualize a single qubit","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"using YaoPlots, Yao\n\nreg = zero_state(1) |> Rx(π/8) |> Rx(π/8)\nrho = density_matrix(ghz_state(2), 1)\n\nbloch_sphere(\"|ψ⟩\"=>reg, \"ρ\"=>rho; show_projection_lines=true)","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"See more examples.","category":"page"},{"location":"man/plot.html#Adjusting-the-plot-attributes","page":"Quantum Circuit Visualization","title":"Adjusting the plot attributes","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"Various attributes of the visualizations can be altered. The plot can be modified, if we change the following attributes","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"YaoPlots.CircuitStyles.linecolor[] for line color, default value being \"#000000\" (black color)\nYaoPlots.CircuitStyles.gate_bgcolor[] for background color of square blocks, the default value being \"#FFFFFF\" (white color)\nYaoPlots.CircuitStyles.textcolor[] for text color, default value being \"#000000\nYaoPlots.CircuitStyles.lw[] for line width, default value being 1 (pt)\nYaoPlots.CircuitStyles.textsize[] for text size, default value being 16 (pt)\nYaoPlots.CircuitStyles.paramtextsize[] for parameter text size, for parameterized gates, default value being 10 (pt)","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"For example,","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"using YaoPlots, Yao\nYaoPlots.CircuitStyles.linecolor[] = \"pink\" \nYaoPlots.CircuitStyles.gate_bgcolor[] = \"yellow\" \nYaoPlots.CircuitStyles.textcolor[] = \"#000080\" # the navy blue color\nYaoPlots.CircuitStyles.fontfamily[] = \"JuliaMono\"\nYaoPlots.CircuitStyles.lw[] = 2.5\nYaoPlots.CircuitStyles.textsize[] = 13\nYaoPlots.CircuitStyles.paramtextsize[] = 8\n\t\t\nvizcircuit(chain(3, put(1=>X), repeat(3, H), put(2=>Y), repeat(3, Rx(π/2))))","category":"page"},{"location":"man/plot.html#Circuit-Visualization","page":"Quantum Circuit Visualization","title":"Circuit Visualization","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"vizcircuit\nplot","category":"page"},{"location":"man/plot.html#YaoPlots.vizcircuit","page":"Quantum Circuit Visualization","title":"YaoPlots.vizcircuit","text":"vizcircuit(circuit; w_depth=0.85, w_line=0.75, format=:svg, filename=nothing,\n show_ending_bar=false, starting_texts=nothing, starting_offset=-0.3,\n ending_texts=nothing, ending_offset=0.3)\n\nVisualize a Yao quantum circuit.\n\nKeyword Arguments\n\nw_depth is the circuit column width.\nw_line is the circuit row width.\nformat can be :svg, :png or :pdf.\nfilename can be \"*.svg\", \"*.png\", \"*.pdf\" or nothing (not saving to a file).\nstarting_texts and ending_texts are texts shown before and after the circuit.\nstarting_offset and end_offset are offsets (real values) for starting and ending texts.\nshow_ending_bar is a boolean switch to show ending bar.\n\nStyles\n\nTo change the gates styles like colors and lines, please modify the constants in submodule CircuitStyles. They are defined as:\n\nCircuitStyles.unit = Ref(60) # number of points in a unit\nCircuitStyles.r = Ref(0.2) # size of nodes\nCircuitStyles.lw = Ref(1.0) # line width\nCircuitStyles.textsize = Ref(16.0) # text size\nCircuitStyles.paramtextsize = Ref(10.0) # text size (longer texts)\nCircuitStyles.fontfamily = Ref(\"JuliaMono\") # font family\nCircuitStyles.linecolor = Ref(\"#000000\") # line color\nCircuitStyles.gate_bgcolor = Ref(\"transparent\") # gate background color\nCircuitStyles.textcolor = Ref(\"#000000\") # text color\n\n\n\n\n\n","category":"function"},{"location":"man/plot.html#YaoPlots.plot","page":"Quantum Circuit Visualization","title":"YaoPlots.plot","text":"An alias of vizcircuit\n\n\n\n\n\n","category":"function"},{"location":"man/plot.html#Bloch-Sphere-Visualization","page":"Quantum Circuit Visualization","title":"Bloch Sphere Visualization","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"CircuitStyles\nbloch_sphere\nBlochStyles","category":"page"},{"location":"man/plot.html#YaoPlots.CircuitStyles","page":"Quantum Circuit Visualization","title":"YaoPlots.CircuitStyles","text":"CircuitStyles\n\nA module to define the styles of the circuit visualization. To change the styles, please modify the variables in this module, e.g.\n\njulia> using YaoPlots\n\njulia> YaoPlots.CircuitStyles.unit[] = 40\n40\n\nStyle variables\n\nSizes\n\nunit is the number of pixels in a unit.\nr is the size of nodes.\nlw is the line width.\n\nTexts\n\ntextsize is the text size.\nparamtextsize is the text size for longer texts.\nfontfamily is the font family.\n\nColors\n\nlinecolor is the line color.\ngate_bgcolor is the gate background color.\ntextcolor is the text color.\n\n\n\n\n\n","category":"module"},{"location":"man/plot.html#YaoPlots.bloch_sphere","page":"Quantum Circuit Visualization","title":"YaoPlots.bloch_sphere","text":"bloch_sphere(\n states...;\n textsize,\n color,\n drawing_size,\n offset_x,\n offset_y,\n filename,\n format,\n fontfamily,\n background_color,\n lw,\n eye_point,\n extra_kwargs...\n) -> Luxor.Drawing\n\n\nDraw a bloch sphere, with the inputs being a list of string => state pairs, where the string is a label for the state and a state can be a complex vector of size 2, a Yao register or DensityMatrix. If you want to get a raw drawing, use draw_bloch_sphere instead.\n\nKeyword Arguments\n\nNote: The default values can be specified in submodule BlochStyles.\n\ntextsize: the size of the text\ncolor: the color of the drawing\ndrawing_size: the size of the drawing\noffset_x: the offset of the drawing in x direction\noffset_y: the offset of the drawing in y direction\nfilename: the filename of the output file, if not specified, a temporary file will be used\nformat: the format of the output file, if not specified, the format will be inferred from the filename\nfontfamily: the font family of the text\nbackground_color: the background color of the drawing\nlw: the line width of the drawing\neye_point: the eye point of the drawing\nextra_kwargs: extra keyword arguments passed to draw_bloch_sphere\ndot_size: the size of the dot\nball_size: the size of the ball\nshow_projection_lines: whether to show the projection lines\nshow_angle_texts: whether to show the angle texts\nshow_line: whether to show the line\nshow01: whether to show the 0 and 1 states\ncolors: the colors of the states\naxes_lw: the line width of the axes\naxes_textsize: the size of the axes texts\naxes_colors: the colors of the axes\naxes_texts: the texts of the axes\n\nExamples\n\njulia> using YaoPlots, YaoArrayRegister\n\njulia> bloch_sphere(\"|ψ⟩\"=>rand_state(1), \"ρ\"=>density_matrix(rand_state(2), 1));\n\n\n\n\n\n","category":"function"},{"location":"man/plot.html#YaoPlots.BlochStyles","page":"Quantum Circuit Visualization","title":"YaoPlots.BlochStyles","text":"BlochStyles\n\nThe module to define the default styles for bloch sphere drawing. To change the default styles, you can modify the values in this module, e.g.\n\nusing YaoPlots\nYaoPlots.BlochStyles.lw[] = 2.0\n\nStyle variables\n\nGeneric\n\nlw: the line width of the drawing\ntextsize: the size of the text\nfontfamily: the font family of the text\nbackground_color: the background color of the drawing\ncolor: the color of the drawing\n\nSphere\n\nball_size: the size of the ball\ndot_size: the size of the dot\neye_point: the eye point of the drawing\n\nAxis\n\naxes_lw: the line width of the axes\naxes_colors: the colors of the axes\naxes_texts: the texts of the axes, default to [\"x\", \"y\", \"z\"]\n\nState display\n\nshow_projection_lines: whether to show the projection lines\nshow_angle_texts: whether to show the angle texts\nshow_line: whether to show the line\nshow01: whether to show the 0 and 1 states\n\n\n\n\n\n","category":"module"},{"location":"man/plot.html#Themes","page":"Quantum Circuit Visualization","title":"Themes","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"darktheme!\nlighttheme!","category":"page"},{"location":"man/plot.html#YaoPlots.darktheme!","page":"Quantum Circuit Visualization","title":"YaoPlots.darktheme!","text":"darktheme!()\n\nChange the default theme to dark.\n\n\n\n\n\n","category":"function"},{"location":"man/plot.html#YaoPlots.lighttheme!","page":"Quantum Circuit Visualization","title":"YaoPlots.lighttheme!","text":"lighttheme!()\n\nChange the default theme to light.\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#Tensor-network-backend","page":"Tensor network backend","title":"Tensor network backend","text":"","category":"section"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"Simulating quantum circuits using tensor networks has been studied in the literature[Markov2008][Pan2022]. The YaoToEinsum package provides a convenient way to convert Yao circuits to tensor networks, which can be used for further analysis and optimization.","category":"page"},{"location":"man/yao2einsum.html#Tutorial","page":"Tensor network backend","title":"Tutorial","text":"","category":"section"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"The main function is","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"yao2einsum(circuit; initial_state=Dict(), final_state=Dict(), optimizer=TreeSA())","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"which transforms a Yao circuit to a tensor network that generalizes the hyper-graph (einsum notation). The return value is a TensorNetwork object.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"initial_state and final_state are for specifying the initial state and final state. Left the qubits unspecified if you want to keep them as the open indices.\noptimizer is for specifying the contraction order optimizing algorithm of the tensor network. The default value is the TreeSA() algorithm that developed in [Kalachev2021][Liu2023]. Please check the README of OMEinsumEinsumContractors.jl for more information.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"In the following example, we show how to convert a quantum Fourier transform circuit to a tensor network and contract it to","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"Get the matrix representation of the circuit.\nGet the probability of measuring the zero state after applying the circuit on the zero state.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"import Yao\nusing Yao.EasyBuild: qft_circuit\nn = 10;\ncircuit = qft_circuit(n); # build a quantum Fourier transform circuit\nnetwork = Yao.yao2einsum(circuit) # convert this circuit to tensor network\nreshape(Yao.contract(network), 1<0 for i=1:n]), final_state=Dict([i=>0 for i=1:n]),\n optimizer=Yao.YaoToEinsum.TreeSA(; nslices=3)) # slicing technique\nYao.contract(network)[] ≈ Yao.zero_state(n)' * (Yao.zero_state(n) |> circuit)","category":"page"},{"location":"man/yao2einsum.html#API","page":"Tensor network backend","title":"API","text":"","category":"section"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"yao2einsum\nTensorNetwork\noptimize_code\ncontraction_complexity\ncontract","category":"page"},{"location":"man/yao2einsum.html#YaoToEinsum.yao2einsum","page":"Tensor network backend","title":"YaoToEinsum.yao2einsum","text":"yao2einsum(circuit; initial_state=Dict(), final_state=Dict(), optimizer=TreeSA())\nyao2einsum(circuit, initial_state::Dict, final_state::Dict, optimizer)\n\nTransform a Yao circuit to a generalized tensor network (einsum) notation. The return value is a TensorNetwork instance.\n\nArguments\n\ncircuit is a Yao block as the input.\ninitial_state and final_state are dictionaries to specify the initial states and final states (taking conjugate).\nIn the first interface, a state is specified as an integer, e.g. Dict(1=>1, 2=>1, 3=>0, 4=>1) specifies a product state |1⟩⊗|1⟩⊗|0⟩⊗|1⟩.\nIn the second interface, a state is specified as an ArrayReg, e.g. Dict(1=>rand_state(1), 2=>rand_state(1)).\n\nIf any qubit in initial state or final state is not specified, it will be treated as a free leg in the tensor network.\n\noptimizer is the optimizer used to optimize the tensor network. The default is TreeSA().\n\nPlease check OMEinsumContractors.jl for more information.\n\njulia> using Yao\n\njulia> c = chain(3, put(3, 2=>X), put(3, 1=>Y), control(3, 1, 3=>Y))\nnqubits: 3\nchain\n├─ put on (2)\n│ └─ X\n├─ put on (1)\n│ └─ Y\n└─ control(1)\n └─ (3,) Y\n\n\njulia> yao2einsum(c; initial_state=Dict(1=>0, 2=>1), final_state=Dict(1=>ArrayReg([0.6, 0.8im]), 2=>1))\nTensorNetwork\nTime complexity: 2^4.700439718141093\nSpace complexity: 2^2.0\nRead-write complexity: 2^6.0\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#YaoToEinsum.TensorNetwork","page":"Tensor network backend","title":"YaoToEinsum.TensorNetwork","text":"TensorNetwork\n\nA (generalized) tensor network representation of a quantum circuit.\n\nFields\n\ncode::AbstractEinsum: The einsum code.\ntensors::Vector: The tensors in the network.\n\n\n\n\n\n","category":"type"},{"location":"man/yao2einsum.html#OMEinsumContractionOrders.optimize_code","page":"Tensor network backend","title":"OMEinsumContractionOrders.optimize_code","text":"optimize_code(c::TensorNetwork, optimizer=TreeSA())\n\nOptimize the code of the tensor network.\n\nArguments\n\nc::TensorNetwork: The tensor network.\noptimizer::Optimizer: The optimizer to use, default is TreeSA(). Please check OMEinsumContractors.jl for more information.\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#OMEinsumContractionOrders.contraction_complexity","page":"Tensor network backend","title":"OMEinsumContractionOrders.contraction_complexity","text":"contraction_complexity(c::TensorNetwork)\n\nReturn the contraction complexity of the tensor network.\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#YaoToEinsum.contract","page":"Tensor network backend","title":"YaoToEinsum.contract","text":"contract(c::TensorNetwork)\n\nContract the tensor network, and return the result tensor.\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#References","page":"Tensor network backend","title":"References","text":"","category":"section"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"[Pan2022]: Pan, Feng, and Pan Zhang. \"Simulation of quantum circuits using the big-batch tensor network method.\" Physical Review Letters 128.3 (2022): 030501.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"[Kalachev2021]: Kalachev, Gleb, Pavel Panteleev, and Man-Hong Yung. \"Recursive multi-tensor contraction for xeb verification of quantum circuits.\" arXiv preprint arXiv:2108.05665 (2021).","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"[Markov2008]: Markov, Igor L., and Yaoyun Shi. \"Simulating quantum computation by contracting tensor networks.\" SIAM Journal on Computing 38.3 (2008): 963-981.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"[Liu2023]: Liu, Jin-Guo, et al. \"Computing solution space properties of combinatorial optimization problems via generic tensor networks.\" SIAM Journal on Scientific Computing 45.3 (2023): A1239-A1270.","category":"page"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"CurrentModule = YaoSym\nDocTestSetup = quote\n using Yao\n using Yao: YaoBlocks, YaoArrayRegister, YaoSym\n using YaoBlocks\n using YaoArrayRegister\n using YaoSym\nend","category":"page"},{"location":"man/symbolic.html#Symbolic-Computation","page":"Symbolic Computation","title":"Symbolic Computation","text":"","category":"section"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"The symbolic engine of Yao is based on SymEngine.jl. It allows one to define quantum circuits with symbolic parameters and perform symbolic computation on them. Two macro/functions play a key role in the symbolic computation:","category":"page"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"@vars for defining symbolic variables\nsubs for substituting symbolic variables with concrete values","category":"page"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"using Yao\n@vars θ\ncircuit = chain(2, put(1=>H), put(2=>Ry(θ)))\nmat(circuit)\nnew_circuit = subs(circuit, θ=>π/2)\nmat(new_circuit)","category":"page"},{"location":"man/symbolic.html#API","page":"Symbolic Computation","title":"API","text":"","category":"section"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"The following functions are for working with symbolic states.","category":"page"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"@ket_str\n@bra_str\nszero_state","category":"page"},{"location":"man/symbolic.html#YaoSym.@ket_str","page":"Symbolic Computation","title":"YaoSym.@ket_str","text":"@ket_str\n\nCreate a ket register. See also @bra_str.\n\nExamples\n\na symbolic quantum state can be created simply by\n\njulia> ket\"110\" + 2ket\"111\"\n|110⟩ + 2.0|111⟩\n\nqubits can be partially actived by focus!\n\njulia> ket\"100\" + ket\"111\" |> focus!(1:2)\n|100⟩ + |111⟩\n\n\n\n\n\n","category":"macro"},{"location":"man/symbolic.html#YaoSym.@bra_str","page":"Symbolic Computation","title":"YaoSym.@bra_str","text":"@bra_str\n\nCreate a bra register. See also @ket_str.\n\nExamples\n\nSimilar to @ket_str literal, a symbolic quantum state can be created by\n\njulia> bra\"111\" + 2bra\"101\"\n2.0⟨101| + ⟨111|\n\njulia> bra\"111\" * (ket\"101\" + ket\"111\")\n1\n\n\n\n\n\n","category":"macro"},{"location":"man/symbolic.html#YaoSym.szero_state","page":"Symbolic Computation","title":"YaoSym.szero_state","text":"szero_state(n; nbatch=1)\n\nCreate a symbolic zero state, same as ket\"000\", but allows you use an integer.\n\n\n\n\n\n","category":"function"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"EditURL = \"../../../examples/4.shor-algorithm/main.jl\"","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"(Image: )","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#Shor","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html#References","page":"Shor's Algorithm","title":"References","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Neilsen\nAn Insightful Blog","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"The main program of a Shor's algorithm can be summrized in several lines of code. For the theory part, please refer the reference materials above. It factorize an integer L, and returns one of the factors.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"using Yao, BitBasis\nusing Yao.EasyBuild: qft_circuit","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#Number-theory-basic","page":"Shor's Algorithm","title":"Number theory basic","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Before entering the main program, let us defined some useful functions in number theory.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"module NumberTheory\n\nexport Z_star, Eulerφ, continued_fraction, mod_inverse, rand_primeto, factor_a_power_b\nexport is_order, order_from_float, find_order\n\n\"\"\"\n Z_star(N::Int) -> Vector\n\nreturns the Z* group elements of `N`, i.e. {x | gcd(x, N) == 1}\n\"\"\"\nZ_star(N::Int) = filter(i->gcd(i, N)==1, 0:N-1)\nEulerφ(N) = length(Z_star(N))\n\n\"\"\"\n continued_fraction(ϕ, niter::Int) -> Rational\n\nobtain `s` and `r` from `ϕ` that satisfies `|s/r - ϕ| ≦ 1/2r²`\n\"\"\"\ncontinued_fraction(ϕ, niter::Int) = niter==0 || isinteger(ϕ) ? floor(Int, ϕ) : floor(Int, ϕ) + 1//continued_fraction(1/mod(ϕ, 1), niter-1)\ncontinued_fraction(ϕ::Rational, niter::Int) = niter==0 || ϕ.den==1 ? floor(Int, ϕ) : floor(Int, ϕ) + 1//continued_fraction(1/mod(ϕ, 1), niter-1)\n\n\"\"\"\n mod_inverse(x::Int, N::Int) -> Int\n\nReturn `y` that `(x*y)%N == 1`, notice the `(x*y)%N` operations in Z* forms a group and this is the definition of inverse.\n\"\"\"\nfunction mod_inverse(x::Int, N::Int)\n for i=1:N\n (x*i)%N == 1 && return i\n end\n throw(ArgumentError(\"Can not find the inverse, $x is probably not in Z*($N)!\"))\nend\n\n\"\"\"\n is_order(r, x, N) -> Bool\n\nReturns true if `r` is the order of `x`, i.e. `r` satisfies `x^r % N == 1`.\n\"\"\"\nis_order(r, x, N) = powermod(x, r, N) == 1\n\n\"\"\"\n find_order(x::Int, N::Int) -> Int\n\nFind the order of `x` by brute force search.\n\"\"\"\nfunction find_order(x::Int, N::Int)\n findfirst(r->is_order(r, x, N), 1:N)\nend\n\n\"\"\"\n rand_primeto(N::Int) -> Int\n\nReturns a random number `2 ≦ x < N` that is prime to `N`.\n\"\"\"\nfunction rand_primeto(N::Int)\n while true\n x = rand(2:N-1)\n d = gcd(x, N)\n if d == 1\n return x\n end\n end\nend\n\n\"\"\"\n order_from_float(ϕ, x, L) -> Int\n\nEstimate the order of `x` to `L`, `r`, from a floating point number `ϕ ∼ s/r` using the continued fraction method.\n\"\"\"\nfunction order_from_float(ϕ, x, L)\n k = 1\n rnum = continued_fraction(ϕ, k)\n while rnum.den < L && k < 100\n r = rnum.den\n if is_order(r, x, L)\n return r\n end\n k += 1\n rnum = continued_fraction(ϕ, k)\n end\n return nothing\nend\n\n\"\"\"\n factor_a_power_b(N::Int) -> (Int, Int) or nothing\n\nFactorize `N` into the power form `a^b`.\n\"\"\"\nfunction factor_a_power_b(N::Int)\n y = log2(N)\n for b = 2:ceil(Int, y)\n x = 2^(y/b)\n u1 = floor(Int, x)\n u1^b == N && return (u1, b)\n (u1+1)^b == N && return (u1+1, b)\n end\nend\n\nend","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Main.var\"##235\".NumberTheory","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#A-quantum-function-to-compute-mod","page":"Shor's Algorithm","title":"A quantum function to compute mod","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Before introducing the main program, let us customize a block for computing the classical function mod. In a more practical setup, it should be compiled to basic quantum gates. Here we just hack this function for simplicity.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"\"\"\"\n KMod <: PrimitiveBlock{2}\n\nThe first `k` qubits are exponent, and the rest `n-k` are base `a`,\nit calculates `mod(a^k*x, L)`, notice `gcd(a, L)` should be 1.\n\"\"\"\nstruct KMod <: PrimitiveBlock{2}\n n::Int\n k::Int\n a::Int\n L::Int\n function KMod(n, k, a, L)\n @assert gcd(a, L) == 1 && L<=1<<(n-k)\n new(n, k, a, L)\n end\nend\n\nYao.nqudits(m::KMod) = m.n\n\nfunction bint2_reader(T, k::Int)\n mask = bmask(T, 1:k)\n return b -> (b&mask, b>>k)\nend\n\nfunction Yao.unsafe_apply!(reg::AbstractArrayReg, m::KMod)\n nstate = zero(reg.state)\n\n reader = bint2_reader(Int, m.k)\n for b in 0:1<= m.L ? i : mod(i*powermod(m.a, k, m.L), m.L)\n _b = k + _i<= m.L ? i : mod(i*powermod(m.a, k, m.L), m.L)\n _b = k + _i< c; nshots=nshots)\n for r in res\n # split bit string b into lower bits `k` and higher bits `r`.\n mask = bmask(1:ncbit)\n k,i = r&mask, r>>ncbit\n # get s/r\n ϕ = bfloat(k) #\n ϕ == 0 && continue\n\n # order_from_float: given a floating point number,\n # return the closest rational number with bounded number of continued fraction steps.\n order = NumberTheory.order_from_float(ϕ, x, L)\n if order === nothing\n continue\n else\n return order\n end\n end\n return nothing\nend","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"get_order (generic function with 2 methods)","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#The-circuit-used-for-finding-order","page":"Shor's Algorithm","title":"The circuit used for finding order","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"\"\"\"\n order_finding_circuit(x::Int, L::Int; nbit::Int=bit_length(L-1), ncbit::Int=estimate_ncbit(nbit, 0.25)) -> AbstractBlock\n\nReturns the circuit for finding the order of `x` to `L`,\nfeeding input `|1>⊗|0>` will get the resulting quantum register with the desired \"phase\" information.\n\"\"\"\nfunction order_finding_circuit(x::Int, L::Int; nbit::Int, ncbit::Int)\n N = nbit+ncbit\n chain(N, repeat(N, H, 1:ncbit), KMod(N, ncbit, x, L),\n subroutine(N, qft_circuit(ncbit)', 1:ncbit))\nend","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Main.var\"##235\".order_finding_circuit","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"The circuit for order finding is consisted of three parts","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Hadamard gates,\nKMod that computes a classical function mod(a^k*x, L).","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"k is the integer stored in first K (or ncbit) qubits and the rest N-K qubits stores a. Notice it is not a basic gate, it should have been compiled to multiple gates, which is not implemented in Yao for the moment. To learn more about implementing arithmatics on a quantum circuit, please read this paper.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Inverse quantum fourier transformation.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#Run","page":"Shor's Algorithm","title":"Run","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Factorizing 15, you should see 3 or 5, please report a bug if it is not...","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"shor(15, Val(:quantum))","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"3","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"EditURL = \"../../../examples/8.riemannian-gradient-flow/main.jl\"","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"(Image: )","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html#Riemannian-gradient-flow-optimizer","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"","category":"section"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"In this tutorial we will present the Riemannian gradient descent algorithm described in Miao and Barthel (2021) and Wiersema and Killoran (2022) As opposed to most standard optimization algorithms that optimize parameters of variational quantum circuits, this algorithm optimizes a function directly over the special unitary group by following the gradient flow over the manifold. Let's start by importing the necessary packages.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"using Yao, Yao.EasyBuild, Plots, Random\nusing KrylovKit: eigsolve","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Variational quantum eigensolver (VQE) is one of the most celebrated near-term quantum algorithms. In the usual setting, VQE tries to reach the ground state by minimizing the energy cost function","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"mathcalL(theta) = textTrHU(theta)rho_0U^dagger(theta)","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"with respect to parameters theta which parameterize a quantum circuit U(theta), where rho_0 = psi_0ranglelanglepsi_0 is some initial state and H the Hamiltonian whose ground state we want to approximate. We can solve the optimization problem textmin_thetamathcalL(theta) by following the direction of the steepest descent in parameter space which is given by the gradient of the cost function, i.e. by considering the following gradient flow","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"dottheta = -textgradmathcalL(theta)","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Discretizing the equation above, we recover the well-known gradient descent algorithm","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"theta_k + 1 = theta_k - alphatextgradmathcalL(theta)","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"where alpha is the learning rate. Let's demonstrate it on the example of finding the ground state of the transverse field Ising model.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"n = 8\nh = transverse_ising(n, 1.0)\nw, v = eigsolve(mat(h), 1, :SR, ishermitian=true)\n\nRandom.seed!(0)\ncircuit = dispatch!(variational_circuit(n, 100), :random);\nhistory = Float64[]\nfor i in 1:100\n _, grad = expect'(h, zero_state(n) => circuit)\n dispatch!(-, circuit, 0.01 * grad)\n push!(history, real.(expect(h, zero_state(n)=>circuit)))\nend\n\nPlots.plot(history, legend=false)\nPlots.plot!(1:100, [w[1] for i=1:100])\nxlabel!(\"steps\")\nylabel!(\"energy\")","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Let's now consider the energy cost function directly over the special unitary group mathcalL textSU(2^n) rightarrow mathbbR","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"mathcalL(U) = textTrHUrho_0U^dagger","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"To minimize the cost function we can follow the Riemannian gradient flow defined through the following differential equation","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"dotU = -textgradmathcalL(U) = Urho_0U^dagger HU","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Discretizing the flow we get the following recursive update rule","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"U_k + 1 = expalphaU_krho_0U^dagger_k HU_k = expalpharho_k HU_k","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"where alpha is the appropriate learning rate and U_0 = I.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"We can expand the commutator in the exponent in the basis of Pauli strings P^j","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"rho_k H = frac12^nsum_j = 1^4^n - 1omega^j_kP^j","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"where","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"omega^j_k = textTrrho_k HP^j = textTrH P^jrho_k = langleH P^jrangle_rho_k","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"It turns out that omega^j_k can easily be evaluated with the help of a parameter shift rule","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"omega^j_k = langleH P^jrangle_rho_k = -ilangle V^dagger_j(pi4)HV_j(pi4) - V^dagger_j(-pi4)HV_j(-pi4)rangle_rho_k","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"where V_j(t) = exp-itP^j.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Next, we write a function for generation of 2-local Pauli operators. We will restrict the Riemannian gradient to this subspace of the Lie algebra since otherwise the number of parameters to calculate would be 4^8 - 1 = 65535 which is too much for a reasonable runtime of the algorithm.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"function generate_2local_pauli_strings(n)\n pauli_strings = []\n for i = 1:n\n push!(pauli_strings, kron(n, i => X))\n push!(pauli_strings, kron(n, i => Y))\n push!(pauli_strings, kron(n, i => Z))\n end\n for i = 1:n-1\n for j = i+1:n\n for P1 in [X, Y, Z]\n for P2 in [X, Y, Z]\n push!(pauli_strings, kron(n, i => P1, j => P2))\n end\n end\n end\n end\n pauli_strings\nend;","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Next we write functions for calculating the expansion coefficients and a single optimization step. We will absorb the factor of 12^n into the learning rate.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"function calculate_omegas(n, reg, h, pauli_strings)\n iω = []\n for P in pauli_strings\n push!(iω, real(expect(h, reg => time_evolve(P, π/4)) - expect(h, reg => time_evolve(P, -π/4))))\n end\n iω\nend;\n\nfunction step_and_cost!(n, circuit, h, α, pauli_strings)\n iω = calculate_omegas(n, zero_state(n) |> circuit, h, pauli_strings)\n\n for (iωʲ, P) in zip(iω, pauli_strings)\n if abs(iωʲ) > 1e-6 # we will only keep the ones that actually contribute\n append!(circuit, chain(n, time_evolve(P, -α * iωʲ)))\n end\n end\n\n real(expect(h, zero_state(n) => circuit))\nend;","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Finally, let's try it out. We initialize the state 0rangle and apply several optimization steps.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"circuit = chain(n)\npauli_strings = generate_2local_pauli_strings(n)\nhistory = Float64[]\n\nfor i=1:100\n cost = step_and_cost!(n, circuit, h, 0.01, pauli_strings)\n push!(history, cost)\nend\n\nPlots.plot(history, legend=false)\nPlots.plot!(1:100, [w[1] for i=1:100])\nxlabel!(\"steps\")\nylabel!(\"energy\")","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"\"Riemannian","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"When we compare the final states achieved with the Riemannian gradient flow optimizer and with the standard VQE we can notice that the former has lower quality. This is because the Riemannian gradient flow optimizer has only a local view of the cost landscape while VQE can access these directions since the ansatz we used is universal. However, if we were able to calculate all of the 4^n - 1 projections, Riemannian gradient flow optimizer would be guaranteed to converge given the appropriate learning rate!","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"This page was generated using Literate.jl.","category":"page"},{"location":"dev/index.html#Developer-Notes","page":"Developer Notes","title":"Developer Notes","text":"","category":"section"},{"location":"dev/index.html#Overview-of-the-Architecture","page":"Developer Notes","title":"Overview of the Architecture","text":"","category":"section"},{"location":"dev/index.html","page":"Developer Notes","title":"Developer Notes","text":"The following is an overview of the entire ecosystem, where Yao and CuYao are two meta-packages.","category":"page"},{"location":"dev/index.html","page":"Developer Notes","title":"Developer Notes","text":"(Image: stack)","category":"page"},{"location":"dev/index.html#The-role-of-QBIR","page":"Developer Notes","title":"The role of QBIR","text":"","category":"section"},{"location":"dev/index.html","page":"Developer Notes","title":"Developer Notes","text":"Currently the main functionality is built on the Quantum Block Intermediate Representation (QBIR). A quantum program is defined by QBIR and then interpreted to different targets, such as different simulation backend or matrix representation.","category":"page"},{"location":"dev/index.html","page":"Developer Notes","title":"Developer Notes","text":"(Image: framework)","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"EditURL = \"../../../examples/7.variation-quantum-eigen-solver/main.jl\"","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"(Image: )","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html#Variational-Quantum-Eigen-Solver","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"","category":"section"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"using Yao, Yao.AD, Yao.EasyBuild","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"number of qubits","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"n = 4","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"4","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"depth","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"d = 5\ncircuit = dispatch!(variational_circuit(n, d),:random)\n\ngatecount(circuit)\n\nnparameters(circuit)\n\nh = heisenberg(n)","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"nqubits: 4\n+\n├─ +\n│ ├─ repeat on (1, 2)\n│ │ └─ X\n│ ├─ repeat on (1, 2)\n│ │ └─ Y\n│ └─ repeat on (1, 2)\n│ └─ Z\n├─ +\n│ ├─ repeat on (2, 3)\n│ │ └─ X\n│ ├─ repeat on (2, 3)\n│ │ └─ Y\n│ └─ repeat on (2, 3)\n│ └─ Z\n├─ +\n│ ├─ repeat on (3, 4)\n│ │ └─ X\n│ ├─ repeat on (3, 4)\n│ │ └─ Y\n│ └─ repeat on (3, 4)\n│ └─ Z\n└─ +\n ├─ repeat on (1, 4)\n │ └─ X\n ├─ repeat on (1, 4)\n │ └─ Y\n └─ repeat on (1, 4)\n └─ Z\n","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"pick the one you like either reverse-mode or forward mode grad = faithfulgrad(h, zerostate(n) => circuit; nshots=100)","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"for i in 1:1000\n _, grad = expect'(h, zero_state(n) => circuit)\n dispatch!(-, circuit, 1e-2 * grad)\n println(\"Step $i, energy = $(real.(expect(h, zero_state(n)=>circuit)))\")\nend\n\nusing LinearAlgebra\nw, _ = eigen(Matrix(mat(h)))","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"LinearAlgebra.Eigen{ComplexF64, Float64, Matrix{ComplexF64}, Vector{Float64}}\nvalues:\n16-element Vector{Float64}:\n -7.9999999999999964\n -4.0\n -3.9999999999999956\n -3.999999999999994\n -7.437659514860159e-32\n -4.426399962566284e-32\n 0.0\n 2.7369110631344083e-48\n 2.003298162163793e-32\n 3.552713678800501e-15\n 4.440892098500626e-15\n 3.9999999999999987\n 3.9999999999999996\n 4.0\n 4.0\n 4.0\nvectors:\n16×16 Matrix{ComplexF64}:\n 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 1.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.559869+0.0im 0.43191+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im 2.22045e-16+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.288675+0.0im 9.56933e-17+0.0im 6.41024e-18+0.0im 0.0+0.0im 0.481733+0.0im -0.624453+0.0im 0.0+0.0im -0.211325+0.0im 1.34897e-17+0.0im 0.0+0.0im -0.288675+0.0im -6.41024e-18+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im -0.559869+0.0im -0.43191+0.0im 0.0+0.0im 0.0+0.0im 2.22045e-16+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n -0.57735+0.0im 0.707107+0.0im -1.30125e-33+0.0im 0.0+0.0im -1.30736e-32+0.0im 0.0+0.0im 0.0+0.0im -8.71576e-33+0.0im 3.06708e-33+0.0im 0.0+0.0im -1.97795e-16+0.0im 1.30125e-33+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.288675+0.0im 9.56933e-17+0.0im -2.39233e-17+0.0im 0.0+0.0im -0.12908+0.0im 0.167322+0.0im 0.0+0.0im 0.788675+0.0im 2.77891e-17+0.0im 0.0+0.0im -0.288675+0.0im 2.39233e-17+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.0+0.0im -4.71028e-16+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im -1.29477e-16+0.0im 6.29876e-17+0.0im 0.0+0.0im 6.06671e-17+0.0im -0.707107+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.288675+0.0im 9.56933e-17+0.0im 1.75131e-17+0.0im 0.0+0.0im -0.352653+0.0im 0.457131+0.0im 0.0+0.0im -0.57735+0.0im -4.12788e-17+0.0im 0.0+0.0im -0.288675+0.0im -1.75131e-17+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n -0.57735+0.0im -0.707107+0.0im 1.30125e-33+0.0im 0.0+0.0im 1.30736e-32+0.0im 0.0+0.0im 0.0+0.0im 8.71576e-33+0.0im -3.06708e-33+0.0im 0.0+0.0im -3.14995e-16+0.0im -1.30125e-33+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.707107+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im\n 0.288675+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.866025+0.0im 0.0+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im -0.707107+0.0im 0.0+0.0im 0.0+0.0im -4.71028e-16+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5-0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 1.0+0.0im","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"EditURL = \"../../../examples/5.shor-9-code/main.jl\"","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"(Image: )","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html#Shor's-9-qubit-code","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"","category":"section"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"The well-known Shor's 9 qubit code can correct any single Pauli error, but it can also correct some other kinds of errors. Its circuit is shown as below (Image: shor-9-circuit) which can be constructed by the following code","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"using Yao\nusing SymEngine\n\nshor(E) = chain(9,\n # encode circuit\n cnot(1, 4), cnot(1, 7),\n put(1=>H), put(4=>H), put(7=>H),\n cnot(1,2), cnot(1,3), cnot(4,5), cnot(4,6), cnot(7,8), cnot(7,9),\n E, # the error\n # decode circuit\n cnot(1,2), cnot(1,3), cnot((2, 3), 1),\n cnot(4,5), cnot(4,6), cnot((5, 6), 4),\n cnot(7,8), cnot(7,9), cnot((8, 9), 7),\n put(1=>H), put(4=>H), put(7=>H), cnot(1, 4), cnot(1, 7), cnot((4, 7), 1)\n)","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"shor (generic function with 1 method)","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"Now we can check whether it can correct a given error by doing symbolic computation on an arbitrary 1-qubit pure quantum state α0 + β1 and a specific weight-9 error.","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"@vars α β\ns = α * ket\"0\" + β * ket\"1\" |> append_qudits!(8)\nE = kron(1=>X, 2=>Z, 3=>Z, 4=>X, 5=>Z, 6=>Z, 7=>X, 8=>Z, 9=>Z);\ns |> shor(E) |> expand","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"α|110110110⟩ + β|110110111⟩","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"This page was generated using Literate.jl.","category":"page"},{"location":"benchmarks.html#Benchmarks","page":"Benchmarks","title":"Benchmarks","text":"","category":"section"},{"location":"benchmarks.html#Benchmark-Guard","page":"Benchmarks","title":"Benchmark Guard","text":"","category":"section"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"To ensure some PR do not contain performance regression, we defined package benchmarks with PkgBenchmark in each component package, you can run the benchmark suite and compare the performance between different version and commits.","category":"page"},{"location":"benchmarks.html#Benchmark-with-Other-Packages","page":"Benchmarks","title":"Benchmark with Other Packages","text":"","category":"section"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"We also provide benchmarks comparing to other packages, you can find a complete benchmark results here: quantum-benchmarks","category":"page"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"a glance of Yao's benchmark comparing to other packages:","category":"page"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"(Image: relative-gate)","category":"page"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"(Image: relative-circuit)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"EditURL = \"../../../examples/1.prepare-ghz-state/main.jl\"","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"(Image: )","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#example-ghz","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"First, you have to use this package in Julia.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"using Yao","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Now, we just define the circuit according to the circuit image below: (Image: ghz)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"circuit = chain(\n 4,\n put(1=>X),\n repeat(H, 2:4),\n control(2, 1=>X),\n control(4, 3=>X),\n control(3, 1=>X),\n control(4, 3=>X),\n repeat(H, 1:4),\n)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nchain\n├─ put on (1)\n│ └─ X\n├─ repeat on (2, 3, 4)\n│ └─ H\n├─ control(2)\n│ └─ (1,) X\n├─ control(4)\n│ └─ (3,) X\n├─ control(3)\n│ └─ (1,) X\n├─ control(4)\n│ └─ (3,) X\n└─ repeat on (1, 2, 3, 4)\n └─ H\n","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Let me explain what happens here.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Put-single-qubit-gate-X-to-location-1","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Put single qubit gate X to location 1","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"we have an X gate applied to the first qubit. We need to tell Yao to put this gate on the first qubit by","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"put(4, 1=>X)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nput on (1)\n└─ X","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"We use Julia's Pair to denote the gate and its location in the circuit, for two-qubit gate, you could also use a tuple of locations:","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"put(4, (1, 2)=>swap(2, 1, 2))","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nput on (1, 2)\n└─ put on (1, 2)\n └─ SWAP\n","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"But, wait, why there's no 4 in the definition above? This is because all the functions in Yao that requires to input the number of qubits as its first arguement could be lazy (curried), and let other constructors to infer the total number of qubits later, e.g","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"put(1=>X)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"(n -> put(n, 1 => X))","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"which will return a lambda that ask for a single arguement n.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"put(1=>X)(4)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nput on (1)\n└─ X","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Apply-the-same-gate-on-different-locations","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Apply the same gate on different locations","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"next we should put Hadmard gates on all locations except the 1st qubits.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"We provide repeat to apply the same block repeatly, repeat can take an iterator of desired locations, and like put, we can also leave the total number of qubits there.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"repeat(H, 2:4)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"(n -> repeat(n, H, 2:4...))","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Define-control-gates","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Define control gates","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"In Yao, we could define controlled gates by feeding a gate to control","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"control(4, 2, 1=>X)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\ncontrol(2)\n└─ (1,) X","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Like many others, you could leave the number of total qubits there, and infer it later.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"control(2, 1=>X)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"(n -> control(n, 2, 1 => X))","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Composite-each-part-together","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Composite each part together","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"This will create a ControlBlock, the concept of block in Yao basically just means quantum operators, since the quantum circuit itself is a quantum operator, we could create a quantum circuit by composite each part of.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Here, we use chain to chain each part together, a chain of quantum operators means to apply each operators one by one in the chain. This will create a ChainBlock.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"circuit = chain(\n 4,\n put(1=>X),\n repeat(H, 2:4),\n control(2, 1=>X),\n control(4, 3=>X),\n control(3, 1=>X),\n control(4, 3=>X),\n repeat(H, 1:4),\n)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nchain\n├─ put on (1)\n│ └─ X\n├─ repeat on (2, 3, 4)\n│ └─ H\n├─ control(2)\n│ └─ (1,) X\n├─ control(4)\n│ └─ (3,) X\n├─ control(3)\n│ └─ (1,) X\n├─ control(4)\n│ └─ (3,) X\n└─ repeat on (1, 2, 3, 4)\n └─ H\n","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"You can check the type of it with typeof","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"typeof(circuit)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ChainBlock{2}","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Construct-GHZ-state-from-00...00","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Construct GHZ state from 00...00","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"For simulation, we provide a builtin register type called ArrayReg, we will use the simulated register in this example.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"First, let's create 0000, you can create it with zero_state","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"zero_state(4)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Or we also provide bit string literals to create arbitrary eigen state","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ArrayReg(bit\"0000\")","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"They will both create a register with Julia's builtin Array as storage.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Feed-Registers-to-Circuits","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Feed Registers to Circuits","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Circuits can be applied to registers with apply!","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"apply!(zero_state(4), circuit)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"or you can use pipe operator |>, when you want to chain several operations together, here we measure the state right after the circuit for 1000 times","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"results = zero_state(4) |> circuit |> r->measure(r, nshots=1000)\n\nusing StatsBase, Plots\n\nhist = fit(Histogram, Int.(results), 0:16)\nbar(hist.edges[1] .- 0.5, hist.weights, legend=:none)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"GHZ state will collapse to 0000 or 1111.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"This page was generated using Literate.jl.","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"CurrentModule = Yao","category":"page"},{"location":"man/cuda.html#CUDA-extension-CuYao","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"","category":"section"},{"location":"man/cuda.html#Tutorial","page":"CUDA extension - CuYao","title":"Tutorial","text":"","category":"section"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"CuYao is a CUDA extension of Yao, which allows you to run Yao circuits on GPU. The usage of CuYao is similar to Yao, but with some extra APIs to upload and download registers between CPU and GPU:","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"cu(reg) to upload a registe reg to GPU, and\ncpu(cureg) to download a register cureg from GPU to CPU.","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"julia> using Yao, CUDA\n\n# create a register on GPU\njulia> cureg = rand_state(9; nbatch=1000) |> cu; # or `curand_state(9; nbatch=1000)`.\n\n# run a circuit on GPU\njulia> cureg |> put(9, 2=>Z);\n\n# measure the register on GPU\njulia> measure!(cureg)\n1000-element CuArray{DitStr{2, 9, Int64}, 1, CUDA.Mem.DeviceBuffer}:\n 110110100 ₍₂₎\n 000100001 ₍₂₎\n 111111001 ₍₂₎\n ⋮\n 010001101 ₍₂₎\n 000100110 ₍₂₎\n\n# download the register to CPU\njulia> reg = cureg |> cpu;","category":"page"},{"location":"man/cuda.html#Features","page":"CUDA extension - CuYao","title":"Features","text":"","category":"section"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"Supported gates:","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"general U(N) gate\ngeneral U(1) gate\nX, Y, Z gate\nT, S gate\nSWAP gate\ncontrol gates","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"Supported register operations:","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"measure!, measurereset!, measureremove!, select\nappendqudits!, appendqubits!\ninsertqudit!, insertqubits!\nfocus!, relax!\njoin\ndensity_matrix\nfidelity\nexpect","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"Autodiff:","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"autodiff is supported when the only parameterized gates are rotation gates in a circuit.","category":"page"},{"location":"man/cuda.html#API","page":"CUDA extension - CuYao","title":"API","text":"","category":"section"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"cpu\ncurand_state\ncuzero_state\ncuproduct_state\ncuuniform_state\ncughz_state","category":"page"},{"location":"man/cuda.html#Yao.cpu","page":"CUDA extension - CuYao","title":"Yao.cpu","text":"cpu(cureg)\n\nDownload the register state from GPU to CPU.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.curand_state","page":"CUDA extension - CuYao","title":"Yao.curand_state","text":"curand_state([T=ComplexF64], n::Int; nbatch=1)\n\nThe GPU version of rand_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.cuzero_state","page":"CUDA extension - CuYao","title":"Yao.cuzero_state","text":"cuzero_state([T=ComplexF64], n::Int; nbatch=1)\n\nThe GPU version of zero_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.cuproduct_state","page":"CUDA extension - CuYao","title":"Yao.cuproduct_state","text":"cuproduct_state([T=ComplexF64], total::Int, bit_config::Integer; nbatch=NoBatch())\n\nThe GPU version of product_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.cuuniform_state","page":"CUDA extension - CuYao","title":"Yao.cuuniform_state","text":"cuuniform_state([T=ComplexF64], n::Int; nbatch=1)\n\nThe GPU version of uniform_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.cughz_state","page":"CUDA extension - CuYao","title":"Yao.cughz_state","text":"cughz_state([T=ComplexF64], n::Int; nbatch=1)\n\nThe GPU version of ghz_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"note: Note\nthe cu function is not documented in this module, but it is used to upload a register to GPU.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"EditURL = \"../../../examples/3.grover-search/main.jl\"","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"(Image: )","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Grover","page":"Grover Search","title":"Grover Search","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"using Yao\nusing Yao.EasyBuild: variational_circuit\nusing LinearAlgebra","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Grover-Step","page":"Grover Search","title":"Grover Step","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"A single grover step is consist of applying oracle circuit and reflection circuit. The reflection_circuit function takes the wave function generator U as the input and returns U|0><0|U'.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"function grover_step!(reg::AbstractRegister, oracle, U::AbstractBlock)\n apply!(reg |> oracle, reflect_circuit(U))\nend\n\nfunction reflect_circuit(gen::AbstractBlock)\n N = nqubits(gen)\n reflect0 = control(N, -collect(1:N-1), N=>-Z)\n chain(gen', reflect0, gen)\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"reflect_circuit (generic function with 1 method)","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"Compute the propotion of target states to estimate the number of iterations, which requires computing the output state.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"function solution_state(oracle, gen::AbstractBlock)\n N = nqubits(gen)\n reg= zero_state(N) |> gen\n reg.state[real.(statevec(ArrayReg(ones(ComplexF64, 1< oracle)) .> 0] .= 0\n normalize!(reg)\nend\n\nfunction num_grover_step(oracle, gen::AbstractBlock)\n N = nqubits(gen)\n reg = zero_state(N) |> gen\n ratio = abs2(solution_state(oracle, gen)'*reg)\n Int(round(pi/4/sqrt(ratio)))-1\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"num_grover_step (generic function with 1 method)","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Run","page":"Grover Search","title":"Run","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"First, we define the problem by an oracle, it finds bit string bit\"000001100100\".","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"num_bit = 12\noracle = matblock(Diagonal((v = ones(ComplexF64, 1< gen\n\ntarget_state = solution_state(oracle, gen)\n\nfor i = 1:num_grover_step(oracle, gen)\n grover_step!(reg, oracle, gen)\n overlap = abs(reg'*target_state)\n println(\"step $(i-1), overlap = $overlap\")\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"step 0, overlap = 0.04685974121093736\nstep 1, overlap = 0.0780487209558483\nstep 2, overlap = 0.10916148124670066\nstep 3, overlap = 0.14016763852852288\nstep 4, overlap = 0.17103691335084453\nstep 5, overlap = 0.20173915993747182\nstep 6, overlap = 0.23224439562572258\nstep 7, overlap = 0.26252283014636996\nstep 8, overlap = 0.29254489471570244\nstep 9, overlap = 0.322281270911289\nstep 10, overlap = 0.35170291930325104\nstep 11, overlap = 0.3807811078130809\nstep 12, overlap = 0.40948743977231195\nstep 13, overlap = 0.4377938816536402\nstep 14, overlap = 0.46567279044741594\nstep 15, overlap = 0.49309694065677034\nstep 16, overlap = 0.5200395508850146\nstep 17, overlap = 0.5464743099893477\nstep 18, overlap = 0.5723754027753314\nstep 19, overlap = 0.5977175352070423\nstep 20, overlap = 0.6224759591082774\nstep 21, overlap = 0.6466264963306958\nstep 22, overlap = 0.6701455623652912\nstep 23, overlap = 0.6930101893741392\nstep 24, overlap = 0.7151980486199263\nstep 25, overlap = 0.7366874722713579\nstep 26, overlap = 0.7574574745631494\nstep 27, overlap = 0.7774877722899375\nstep 28, overlap = 0.7967588046140988\nstep 29, overlap = 0.8152517521681291\nstep 30, overlap = 0.8329485554329328\nstep 31, overlap = 0.8498319323740713\nstep 32, overlap = 0.8658853953187506\nstep 33, overlap = 0.8810932670570639\nstep 34, overlap = 0.8954406961517668\nstep 35, overlap = 0.9089136714416339\nstep 36, overlap = 0.9214990357242339\nstep 37, overlap = 0.9331844986047592\nstep 38, overlap = 0.9439586484983656\nstep 39, overlap = 0.953810963774298\nstep 40, overlap = 0.9627318230309194\nstep 41, overlap = 0.9707125144916121\nstep 42, overlap = 0.9777452445123718\nstep 43, overlap = 0.983823145192787\nstep 44, overlap = 0.9889402810829753\nstep 45, overlap = 0.9930916549799182\nstep 46, overlap = 0.9962732128075449\nstep 47, overlap = 0.9984818475757891\nstep 48, overlap = 0.9997154024147601\n","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Rejection-Sampling","page":"Grover Search","title":"Rejection Sampling","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"In practise, it is often not possible to determine the number of iterations before actual running. we can use rejection sampling technique to avoid estimating the number of grover steps.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"In a single try, we apply the grover algorithm for nstep times.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"function single_try(oracle, gen::AbstractBlock, nstep::Int; nbatch::Int)\n N = nqubits(gen)\n reg = zero_state(N+1; nbatch)\n focus(reg, (1:N...,)) do r\n r |> gen\n for i = 1:nstep\n grover_step!(r, oracle, gen)\n end\n return r\n end\n reg |> checker\n res = measure!(RemoveMeasured(), reg, (N+1))\n return res, reg\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"single_try (generic function with 1 method)","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"After running the grover search, we have a checker program that flips the ancilla qubit if the output is the desired value, we assume the checker program can be implemented in polynomial time. to gaurante the output is correct. We contruct a checker \"program\", if the result is correct, flip the ancilla qubit","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"ctrl = -collect(1:num_bit); ctrl[[3,6,7]] *= -1\nchecker = control(num_bit+1,ctrl, num_bit+1=>X)","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"nqubits: 13\ncontrol(¬1, ¬2, 3, ¬4, ¬5, 6, 7, ¬8, ¬9, ¬10, ¬11, ¬12)\n└─ (13,) X","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"The register is batched, with batch dimension nshot. focus! views the first 1-N qubts as system. For a batched register, measure! returns a vector of bitstring as output.","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Run-2","page":"Grover Search","title":"Run","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"maxtry = 100\nnshot = 3\n\nfor nstep = 0:maxtry\n println(\"number of iter = $nstep\")\n res, regi = single_try(oracle, gen, nstep; nbatch=3)\n\n # success!\n if any(==(1), res)\n overlap_final = viewbatch(regi, findfirst(==(1), res))'*target_state\n println(\"success, overlap = $(overlap_final)\")\n break\n end\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"number of iter = 0\nnumber of iter = 1\nnumber of iter = 2\nnumber of iter = 3\nnumber of iter = 4\nnumber of iter = 5\nnumber of iter = 6\nnumber of iter = 7\nnumber of iter = 8\nnumber of iter = 9\nnumber of iter = 10\nsuccess, overlap = 1.0 + 0.0im\n","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"The final state has an overlap of 1 with the target state.","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Amplitude-Amplification","page":"Grover Search","title":"Amplitude Amplification","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"Given a circuit to generate a state, now we want to project out the subspace with [1,3,5,8,9,11,12] fixed to 1 and [4,6] fixed to 0. We can construct an oracle","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"evidense = [1, 3, -4, 5, -6, 8, 9, 11, 12]\nfunction inference_oracle(nbit::Int, locs::Vector{Int})\n control(nbit, locs[1:end-1], abs(locs[end]) => (locs[end]>0 ? Z : -Z))\nend\noracle = inference_oracle(nqubits(reg), evidense)","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"nqubits: 12\ncontrol(1, 3, ¬4, 5, ¬6, 8, 9, 11)\n└─ (12,) Z","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"We use a variational circuit generator defined in Yao.EasyBuild","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"gen = dispatch!(variational_circuit(num_bit), :random)\nreg = zero_state(num_bit) |> gen","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 12/12\n nlevel: 2","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Run-3","page":"Grover Search","title":"Run","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"solution = solution_state(oracle, gen)\nfor i = 1:num_grover_step(oracle, gen)\n grover_step!(reg, oracle, gen)\n println(\"step $(i-1), overlap = $(abs(reg'*solution))\")\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"step 0, overlap = 0.11457856932749395\nstep 1, overlap = 0.19021840433085546\nstep 2, overlap = 0.2647440104263067\nstep 3, overlap = 0.3377188442363379\nstep 4, overlap = 0.408715446232692\nstep 5, overlap = 0.47731794463584265\nstep 6, overlap = 0.543124491437735\nstep 7, overlap = 0.6057496162784728\nstep 8, overlap = 0.6648264843888095\nstep 9, overlap = 0.7200090453722614\nstep 10, overlap = 0.7709740602400635\nstep 11, overlap = 0.817422994825359\nstep 12, overlap = 0.859083768485696\nstep 13, overlap = 0.8957123478505835\nstep 14, overlap = 0.9270941762785245\nstep 15, overlap = 0.9530454306502978\nstep 16, overlap = 0.9734140981366541\nstep 17, overlap = 0.9880808666331276\nstep 18, overlap = 0.9969598236461193\nstep 19, overlap = 0.9999989595364428\n","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"This page was generated using Literate.jl.","category":"page"},{"location":"man/automatic_differentiation.html#Automatic-Differentiation","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"","category":"section"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"Yao currently contains builtin automatic differentiation engine (an operator overloading based) especially for quantum circuits. It uses the reversible context of quantum computation to optimize the performance during simulation, thus you may find this is way faster than any other AD engine at the moment.","category":"page"},{"location":"man/automatic_differentiation.html#Builtin-Reverse-mode-AD-engine-for-simulation","page":"Automatic Differentiation","title":"Builtin Reverse mode AD engine for simulation","text":"","category":"section"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"As for expectation, the usage is pretty simple, since the evluation of expectations are just","category":"page"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"expect(H, rand_state(10)=>circuit)","category":"page"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"to get the gradients, simply add an adjoint","category":"page"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"expect'(H, rand_state(10)=>circuit)","category":"page"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"which will return the pair of gradients, one is the gradient of input register and the other is the gradient of circuit parameters.","category":"page"},{"location":"man/automatic_differentiation.html#Integration-with-General-purpose-AD-engine","page":"Automatic Differentiation","title":"Integration with General purpose AD engine","text":"","category":"section"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"The builtin AD engine for Yao only provides the differentiation of quantum circuits, but you can plug it into a general AD engine, such as Zygote, since we have ported these rules to ChainRules.","category":"page"},{"location":"man/automatic_differentiation.html#APIs","page":"Automatic Differentiation","title":"APIs","text":"","category":"section"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"Modules = [YaoBlocks.AD]\nOrder = [:function, :macro]","category":"page"},{"location":"man/automatic_differentiation.html#YaoBlocks.AD.apply_back-Tuple{Tuple{AbstractArrayReg, AbstractArrayReg}, AbstractBlock}","page":"Automatic Differentiation","title":"YaoBlocks.AD.apply_back","text":"apply_back(st::Tuple{<:AbstractArrayReg, <:AbstractArrayReg}, block::AbstractBlock; kwargs...) -> (out, outδ), paramsδ\n\nThe backward function of apply!. Returns a tuple of ((input register, gradient of input register), parameter gradients)\n\n\n\n\n\n","category":"method"},{"location":"man/automatic_differentiation.html#YaoBlocks.AD.generator-Tuple{RotationGate}","page":"Automatic Differentiation","title":"YaoBlocks.AD.generator","text":"generator(rot::Rotor) -> AbstractBlock\n\nReturn the generator of rotation block.\n\n\n\n\n\n","category":"method"},{"location":"man/automatic_differentiation.html#YaoBlocks.AD.mat_back-Union{Tuple{T}, Tuple{AbstractBlock, AbstractMatrix{T}}} where T","page":"Automatic Differentiation","title":"YaoBlocks.AD.mat_back","text":"mat_back([::Type{T}, ]block::AbstractBlock, adjm::AbstractMatrix) -> Vector\n\nThe backward function of mat. Returns the gradients of parameters.\n\n\n\n\n\n","category":"method"},{"location":"man/automatic_differentiation.html#YaoBlocks.AD.rotgrad-Union{Tuple{T}, Tuple{D}, Tuple{Type{T}, RotationGate{D, T, GT} where {T, GT<:AbstractBlock{D}}}} where {D, T}","page":"Automatic Differentiation","title":"YaoBlocks.AD.rotgrad","text":"The matrix gradient of a rotation block.\n\n\n\n\n\n","category":"method"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"EditURL = \"../../../examples/6.quantum-circuit-born-machine/main.jl\"","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"(Image: )","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#qcbm","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Yao is designed with variational quantum circuits in mind, and this tutorial will introduce how to use Yao for this kind of task by implementing a quantum circuit born machine described in Jin-Guo Liu, Lei Wang (2018)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"let's use the packages first","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"using Yao, LinearAlgebra, Plots","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Training-Target","page":"Quantum Circuit Born Machine","title":"Training Target","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"In this tutorial, we will ask the variational circuit to learn the most basic distribution: a guassian distribution. It is defined as follows:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"f(x left mu sigma^2right) = frac1sqrt2pisigma^2 e^-frac(x-mu)^22sigma^2","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We implement it as gaussian_pdf:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"function gaussian_pdf(x, μ::Real, σ::Real)\n pl = @. 1 / sqrt(2pi * σ^2) * exp(-(x - μ)^2 / (2 * σ^2))\n pl / sum(pl)\nend\npg = gaussian_pdf(1:1<<6, 1<<5-0.5, 1<<4);","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We can plot the distribution, it looks like","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Plots.plot(pg)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Create-the-Circuit","page":"Quantum Circuit Born Machine","title":"Create the Circuit","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"A quantum circuit born machine looks like the following:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"(Image: differentiable ciruit)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"It is composited by two different layers: rotation layer and entangler layer.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Rotation-Layer","page":"Quantum Circuit Born Machine","title":"Rotation Layer","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Arbitrary rotation is built with Rotation Gate on Z, X, Z axis with parameters.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Rz(theta) cdot Rx(theta) cdot Rz(theta)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Since our input will be a 0dots 0rangle state. The first layer of arbitrary rotation can just use Rx(theta) cdot Rz(theta) and the last layer of arbitrary rotation could just use Rz(theta)cdot Rx(theta)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"In 幺, every Hilbert operator is a block type, this ncludes all quantum gates and quantum oracles. In general, operators appears in a quantum circuit can be divided into Composite Blocks and Primitive Blocks.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We follow the low abstraction principle and thus each block represents a certain approach of calculation. The simplest Composite Block is a Chain Block, which chains other blocks (oracles) with the same number of qubits together. It is just a simple mathematical composition of operators with same size. e.g.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"textchain(X Y Z) iff X cdot Y cdot Z","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We can construct an arbitrary rotation block by chain Rz, Rx, Rz together.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"chain(Rz(0.0), Rx(0.0), Rz(0.0))","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"nqubits: 1\nchain\n├─ rot(Z, 0.0)\n├─ rot(X, 0.0)\n└─ rot(Z, 0.0)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Rx, Rz will construct new rotation gate, which are just shorthands for rot(X, 0.0), etc.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Then let's chain them up","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"layer(nbit::Int, x::Symbol) = layer(nbit, Val(x))\nlayer(nbit::Int, ::Val{:first}) = chain(nbit, put(i=>chain(Rx(0), Rz(0))) for i = 1:nbit);","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We do not need to feed the first n parameter into put here. All factory methods can be lazy evaluate the first arguements, which is the number of qubits. It will return a lambda function that requires a single interger input. The instance of desired block will only be constructed until all the information is filled. When you filled all the information in somewhere of the declaration, 幺 will be able to infer the others. We will now define the rest of rotation layers","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"layer(nbit::Int, ::Val{:last}) = chain(nbit, put(i=>chain(Rz(0), Rx(0))) for i = 1:nbit)\nlayer(nbit::Int, ::Val{:mid}) = chain(nbit, put(i=>chain(Rz(0), Rx(0), Rz(0))) for i = 1:nbit);","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Entangler","page":"Quantum Circuit Born Machine","title":"Entangler","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Another component of quantum circuit born machine are several CNOT operators applied on different qubits.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"entangler(pairs) = chain(control(ctrl, target=>X) for (ctrl, target) in pairs);","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We can then define such a born machine","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"function build_circuit(n, nlayers, pairs)\n circuit = chain(n)\n push!(circuit, layer(n, :first))\n for i in 2:nlayers\n push!(circuit, cache(entangler(pairs)))\n push!(circuit, layer(n, :mid))\n end\n push!(circuit, cache(entangler(pairs)))\n push!(circuit, layer(n, :last))\n return circuit\nend","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"build_circuit (generic function with 1 method)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We use the method cache here to tag the entangler block that it should be cached after its first run, because it is actually a constant oracle. Let's see what will be constructed","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"build_circuit(4, 1, [1=>2, 2=>3, 3=>4])","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"nqubits: 4\nchain\n├─ chain\n│ ├─ put on (1)\n│ │ └─ chain\n│ │ ├─ rot(X, 0.0)\n│ │ └─ rot(Z, 0.0)\n│ ├─ put on (2)\n│ │ └─ chain\n│ │ ├─ rot(X, 0.0)\n│ │ └─ rot(Z, 0.0)\n│ ├─ put on (3)\n│ │ └─ chain\n│ │ ├─ rot(X, 0.0)\n│ │ └─ rot(Z, 0.0)\n│ └─ put on (4)\n│ └─ chain\n│ ├─ rot(X, 0.0)\n│ └─ rot(Z, 0.0)\n├─ [cached] chain\n│ ├─ control(1)\n│ │ └─ (2,) X\n│ ├─ control(2)\n│ │ └─ (3,) X\n│ └─ control(3)\n│ └─ (4,) X\n└─ chain\n ├─ put on (1)\n │ └─ chain\n │ ├─ rot(Z, 0.0)\n │ └─ rot(X, 0.0)\n ├─ put on (2)\n │ └─ chain\n │ ├─ rot(Z, 0.0)\n │ └─ rot(X, 0.0)\n ├─ put on (3)\n │ └─ chain\n │ ├─ rot(Z, 0.0)\n │ └─ rot(X, 0.0)\n └─ put on (4)\n └─ chain\n ├─ rot(Z, 0.0)\n └─ rot(X, 0.0)\n","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#MMD-Loss-and-Gradients","page":"Quantum Circuit Born Machine","title":"MMD Loss & Gradients","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"The MMD loss is describe below:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"beginaligned\nmathcalL = left sum_x p theta(x) phi(x) - sum_x pi(x) phi(x) right^2\n = langle K(x y) rangle_x sim p_theta ysim p_theta - 2 langle K(x y) rangle_xsim p_theta ysim pi + langle K(x y) rangle_xsimpi ysimpi\nendaligned","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We will use a squared exponential kernel here.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"struct RBFKernel\n σ::Float64\n m::Matrix{Float64}\nend\n\nfunction RBFKernel(σ::Float64, space)\n dx2 = (space .- space').^2\n return RBFKernel(σ, exp.(-1/2σ * dx2))\nend\n\nkexpect(κ::RBFKernel, x, y) = x' * κ.m * y","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"kexpect (generic function with 1 method)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"There are two different way to define the loss:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"In simulation we can use the probability distribution of the state directly","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"get_prob(qcbm) = probs(zero_state(nqubits(qcbm)) |> qcbm)\n\nfunction loss(κ, c, target)\n p = get_prob(c) - target\n return kexpect(κ, p, p)\nend","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"loss (generic function with 1 method)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Or if you want to simulate the whole process with measurement (which is entirely physical), you should define the loss with measurement results, for convenience we directly use the simulated results as our loss","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Gradients","page":"Quantum Circuit Born Machine","title":"Gradients","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"the gradient of MMD loss is","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"beginaligned\nfracpartial mathcalLpartial theta^i_l = langle K(x y) rangle_xsim p_theta^+ ysim p_theta - langle K(x y) rangle_xsim p_theta^- ysim p_theta\n- langle K(x y) rangle _xsim p_theta^+ ysimpi + langle K(x y) rangle_xsim p_theta^- ysimpi\nendaligned","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"which can be implemented as","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"function gradient(qcbm, κ, ptrain)\n n = nqubits(qcbm)\n prob = get_prob(qcbm)\n grad = zeros(Float64, nparameters(qcbm))\n\n count = 1\n for k in 1:2:length(qcbm), each_line in qcbm[k], gate in content(each_line)\n dispatch!(+, gate, π/2)\n prob_pos = probs(zero_state(n) |> qcbm)\n\n dispatch!(-, gate, π)\n prob_neg = probs(zero_state(n) |> qcbm)\n\n dispatch!(+, gate, π/2) # set back\n\n grad_pos = kexpect(κ, prob, prob_pos) - kexpect(κ, prob, prob_neg)\n grad_neg = kexpect(κ, ptrain, prob_pos) - kexpect(κ, ptrain, prob_neg)\n grad[count] = grad_pos - grad_neg\n count += 1\n end\n return grad\nend","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"gradient (generic function with 1 method)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Now let's setup the training","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"import Optimisers\nqcbm = build_circuit(6, 10, [1=>2, 3=>4, 5=>6, 2=>3, 4=>5, 6=>1])\ndispatch!(qcbm, :random) # initialize the parameters\n\nκ = RBFKernel(0.25, 0:2^6-1)\npg = gaussian_pdf(1:1<<6, 1<<5-0.5, 1<<4);\nopt = Optimisers.setup(Optimisers.ADAM(0.01), parameters(qcbm));\n\nfunction train(qcbm, κ, opt, target)\n history = Float64[]\n for _ in 1:100\n push!(history, loss(κ, qcbm, target))\n ps = parameters(qcbm)\n Optimisers.update!(opt, ps, gradient(qcbm, κ, target))\n dispatch!(qcbm, ps)\n end\n return history\nend\n\nhistory = train(qcbm, κ, opt, pg)\ntrained_pg = probs(zero_state(nqubits(qcbm)) |> qcbm)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"64-element Vector{Float64}:\n 0.004133486523101152\n 0.004841758195470542\n 0.0053638198800351165\n 0.006014067209381298\n 0.006577475953851315\n 0.007340590841432222\n 0.007987709345414127\n 0.009017039314901651\n 0.009645340650396284\n 0.010435751908475167\n 0.011647409377713726\n 0.01234765457502382\n 0.013336669977445042\n 0.014496200812926885\n 0.015452937863625204\n 0.016292488172597357\n 0.01740118188567342\n 0.018234802654645856\n 0.019294135340699466\n 0.020094759064642604\n 0.021122612861327484\n 0.02180597955896689\n 0.02275092787008356\n 0.0235220107001656\n 0.024084383489436055\n 0.024627480682834234\n 0.02516504040700968\n 0.025344694045761448\n 0.02583276823274501\n 0.026160935182472235\n 0.02618172063179388\n 0.02604922109724038\n 0.025985431670209357\n 0.02580315288488768\n 0.02552154780137255\n 0.025153477382960497\n 0.024554110325239527\n 0.023948712361655324\n 0.02341735029755776\n 0.022662641242418135\n 0.021884914051207897\n 0.021071310646725787\n 0.020227089865122772\n 0.01929684901543418\n 0.018289729491622553\n 0.017302671908413825\n 0.016438647016922305\n 0.015377155726144263\n 0.01437055843498409\n 0.013359817682805902\n 0.01246175003383155\n 0.011442304670168494\n 0.010721036557505368\n 0.009607224243172417\n 0.008870469764915647\n 0.008073664088723587\n 0.007367475157463305\n 0.00660278960091021\n 0.006039481228193021\n 0.005422775746160495\n 0.0046450367009025105\n 0.004197972807648939\n 0.00388346230413649\n 0.003396334983295141","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"The history of training looks like below","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"title!(\"training history\")\nxlabel!(\"steps\"); ylabel!(\"loss\")\nPlots.plot(history)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"And let's check what we got","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"fig2 = Plots.plot(1:1<<6, trained_pg; label=\"trained\")\nPlots.plot!(fig2, 1:1<<6, pg; label=\"target\")\ntitle!(\"distribution\")\nxlabel!(\"x\"); ylabel!(\"p\")","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"So within 50 steps, we got a pretty close estimation of our target distribution!","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"This page was generated using Literate.jl.","category":"page"},{"location":"quick-start.html#Quick-Start","page":"Quick Start","title":"Quick Start","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"In this quick start, we list several common use cases for Yao before you go deeper into the manual.","category":"page"},{"location":"quick-start.html#Create-a-quantum-register/state","page":"Quick Start","title":"Create a quantum register/state","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"A register is an object that describes a device with an internal state. See Registers for more details. Yao use registers to represent quantum states. The most common register is the ArrayReg, you can create it by feeding a state vector to it, e.g","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"using Yao\nArrayReg(randn(ComplexF64, 2^3)) # a random unnormalized 3-qubit state\nzero_state(5) # |00000⟩\nrand_state(5) # a random state\nproduct_state(bit\"10100\") # |10100⟩\nghz_state(5) # (|00000⟩ + |11111⟩)/√2","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"the internal quantum state can be accessed via statevec method","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"statevec(ghz_state(2))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"for more functionalities about registers please refer to the manual of Registers.","category":"page"},{"location":"quick-start.html#Create-quantum-circuit","page":"Quick Start","title":"Create quantum circuit","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"Yao introduces an abstract representation for linear maps, called \"block\"s, which can be used to represent quantum circuits, Hamiltonians, and other quantum operations. The following code creates a 2-qubit circuit","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"chain(2, put(1=>H), put(2=>X))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"where H gate is at 1st qubit, X gate is at 2nd qubit. A more advanced example is the quantum Fourier transform circuit","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1)))) # a cphase gate\nB(n, k) = chain(n, j==k ? put(k=>H) : A(j, k) for j in k:n)\nqft(n) = chain(B(n, k) for k in 1:n)\ncircuit = qft(3) # a 3-qubit QFT circuit\nmat(circuit) # the matrix representation of the circuit\napply!(zero_state(3), circuit) # apply the circuit to a zero state","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"More details about available blocks can be found in the manual of Blocks.","category":"page"},{"location":"quick-start.html#Create-Hamiltonian","page":"Quick Start","title":"Create Hamiltonian","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"We can create a simple Ising Hamiltonian on 1D chain as following","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"h = sum([kron(5, i=>Z, mod1(i+1, 5)=>Z) for i in 1:5]) # a 5-qubit Ising Hamiltonian\nmat(h) # the matrix representation of the Hamiltonian","category":"page"},{"location":"quick-start.html#Differentiating-a-quantum-circuit","page":"Quick Start","title":"Differentiating a quantum circuit","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"Yao has its own automatic differentiation rule implemented, this allows one obtain gradients of a loss function by simply putting a ' mark following expect or fidelity, e.g","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"To obtain the gradient of the quantum Fourier transform circuit with respect to its parameters, one can use the following code","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"grad_state, grad_circuit_params = expect'(kron(X, X, I2) + kron(I2, X, X), zero_state(3)=>qft(3))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"where kron(X, X, I2) + kron(I2, X, X) is the target Hamiltonian, zero_state(3) is the initial state, qft(3) is the quantum Fourier transform circuit. The return value is a vector, each corresponding to the gradient of the loss function with respect to a parameter in the circuit. The list of parameters can be obtained by parameters function.","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"parameters(qft(3))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"To obtain the gradient of the fidelity between a state parameterized by a quantum circuit and a target state, one can use the following code","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"((grad_state1, grad_circuit1), grad_state2) = fidelity'(zero_state(3)=>qft(3), ghz_state(3))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"where zero_state(3) is the initial state, qft(3) is the quantum Fourier transform circuit, ghz_state(3) is the target state.","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"The automatic differentiation functionality can also be accessed by interfacing with the machine learning libraries Zygote.","category":"page"},{"location":"quick-start.html#Plot-quantum-circuits","page":"Quick Start","title":"Plot quantum circuits","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"The component package YaoPlots provides plotting for quantum circuits and ZX diagrams. You can use it to visualize your quantum circuits in VSCode, Jupyter notebook or Pluto notebook.","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"using Yao.EasyBuild, Yao.YaoPlots\nusing Compose\n\n# show a qft circuit\nvizcircuit(qft_circuit(5))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"More details about the plotting can be found in the manual: Quantum Circuit Visualization.","category":"page"},{"location":"notes.html#How-to-overload-exist-method-for-a-block","page":"How to overload exist method for a block","title":"How to overload exist method for a block","text":"","category":"section"},{"location":"notes.html","page":"How to overload exist method for a block","title":"How to overload exist method for a block","text":"every block has two method: mat & apply!, overload mat to define how to gather this block's matrix form, overload apply! to define how to apply this block to a register.","category":"page"},{"location":"notes.html","page":"How to overload exist method for a block","title":"How to overload exist method for a block","text":"Prototypes:","category":"page"},{"location":"notes.html","page":"How to overload exist method for a block","title":"How to overload exist method for a block","text":"apply!(reg, block)\nmat(block)","category":"page"},{"location":"performancetips.html#Performance-Tips","page":"Performance Tips","title":"Performance Tips","text":"","category":"section"},{"location":"performancetips.html#Use-the-correct-block-types","page":"Performance Tips","title":"Use the correct block types","text":"","category":"section"},{"location":"performancetips.html#put-v.s.-subroutine","page":"Performance Tips","title":"put v.s. subroutine","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"While both blocks maps a subblock to a subset of qudits, their implementations are purposes are quite different. The put block applies the gate in a in-place manner, which requires the static matrix representation of its subblock. It works the best when the subblock is small.","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"The subroutine block is for running a sub-program in a subset of qubits. It first sets target qubits as active qubits using the focus! function, then apply the gates on active qubits. Finally, it unsets the active qubits with the relax! function.","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"julia> using Yao\n\njulia> reg = rand_state(20);\n\njulia> @time apply(reg, put(20, 1:6=>EasyBuild.qft_circuit(6))); # second run\n 0.070245 seconds (1.32 k allocations: 16.525 MiB)\n\njulia> @time apply(reg, subroutine(20, EasyBuild.qft_circuit(6), 1:6)); # second run\n 0.036840 seconds (1.07 k allocations: 16.072 MiB)","category":"page"},{"location":"performancetips.html#repeat-v.s.-put","page":"Performance Tips","title":"repeat v.s. put","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"repeat block is not only an alias of a chain of put, sometimes it can provide speed ups due to the different implementations.","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"julia> reg = rand_state(20);\n\njulia> @time apply!(reg, repeat(20, X));\n 0.002252 seconds (5 allocations: 656 bytes)\n\njulia> @time apply!(reg, chain([put(20, i=>X) for i=1:20]));\n 0.049362 seconds (82.48 k allocations: 4.694 MiB, 47.11% compilation time)","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"Other gates accelerated by repeat include: X, Y, Z, S, T, Sdag, and Tdag.","category":"page"},{"location":"performancetips.html#Diagonal-matrix-in-time_evole","page":"Performance Tips","title":"Diagonal matrix in time_evole","text":"","category":"section"},{"location":"performancetips.html#Register-storage","page":"Performance Tips","title":"Register storage","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"One can use transposed storage and normal storage for computing batched registers. The transposed storage is used by default because it is often faster in practice. One can use transpose_storage to convert the storage.","category":"page"},{"location":"performancetips.html#Multithreading","page":"Performance Tips","title":"Multithreading","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"Multithreading can be switched on by starting Julia in with a global environment variable JULIA_NUM_THREAD","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"$ JULIA_NUM_THREAD=4 julia xxx.jl","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"Check the Julia Multi-Treading manual for details.","category":"page"},{"location":"performancetips.html#GPU-backend","page":"Performance Tips","title":"GPU backend","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"The GPU backend is supported in CuYao.","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"julia> using Yao, CuYao\n\njulia> reg = CuYao.cu(rand_state(20));\n\njulia> circ = Yao.EasyBuild.qft_circuit(20);\n\njulia> apply!(reg, circ)\nArrayReg{2, ComplexF64, CuArray...}\n active qubits: 20/20\n nlevel: 2","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"CurrentModule = YaoArrayRegister\nDocTestSetup = quote\n using Yao\n using BitBasis\n using YaoAPI\n using YaoBlocks\n using YaoArrayRegister\nend","category":"page"},{"location":"man/registers.html#registers","page":"Quantum Registers","title":"Quantum Registers","text":"","category":"section"},{"location":"man/registers.html#Constructing-quantum-states","page":"Quantum Registers","title":"Constructing quantum states","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"A quantum register is a quantum state or a batch of quantum states. Qubits in a Yao register can be active or inactive. Only active qubits are visible to quantum operators, which enables applying quantum operators on a subset of qubits. For example, Suppose we want to run a quantum Fourier transformation circuit of size 4 on qubits (1, 3, 5, 7) with the focus! function, we first set these qubits to active qubits the rest to inactive, then we apply the circuit on the active qubits, and finally we switch back to the original configuration with the relax! function.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"Yao provides two types of quantum registers ArrayReg and BatchedArrayReg. Both use matrices as the storage. For example, for a quantum register with a active qubits, r remaining qubits and batch size b, the storage is as follows.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"(Image: )","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The first dimension of size 2^a is for active qubits, only this subset of qubits are allowed to interact with quantum operators. Since we reshaped the state vector into a matrix, applying a quantum operator can be conceptually represented as a matrix-matrix multiplication.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"Various quantum states can be created with the following functions.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"using Yao\nreg = ArrayReg([0, 1, -1+0.0im, 0]) # a unnormalized Bell state |01⟩ - |10⟩\nstatevec(reg) # a quantum state is represented as a vector\nprint_table(reg)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_zero = zero_state(3) # create a zero state |000⟩\nprint_table(reg_zero)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_rand = rand_state(ComplexF32, 3) # a random state","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_uniform = uniform_state(ComplexF32, 3) # a uniform state\nprint_table(reg_uniform)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_prod = product_state(bit\"110\") # a product state\nbit\"110\"[3] # the bit string is in little-endian format\nprint_table(reg_prod)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_ghz = ghz_state(3) # a GHZ state\nprint_table(reg_ghz)\nvon_neumann_entropy(reg_ghz, (1, 3)) / log(2) # entanglement entropy between qubits (1, 3) and (2,)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_rand3 = rand_state(3, nlevel=3) # a random qutrit state\nreg_prod3 = product_state(dit\"120;3\") # a qudit product state, what follows \";\" symbol denotes the number of levels\nprint_table(reg_prod3)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_batch = rand_state(3; nbatch=2) # a batch of 2 random qubit states\nprint_table(reg_batch)\nreg_view = viewbatch(reg_batch, 1) # view the first state in the batch\nprint_table(reg_view)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg = rand_state(3; nlevel=4, nbatch=2)\nnqudits(reg) # the total number of qudits\nnactive(reg) # the number of active qubits\nnremain(reg) # the number of remaining qubits\nnbatch(reg) # the batch size\nnlevel(reg) # the number of levels of each qudit\nbasis(reg) # the basis of the register\nfocus!(reg, 1:2) # set on the first two qubits as active\nnactive(reg) # the number of active qubits\nbasis(reg) # the basis of the register\nrelax!(reg) # set all qubits as active\nnactive(reg) # the number of active qubits\nreorder!(reg, (3,1,2)) # reorder the qubits\n\nreg1 = product_state(bit\"111\");\nreg2 = ghz_state(3);\nfidelity(reg1, reg2) # the fidelity between two states\ntracedist(reg1, reg2) # the trace distance between two states","category":"page"},{"location":"man/registers.html#Arithmetic-operations","page":"Quantum Registers","title":"Arithmetic operations","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The list of arithmetic operations for ArrayReg include ","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"+\n-\n*\n/ (scalar)\nadjoint","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg1 = rand_state(3)\nreg2 = rand_state(3)\nreg3 = reg1 + reg2 # addition\nnormalize!(reg3) # normalize the state\nisnormalized(reg3) # check if the state is normalized\nreg1 - reg2 # subtraction\nreg1 * 2 # scalar multiplication\nreg1 / 2 # scalar division\nreg1' # adjoint\nreg1' * reg1 # inner product","category":"page"},{"location":"man/registers.html#Register-operations","page":"Quantum Registers","title":"Register operations","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg0 = rand_state(3)\nappend_qudits!(reg0, 2) # append 2 qubits\ninsert_qudits!(reg0, 2, 2) # insert 2 qubits at the 2nd position","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"Comparing with using matrix multiplication for quantum simulation, using specialized instructions are much faster and memory efficient. These instructions are specified with the instruct! function.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg = zero_state(2)\ninstruct!(reg, Val(:H), (1,)) # apply a Hadamard gate on the first qubit\nprint_table(reg)","category":"page"},{"location":"man/registers.html#Measurement","page":"Quantum Registers","title":"Measurement","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"We use the measure! function returns the measurement outcome and collapses the state after the measurement. We also have some \"cheating\" version measure that does not collapse states to facilitate classical simulation.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"measure!(reg0, 1) # measure the qubit, the state collapses\nmeasure!(reg0) # measure all qubits\nmeasure(reg0, 3) # measure the qubit at location 3, the state does not collapse (hacky)\nreorder!(reg0, 7:-1:1) # reorder the qubits\nmeasure!(reg0)\ninvorder!(reg0) # reverse the order of qubits\nmeasure!(reg0)\nmeasure!(RemoveMeasured(), reg0, 2:4) # remove the measured qubits\nreg0\n\nreg1 = ghz_state(3)\nselect!(reg1, bit\"111\") # post-select the |111⟩ state\nisnormalized(reg1) # check if the state is normalized","category":"page"},{"location":"man/registers.html#Density-matrices","page":"Quantum Registers","title":"Density matrices","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg = rand_state(3)\nrho = density_matrix(reg) # the density matrix of the state\nrand_density_matrix(3) # a random density matrix\ncompletely_mixed_state(3) # a completely mixed state\npartial_tr(rho, 1) # partial trace on the first qubit\npurify(rho) # purify the state\nvon_neumann_entropy(rho) # von Neumann entropy\nmutual_information(rho, 1, 2) # mutual information between qubits 1 and 2","category":"page"},{"location":"man/registers.html#API","page":"Quantum Registers","title":"API","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The constructors and functions for quantum registers are listed below.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"AbstractRegister\nAbstractArrayReg\nArrayReg\nBatchedArrayReg","category":"page"},{"location":"man/registers.html#YaoAPI.AbstractRegister","page":"Quantum Registers","title":"YaoAPI.AbstractRegister","text":"AbstractRegister{D}\n\nAbstract type for quantum registers. Type parameter D is the number of levels in each qudit. For qubits, D = 2.\n\nRequired methods\n\ninstruct!\nnqudits\nnactive\ninsert_qubits!\nappend_qubits!\nfocus!\nrelax!\nreorder!\ninvorder!\n\nOptional methods\n\nnlevel\nnremain\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html#YaoArrayRegister.AbstractArrayReg","page":"Quantum Registers","title":"YaoArrayRegister.AbstractArrayReg","text":"AbstractArrayReg\n\nAbstract type for quantum registers that are represented by an array.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html#YaoArrayRegister.ArrayReg","page":"Quantum Registers","title":"YaoArrayRegister.ArrayReg","text":"ArrayReg{D,T,MT<:AbstractMatrix{T}} <: AbstractArrayRegister{D}\nArrayReg{D}(raw)\nArrayReg(raw::AbstractVecOrMat; nlevel=2)\nArrayReg(r::ArrayReg)\n\nSimulated full amplitude register type, it uses an array to represent corresponding one or a batch of quantum states. T is the numerical type for each amplitude, it is ComplexF64 by default.\n\nwarning: Warning\nArrayReg constructor will not normalize the quantum state. If you need a normalized quantum state remember to use normalize!(register) on the register.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html#YaoArrayRegister.BatchedArrayReg","page":"Quantum Registers","title":"YaoArrayRegister.BatchedArrayReg","text":"BatchedArrayReg{D,T,MT<:AbstractMatrix{T}} <: AbstractArrayReg{D}\nBatchedArrayReg(raw, nbatch; nlevel=2)\nBatchedArrayReg{D}(raw, nbatch)\n\nSimulated batched full amplitude register type, it uses an array to represent corresponding one or a batch of quantum states. T is the numerical type for each amplitude, it is ComplexF64 by default.\n\nwarning: Warning\nBatchedArrayReg constructor will not normalize the quantum state. If you need a normalized quantum state remember to use normalize!(register) on the register.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"arrayreg\nproduct_state\nzero_state\nzero_state_like\nrand_state\nuniform_state\nghz_state\nclone","category":"page"},{"location":"man/registers.html#YaoArrayRegister.arrayreg","page":"Quantum Registers","title":"YaoArrayRegister.arrayreg","text":"arrayreg(state; nbatch::Union{Integer,NoBatch}=NoBatch(), nlevel::Integer=2)\n\nCreate an array register, if nbatch is a integer, it will return a BatchedArrayReg.\n\n\n\n\n\narrayreg([T=ComplexF64], bit_str; nbatch=NoBatch())\n\nConstruct an array register from bit string literal. For bit string literal please read @bit_str.\n\nExamples\n\njulia> arrayreg(bit\"1010\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> arrayreg(ComplexF32, bit\"1010\")\nArrayReg{2, ComplexF32, Array...}\n active qubits: 4/4\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.product_state","page":"Quantum Registers","title":"YaoArrayRegister.product_state","text":"product_state([T=ComplexF64], dit_str; nbatch=NoBatch(), no_transpose_storage=false)\nproduct_state([T=ComplexF64], nbits::Int, val::Int; nbatch=NoBatch(), nlevel=2, no_transpose_storage=false)\nproduct_state([T=ComplexF64], vector; nbatch=NoBatch(), nlevel=2, no_transpose_storage=false)\n\nCreate an ArrayReg of product state. The configuration can be specified with a dit string, which can be defined with @bit_str or @dit_str. Or equivalently, it can be specified explicitly with nbits, val and nlevel. See also zero_state, rand_state, uniform_state.\n\nExamples\n\njulia> reg = product_state(dit\"120;3\"; nbatch=2)\nBatchedArrayReg{3, ComplexF64, Transpose...}\n active qudits: 3/3\n nlevel: 3\n nbatch: 2\n\njulia> measure(reg)\n1×2 Matrix{BitBasis.DitStr64{3, 3}}:\n 120 ₍₃₎ 120 ₍₃₎\n\njulia> product_state(bit\"100\"; nbatch=2);\n\njulia> r1 = product_state(ComplexF32, bit\"001\"; nbatch=2);\n\njulia> r2 = product_state(ComplexF32, [1, 0, 0]; nbatch=2);\n\njulia> r3 = product_state(ComplexF32, 3, 0b001; nbatch=2);\n\njulia> r1 ≈ r2 # because we read bit strings from right to left, vectors from left to right.\ntrue\n\njulia> r1 ≈ r3\ntrue\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.zero_state","page":"Quantum Registers","title":"YaoArrayRegister.zero_state","text":"zero_state([T=ComplexF64], n::Int; nbatch::Int=NoBatch())\n\nCreate an AbstractArrayReg that initialized to state 0rangle^otimes n. See also product_state, rand_state, uniform_state and ghz_state.\n\nExamples\n\njulia> zero_state(4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> zero_state(ComplexF32, 4)\nArrayReg{2, ComplexF32, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> zero_state(ComplexF32, 4; nbatch=3)\nBatchedArrayReg{2, ComplexF32, Transpose...}\n active qubits: 4/4\n nlevel: 2\n nbatch: 3\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.zero_state_like","page":"Quantum Registers","title":"YaoArrayRegister.zero_state_like","text":"zero_state_like(register, n) -> AbstractRegister\n\nCreate a register initialized to zero from an existing one.\n\nExamples\n\njulia> reg = rand_state(3; nbatch=2);\n\njulia> zero_state_like(reg, 2)\nBatchedArrayReg{2, ComplexF64, Array...}\n active qubits: 2/2\n nlevel: 2\n nbatch: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.rand_state","page":"Quantum Registers","title":"YaoArrayRegister.rand_state","text":"rand_state([T=ComplexF64], n::Int; nbatch=NoBatch(), no_transpose_storage=false)\n\nCreate a random AbstractArrayReg with total number of qudits n.\n\nExamples\n\njulia> rand_state(4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> rand_state(ComplexF64, 4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> rand_state(ComplexF64, 4; nbatch=2)\nBatchedArrayReg{2, ComplexF64, Transpose...}\n active qubits: 4/4\n nlevel: 2\n nbatch: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.uniform_state","page":"Quantum Registers","title":"YaoArrayRegister.uniform_state","text":"uniform_state([T=ComplexF64], n; nbatch=NoBatch(), no_transpose_storage=false)\n\nCreate a uniform state:\n\nfrac1sqrt2^n sum_k=0^2^n-1 krangle\n\nThis state can also be created by applying H (Hadmard gate) on 0000 state.\n\nExample\n\njulia> uniform_state(4; nbatch=2)\nBatchedArrayReg{2, ComplexF64, Transpose...}\n active qubits: 4/4\n nlevel: 2\n nbatch: 2\n\njulia> uniform_state(ComplexF32, 4; nbatch=2)\nBatchedArrayReg{2, ComplexF32, Transpose...}\n active qubits: 4/4\n nlevel: 2\n nbatch: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.ghz_state","page":"Quantum Registers","title":"YaoArrayRegister.ghz_state","text":"ghz_state([T=ComplexF64], n::Int; nbatch::Int=NoBatch())\n\nCreate a GHZ state (or a cat state) that defined as\n\nfrac0rangle^otimes n + 1rangle^otimes nsqrt2\n\nExamples\n\njulia> ghz_state(4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.clone","page":"Quantum Registers","title":"YaoAPI.clone","text":"clone(register, n)\n\nCreate an ArrayReg by cloning the original register for n times on batch dimension. This function is only for emulation.\n\nExample\n\njulia> clone(arrayreg(bit\"101\"; nbatch=3), 4)\nBatchedArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n nbatch: 12\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for querying the properties of a quantum register.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"nqudits\nnqubits\nnactive\nnremain\nnbatch\nnlevel\nfocus!\nfocus\nrelax!\nexchange_sysenv","category":"page"},{"location":"man/registers.html#YaoAPI.nqudits","page":"Quantum Registers","title":"YaoAPI.nqudits","text":"nqudits(register) -> Int\n\nReturns the total number of qudits in register.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.nqubits","page":"Quantum Registers","title":"YaoAPI.nqubits","text":"nqubits(register) -> Int\n\nReturns the (total) number of qubits. See nactive, nremain for more details.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.nactive","page":"Quantum Registers","title":"YaoAPI.nactive","text":"nactive(register) -> Int\n\nReturns the number of active qudits in register. Here, active qudits means the system qubits that operators can be applied on.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.nremain","page":"Quantum Registers","title":"YaoAPI.nremain","text":"nremain(register) -> Int\n\nReturns the number of inactive qudits in register. It equals to subtracting nqudits and nactive.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.nbatch","page":"Quantum Registers","title":"YaoArrayRegister.nbatch","text":"nbatch(register) -> Union{Int,NoBatch()}\n\nReturns the number of batches.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.nlevel","page":"Quantum Registers","title":"YaoAPI.nlevel","text":"nlevel(x)\n\nNumber of levels in each qudit.\n\nExamples\n\njulia> nlevel(X)\n2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.focus!","page":"Quantum Registers","title":"YaoAPI.focus!","text":"focus!(register, locs) -> register\nfocus!(locs...) -> f(register) -> register\n\nSet the active qubits to focused locations, usually used to execute a subroutine. If register is not provided, returns a lambda that takes a register as input.\n\nExamples\n\njulia> reg = product_state(bit\"01101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> focus!(reg, (1,3,4))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/5\n nlevel: 2\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 111 ₍₂₎\n 111 ₍₂₎\n 111 ₍₂₎\n\njulia> measure(apply(reg, put(3, 2=>X)); nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 101 ₍₂₎\n 101 ₍₂₎\n 101 ₍₂₎\n\nHere, we prepare a product state and only look at the qubits 1, 3 and 4. The measurement results are all ones. With the focued register, we can apply a block of size 3 on it, even though the number of qubits is 5.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.focus","page":"Quantum Registers","title":"YaoAPI.focus","text":"focus(f, register, locs)\n\nCall a callable f under the context of focus. See also focus!.\n\nExamples\n\nTo print the focused register\n\njulia> r = arrayreg(bit\"101100\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 6/6\n nlevel: 2\n\njulia> focus(x->(println(x);x), r, (1, 2));\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/6\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.relax!","page":"Quantum Registers","title":"YaoAPI.relax!","text":"relax!(register[, locs]; to_nactive=nqudits(register)) -> register\nrelax!(locs::Int...; to_nactive=nqudits(register)) -> f(register) -> register\n\nInverse transformation of focus!, where to_nactive is the number of active bits for target register. If the register is not provided, returns a lambda function that takes a register as input.\n\nExamples\n\njulia> reg = product_state(bit\"01101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> focus!(reg, (1,3,4))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/5\n nlevel: 2\n\njulia> relax!(reg, (1,3,4))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.exchange_sysenv","page":"Quantum Registers","title":"YaoArrayRegister.exchange_sysenv","text":"exchange_sysenv(reg::AbstractArrayReg) -> AbstractRegister\n\nExchange system (focused qubits) and environment (remaining qubits).\n\njulia> reg = rand_state(5)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> focus!(reg, (2,4))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/5\n nlevel: 2\n\njulia> exchange_sysenv(reg)\nArrayReg{2, ComplexF64, Adjoint...}\n active qubits: 3/5\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for querying the state of a quantum register.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"state\nbasis\nstatevec\nrelaxedvec\nhypercubic\nrank3\nviewbatch\ntranspose_storage","category":"page"},{"location":"man/registers.html#YaoArrayRegister.state","page":"Quantum Registers","title":"YaoArrayRegister.state","text":"state(register::AbstractArrayReg) -> Matrix\n\nReturns the raw array storage of register. See also statevec.\n\n\n\n\n\nstate(ρ::DensityMatrix) -> Matrix\n\nReturn the raw state of density matrix ρ.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#BitBasis.basis","page":"Quantum Registers","title":"BitBasis.basis","text":"basis(ditstr) -> UnitRange{DitStr{D,N,T}}\nbasis(DitStr{D,N,T}) -> UnitRange{DitStr{D,N,T}}\n\nReturns the UnitRange for basis in Hilbert Space of qudits.\n\n\n\n\n\nbasis(register) -> UnitRange\n\nReturns an UnitRange of the all the bits in the Hilbert space of given register.\n\njulia> collect(basis(rand_state(3)))\n8-element Vector{DitStr{2, 3, Int64}}:\n 000 ₍₂₎\n 001 ₍₂₎\n 010 ₍₂₎\n 011 ₍₂₎\n 100 ₍₂₎\n 101 ₍₂₎\n 110 ₍₂₎\n 111 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.statevec","page":"Quantum Registers","title":"YaoArrayRegister.statevec","text":"statevec(r::ArrayReg) -> array\n\nReturn a state matrix/vector by droping the last dimension of size 1 (i.e. nactive(r) = nqudits(r)). See also state.\n\nwarning: Warning\nstatevec is not type stable. It may cause performance slow down.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.relaxedvec","page":"Quantum Registers","title":"YaoArrayRegister.relaxedvec","text":"relaxedvec(r::AbstractArrayReg) -> AbstractArray\n\nReturn a vector representation of state, with all qudits activated. See also state, statevec.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#BitBasis.hypercubic","page":"Quantum Registers","title":"BitBasis.hypercubic","text":"hypercubic(A::Array) -> Array\n\nget the hypercubic representation for an array.\n\n\n\n\n\nhypercubic(r::ArrayReg) -> AbstractArray\n\nReturn the hypercubic representation (high dimensional tensor) of this register, only active qudits are considered. See also rank3 and state.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.rank3","page":"Quantum Registers","title":"YaoArrayRegister.rank3","text":"rank3(r::ArrayReg)\n\nReturn the rank 3 tensor representation of state, the 3 dimensions are (activated space, remaining space, batch dimension). See also hypercubic and state.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.viewbatch","page":"Quantum Registers","title":"YaoAPI.viewbatch","text":"viewbatch(register, i::Int) -> AbstractRegister\n\nReturns the i-th single register of a batched register. The returned instance is a view of the original register, i.e. inplace operation changes the original register directly.\n\nExamples\n\njulia> reg = zero_state(5; nbatch=2);\n\njulia> apply!(viewbatch(reg, 2), put(5, 2=>X));\n\njulia> measure(reg; nshots=3)\n3×2 Matrix{DitStr{2, 5, Int64}}:\n 00000 ₍₂₎ 00010 ₍₂₎\n 00000 ₍₂₎ 00010 ₍₂₎\n 00000 ₍₂₎ 00010 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.transpose_storage","page":"Quantum Registers","title":"YaoArrayRegister.transpose_storage","text":"transpose_storage(register) -> register\n\nTranspose the register storage. Sometimes transposed storage provides better performance for batched simulation.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for arithmetic operations on quantum registers.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"AdjointArrayReg","category":"page"},{"location":"man/registers.html#YaoArrayRegister.AdjointArrayReg","page":"Quantum Registers","title":"YaoArrayRegister.AdjointArrayReg","text":"AdjointArrayReg{D,T,MT} = AdjointRegister{D,<:AbstractArrayReg{D,T,MT}}\n\nAdjoint array register type, it is used to represent the bra in the Dirac notation.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"We also have some faster inplace versions of arithematic operations","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"regadd!\nregsub!\nregscale!","category":"page"},{"location":"man/registers.html#YaoArrayRegister.regadd!","page":"Quantum Registers","title":"YaoArrayRegister.regadd!","text":"regadd!(target, source)\n\nInplace version of + that accumulates source to target.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.regsub!","page":"Quantum Registers","title":"YaoArrayRegister.regsub!","text":"regsub!(target, source)\n\nInplace version of - that subtract source from target.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.regscale!","page":"Quantum Registers","title":"YaoArrayRegister.regscale!","text":"regscale!(target, x)\n\nInplace version of multiplying a scalar x to target.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"We also define the following functions for state normalization, and distance measurement.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"normalize!\nisnormalized\nfidelity\ntracedist","category":"page"},{"location":"man/registers.html#LinearAlgebra.normalize!","page":"Quantum Registers","title":"LinearAlgebra.normalize!","text":"normalize!(r::AbstractArrayReg)\n\nNormalize the register r by its 2-norm. It changes the register directly.\n\nExamples\n\nThe following code creates a normalized GHZ state.\n\njulia> reg = product_state(bit\"000\") + product_state(bit\"111\");\n\njulia> norm(reg)\n1.4142135623730951\n\njulia> isnormalized(reg)\nfalse\n\njulia> normalize!(reg);\n\njulia> isnormalized(reg)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.isnormalized","page":"Quantum Registers","title":"YaoArrayRegister.isnormalized","text":"isnormalized(r::ArrayReg) -> Bool\n\nReturns true if the register r is normalized.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.fidelity","page":"Quantum Registers","title":"YaoAPI.fidelity","text":"fidelity(register1, register2) -> Real/Vector{<:Real}\nfidelity'(pair_or_reg1, pair_or_reg2) -> (g1, g2)\n\nReturn the fidelity between two states. Calcuate the fidelity between r1 and r2, if r1 or r2 is not pure state (nactive(r) != nqudits(r)), the fidelity is calcuated by purification. See also: http://iopscience.iop.org/article/10.1088/1367-2630/aa6a4b/meta\n\nObtain the gradient with respect to registers and circuit parameters. For pair input ψ=>circuit, the returned gradient is a pair of gψ=>gparams, with gψ the gradient of input state and gparams the gradients of circuit parameters. For register input, the return value is a register.\n\nDefinition\n\nThe fidelity of two quantum state for qudits is defined as:\n\nF(ρ σ) = tr(sqrtsqrtρσsqrtρ)\n\nnote: Note\nThis definition is different from the one in Wiki by a square.\n\nExamples\n\njulia> reg1 = uniform_state(3);\n\njulia> reg2 = zero_state(3);\n\njulia> fidelity(reg1, reg2)\n0.35355339059327373\n\nReferences\n\nJozsa R. Fidelity for mixed quantum states[J]. Journal of modern optics, 1994, 41(12): 2315-2323.\nNielsen M A, Chuang I. Quantum computation and quantum information[J]. 2002.\n\nnote: Note\nThe original definition of fidelity F was from \"transition probability\", defined by Jozsa in 1994, it is the square of what we use here.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.tracedist","page":"Quantum Registers","title":"YaoAPI.tracedist","text":"tracedist(register1, register2)\n\nReturn the trace distance of register1 and register2.\n\nDefinition\n\nTrace distance is defined as following:\n\nfrac12 A - B _rm tr\n\nIt takes values between 0 and 1.\n\nExamples\n\njulia> reg1 = uniform_state(3);\n\njulia> reg2 = zero_state(3);\n\njulia> tracedist(reg1, reg2)\n0.9354143466934852\n\nReferences\n\nhttps://en.wikipedia.org/wiki/Trace_distance\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for adding and reordering qubits in a quantum register.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"insert_qudits!\ninsert_qubits!\nappend_qudits!\nappend_qubits!\nreorder!\ninvorder!","category":"page"},{"location":"man/registers.html#YaoAPI.insert_qudits!","page":"Quantum Registers","title":"YaoAPI.insert_qudits!","text":"insert_qudits!(register, loc::Int, nqudits::Int) -> register\ninsert_qudits!(loc::Int, nqudits::Int) -> λ(register)\n\nInsert qudits to given register in state |0>. i.e. |psi> -> join(|psi>, |0...>, |psi>), increased bits have higher indices.\n\nExamples\n\njulia> reg = product_state(bit\"01101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> insert_qudits!(reg, 2, 2)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 7/7\n nlevel: 2\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 7, Int64}}:\n 0110001 ₍₂₎\n 0110001 ₍₂₎\n 0110001 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.insert_qubits!","page":"Quantum Registers","title":"YaoAPI.insert_qubits!","text":"insert_qubits!(register, loc::Int, nqubits::Int=1) -> register\ninsert_qubits!(loc::Int, nqubits::Int=1) -> λ(register)\n\nInsert n qubits to given register in state |0>. It is an alias of insert_qudits! function.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.append_qudits!","page":"Quantum Registers","title":"YaoAPI.append_qudits!","text":"append_qudits!(register, n::Int) -> register\nappend_qudits!(n::Int) -> λ(register)\n\nAdd n qudits to given register in state |0>. i.e. |psi> -> |000> ⊗ |psi>, increased bits have higher indices.\n\nIf only an integer is provided, then returns a lambda function.\n\nExamples\n\njulia> reg = product_state(bit\"01101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> append_qudits!(reg, 2)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 7/7\n nlevel: 2\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 7, Int64}}:\n 0001101 ₍₂₎\n 0001101 ₍₂₎\n 0001101 ₍₂₎\n\nNote here, we read the bit string from right to left.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.append_qubits!","page":"Quantum Registers","title":"YaoAPI.append_qubits!","text":"append_qubits!(register, n::Int) -> register\nappend_qubits!(n::Int) -> λ(register)\n\nAdd n qudits to given register in state |0>. It is an alias of append_qudits! function.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.reorder!","page":"Quantum Registers","title":"YaoAPI.reorder!","text":"reorder!(reigster, orders)\n\nReorder the locations of register by input orders. For a 3-qubit register, an order (i, j, k) specifies the following reordering of qubits\n\nmove the first qubit go to i,\nmove the second qubit go to j,\nmove the third qubit go to k.\n\nnote: Note\nThe convention of reorder! is different from the permutedims function, one can use the sortperm function to relate the permutation order and the order in this function.\n\nExamples\n\njulia> reg = product_state(bit\"010101\");\n\njulia> reorder!(reg, (1,4,2,5,3,6));\n\njulia> measure(reg)\n1-element Vector{DitStr{2, 6, Int64}}:\n 000111 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.invorder!","page":"Quantum Registers","title":"YaoAPI.invorder!","text":"invorder!(register)\n\nInverse the locations of the register.\n\nExamples\n\njulia> reg = product_state(bit\"010101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 6/6\n nlevel: 2\n\njulia> measure(invorder!(reg); nshots=3)\n3-element Vector{DitStr{2, 6, Int64}}:\n 101010 ₍₂₎\n 101010 ₍₂₎\n 101010 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The instruct! function is for applying quantum operators on a quantum register.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"YaoArrayRegister.instruct!","category":"page"},{"location":"man/registers.html#YaoAPI.instruct!","page":"Quantum Registers","title":"YaoAPI.instruct!","text":"instruct!([nlevel=Val(2), ]state, operator, locs[, control_locs, control_configs, theta])\n\nUnified interface for applying an operator to a quantum state. It modifies the state directly.\n\nArguments\n\nnlevel is the number of levels in each qudit,\nstate is a vector or matrix representing the quantum state, where the first dimension is the active qubit dimension, the second is the batch dimension.\noperator is a quantum operator, which can be Val(GATE_SYMBOL) or a matrix.\nlocs::Tuple is a tuple for specifying the locations this gate applied.\ncontrol_locs::Tuple and control_configs are tuples for specifying the control locations and control values.\ntheta::Real is the parameter for the gate, e.g. Val(:Rx) gate takes a real number of its parameter.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for measurement and post-selection.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"measure!\nmeasure\nselect!\nselect\ncollapseto!\nprobs\nmost_probable","category":"page"},{"location":"man/registers.html#YaoAPI.measure!","page":"Quantum Registers","title":"YaoAPI.measure!","text":"measure!([postprocess,] [operator, ]register[, locs]; rng=Random.GLOBAL_RNG)\n\nMeasure current active qudits or qudits at locs. If the operator is not provided, it will measure on the computational basis and collapse to a product state. Otherwise, the quantum state collapse to the subspace corresponds to the resulting eigenvalue of the observable.\n\nArguments\n\npostprocess is the postprocessing method, it can be\nNoPostProcess() (default).\nResetTo(config), reset to result state to config. It can not be used if operator is provided, because measuring an operator in general does not return a product state.\nRemoveMeasured(), remove the measured qudits from the register. It is also incompatible with the operator argument.\noperator::AbstractBlock is the operator to measure.\nregister::AbstractRegister is the quantum state.\nlocs is the qubits to performance the measurement. If locs is not provided, all current active qudits are measured (regarding to active qudits,\n\nsee focus! and relax!).\n\nKeyword arguments\n\nrng is the random number generator.\n\nExamples\n\nThe following example measures a random state on the computational basis and reset it to a certain bitstring value.\n\njulia> reg = rand_state(3);\n\njulia> measure!(ResetTo(bit\"011\"), reg)\n110 ₍₂₎\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 011 ₍₂₎\n 011 ₍₂₎\n 011 ₍₂₎\n\njulia> measure!(RemoveMeasured(), reg, (1,2))\n11 ₍₂₎\n\njulia> reg # removed qubits are not usable anymore\nArrayReg{2, ComplexF64, Array...}\n active qubits: 1/1\n nlevel: 2\n\nMeasuring an operator will project the state to the subspace associated with the returned eigenvalue.\n\njulia> reg = uniform_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> print_table(reg)\n000 ₍₂₎ 0.35355 + 0.0im\n001 ₍₂₎ 0.35355 + 0.0im\n010 ₍₂₎ 0.35355 + 0.0im\n011 ₍₂₎ 0.35355 + 0.0im\n100 ₍₂₎ 0.35355 + 0.0im\n101 ₍₂₎ 0.35355 + 0.0im\n110 ₍₂₎ 0.35355 + 0.0im\n111 ₍₂₎ 0.35355 + 0.0im\n\njulia> measure!(repeat(3, Z, 1:3), reg)\n-1.0 + 0.0im\n\njulia> print_table(reg)\n000 ₍₂₎ 0.0 + 0.0im\n001 ₍₂₎ 0.5 + 0.0im\n010 ₍₂₎ 0.5 + 0.0im\n011 ₍₂₎ 0.0 + 0.0im\n100 ₍₂₎ 0.5 + 0.0im\n101 ₍₂₎ 0.0 + 0.0im\n110 ₍₂₎ 0.0 + 0.0im\n111 ₍₂₎ 0.5 + 0.0im\n\nHere, we measured the parity operator, as a result, the resulting state collapsed to the subspace with either even or odd parity.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.measure","page":"Quantum Registers","title":"YaoAPI.measure","text":"measure([, operator], register[, locs]; nshots=1, rng=Random.GLOBAL_RNG) -> Vector{Int}\n\nMeasure a quantum state and return measurement results of qudits. This measurement function a cheating version of measure! that does not collapse the input state. It also does not need to recompute the quantum state for performing multiple shots measurement.\n\nArguments\n\noperator::AbstractBlock is the operator to measure.\nregister::AbstractRegister is the quantum state.\nlocs is the qubits to performance the measurement. If locs is not provided, all current active qudits are measured (regarding to active qudits,\n\nsee focus! and relax!).\n\nKeyword arguments\n\nnshots::Int is the number of shots.\nrng is the random number generator.\n\nExamples\n\njulia> reg = product_state(bit\"110\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 110 ₍₂₎\n 110 ₍₂₎\n 110 ₍₂₎\n\njulia> measure(reg, (2,3); nshots=3)\n3-element Vector{DitStr{2, 2, Int64}}:\n 11 ₍₂₎\n 11 ₍₂₎\n 11 ₍₂₎\n\nThe following example switches to the X basis for measurement.\n\njulia> reg = apply!(product_state(bit\"100\"), repeat(3, H, 1:3))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> measure(repeat(3, X, 1:3), reg; nshots=3)\n3-element Vector{ComplexF64}:\n -1.0 + 0.0im\n -1.0 + 0.0im\n -1.0 + 0.0im\n\njulia> reg = apply!(product_state(bit\"101\"), repeat(3, H, 1:3))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> measure(repeat(3, X, 1:3), reg; nshots=3)\n3-element Vector{ComplexF64}:\n 1.0 - 0.0im\n 1.0 - 0.0im\n 1.0 - 0.0im\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.select!","page":"Quantum Registers","title":"YaoAPI.select!","text":"select!(dest::AbstractRegister, src::AbstractRegister, bits::Integer...) -> AbstractRegister\nselect!(register::AbstractRegister, bits::Integer...) -> register\nselect!(b::Integer) -> f(register)\n\nselect a subspace of given quantum state based on input eigen state bits. See also select for the non-inplace version. If the register is not provided, it returns a lambda expression that takes a register as the input.\n\nExamples\n\njulia> reg = ghz_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> select!(reg, bit\"111\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 0/0\n nlevel: 2\n\njulia> norm(reg)\n0.7071067811865476\n\nThe selection only works on the activated qubits, for example\n\njulia> reg = focus!(ghz_state(3), (1, 2))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/3\n nlevel: 2\n\njulia> select!(reg, bit\"11\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 0/1\n nlevel: 2\n\njulia> statevec(reg)\n1×2 Matrix{ComplexF64}:\n 0.0+0.0im 0.707107+0.0im\n\ntip: Tip\nDevelopers should overload select!(r::RegisterType, bits::NTuple{N, <:Integer}) and do not assume bits has specific number of bits (e.g Int64), or it will restrict the its maximum available number of qudits.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.select","page":"Quantum Registers","title":"YaoAPI.select","text":"select(register, bits) -> AbstractRegister\n\nThe non-inplace version of select!.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.collapseto!","page":"Quantum Registers","title":"YaoAPI.collapseto!","text":"collapseto!(register, config)\n\nSet the register to bit string literal bit_str (or an equivalent integer). About bit string literal, see more in @bit_str. This interface is only for emulation.\n\nExamples\n\nThe following code collapse a random state to a certain state.\n\njulia> measure(collapseto!(rand_state(3), bit\"001\"); nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 001 ₍₂₎\n 001 ₍₂₎\n 001 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.probs","page":"Quantum Registers","title":"YaoAPI.probs","text":"probs(register) -> Vector\n\nReturns the probability distribution of computation basis, aka xψ^2.\n\nExamples\n\njulia> reg = product_state(bit\"101\");\n\njulia> reg |> probs\n8-element Vector{Float64}:\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 1.0\n 0.0\n 0.0\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.most_probable","page":"Quantum Registers","title":"YaoArrayRegister.most_probable","text":"most_probable(reg::ArrayReg{D, T} where T, n::Int64) -> Any\n\n\nFind n most probable qubit configurations in a quantum register and return these configurations as a vector of DitStr instances.\n\nExample\n\njulia> most_probable(ghz_state(3), 2)\n2-element Vector{DitStr{2, 3, Int64}}:\n 000 ₍₂₎\n 111 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for density matrices.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"DensityMatrix\ndensity_matrix\nrand_density_matrix\ncompletely_mixed_state\npartial_tr\npurify\nvon_neumann_entropy\nmutual_information","category":"page"},{"location":"man/registers.html#YaoAPI.DensityMatrix","page":"Quantum Registers","title":"YaoAPI.DensityMatrix","text":"DensityMatrix{D,T,MT<:AbstractMatrix{T}} <: AbstractRegister{D}\nDensityMatrix{D}(state::AbstractMatrix)\nDensityMatrix(state::AbstractMatrix; nlevel=2)\n\nDensity matrix type, where state is a matrix. Type parameter D is the number of levels, it can also be specified by a keyword argument nlevel.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html#YaoAPI.density_matrix","page":"Quantum Registers","title":"YaoAPI.density_matrix","text":"density_matrix(register_or_rho[, locations])\n\nReturns the reduced density matrix for qubits at locations (default: all qubits).\n\nExamples\n\nThe following code gets the single site reduce density matrix for the GHZ state.\n\njulia> reg = ghz_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> density_matrix(reg, (2,)).state\n2×2 Matrix{ComplexF64}:\n 0.5+0.0im 0.0+0.0im\n 0.0-0.0im 0.5+0.0im\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.rand_density_matrix","page":"Quantum Registers","title":"YaoArrayRegister.rand_density_matrix","text":"rand_density_matrix([T=ComplexF64], n::Int; nlevel::Int=2, pure::Bool=false)\n\nGenerate a random density matrix by partial tracing half of the pure state.\n\nnote: Note\nThe generated density matrix is not strict hermitian due to rounding error. If you need to check hermicity, do not use ishermitian consider using isapprox(dm.state, dm.state') or explicit mark it as Hermitian.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.completely_mixed_state","page":"Quantum Registers","title":"YaoArrayRegister.completely_mixed_state","text":"completely_mixed_state([T=ComplexF64], n::Int; nlevel::Int=2)\n\nGenerate the completely mixed state with density matrix I(n) ./ nlevel^n.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.partial_tr","page":"Quantum Registers","title":"YaoAPI.partial_tr","text":"partial_tr(ρ, locs) -> DensityMatrix\n\nReturn a density matrix which is the partial traced on locs.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.purify","page":"Quantum Registers","title":"YaoAPI.purify","text":"purify(r::DensityMatrix; nbit_env::Int=nactive(r)) -> ArrayReg\n\nGet a purification of target density matrix.\n\nExamples\n\nThe following example shows how to measure a local operator on the register, reduced density matrix and the purified register. Their results should be consistent.\n\njulia> reg = ghz_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> r = density_matrix(reg, (2,));\n\njulia> preg = purify(r)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 1/2\n nlevel: 2\n\njulia> isapprox(expect(Z + Y, preg), 0.0; atol=1e-10)\ntrue\n\njulia> isapprox(expect(Z + Y, r), 0.0; atol=1e-10)\ntrue\n\njulia> isapprox(expect(put(3, 2=>(Z + Y)), reg), 0.0; atol=1e-10)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.von_neumann_entropy","page":"Quantum Registers","title":"YaoArrayRegister.von_neumann_entropy","text":"von_neumann_entropy(reg::AbstractArrayReg, part)\nvon_neumann_entropy(ρ::DensityMatrix)\n\nThe entanglement entropy between part and the rest part in quantum state reg. If the input is a density matrix, it returns the entropy of a mixed state.\n\nExample\n\nThe Von Neumann entropy of any segment of GHZ state is log 2.\n\njulia> von_neumann_entropy(ghz_state(3), (1,2))\n0.6931471805599612\n\n\n\n\n\nvon_neumann_entropy(rho) -> Real\n\nReturn the von-Neumann entropy for the input density matrix:\n\n-rm Tr(rholnrho)\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.mutual_information","page":"Quantum Registers","title":"YaoArrayRegister.mutual_information","text":"mutual_information(register_or_rho, part1, part2)\n\nReturns the mutual information between subsystems part1 and part2 of the input quantum register or density matrix:\n\nS(rho_A) + S(rho_B) - S(rho_AB)\n\nExample\n\nThe mutual information of a GHZ state of any two disjoint parts is always equal to log 2.\n\njulia> mutual_information(ghz_state(4), (1,), (3,4))\n0.6931471805599132\n\n\n\n\n\n","category":"function"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"EditURL = \"../../../examples/2.qft-phase-estimation/main.jl\"","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"(Image: )","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html#example-qft","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"","category":"section"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Let's use Yao first","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"using Yao","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html#Quantum-Fourier-Transformation","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation","text":"","category":"section"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"The Quantum Fourier Transformation (QFT) circuit is to repeat two kinds of blocks repeatly:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"(Image: qft-circuit)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"The basic building block control phase shift gate is defined as","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"R(k)=beginbmatrix\n1 0\n0 expleft(frac2pi i2^kright)\nendbmatrix","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Let's define block A and block B, block A is actually a control block.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1))))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"A (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Once you construct the blockl you can inspect its matrix using mat function. Let's construct the circuit in dash box A, and see the matrix of R_4 gate.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"R4 = A(4, 1)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"(n -> control(n, 4, 1 => shift(0.39269908169872414)))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"If you have read about preparing GHZ state, you probably know that in Yao, we could just leave the number of qubits, and it will be evaluated when possible.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"R4(5)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"nqubits: 5\ncontrol(4)\n└─ (1,) shift(0.39269908169872414)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"its matrix will be","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"mat(R4(5))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"32×32 Diagonal{ComplexF64, Vector{ComplexF64}}:\n 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Then we repeat this control block over and over on different qubits, and put a Hadamard gate to ith qubit to construct i-th B block.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"B(n, k) = chain(n, j==k ? put(k=>H) : A(j, k) for j in k:n)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"B (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"We need to input the total number of qubits n here because we have to iterate through from k-th location to the last.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Now, let's construct the circuit by chaining all the B blocks together","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"qft(n) = chain(B(n, k) for k in 1:n)\nqft(4)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"nqubits: 4\nchain\n├─ chain\n│ ├─ put on (1)\n│ │ └─ H\n│ ├─ control(2)\n│ │ └─ (1,) shift(1.5707963267948966)\n│ ├─ control(3)\n│ │ └─ (1,) shift(0.7853981633974483)\n│ └─ control(4)\n│ └─ (1,) shift(0.39269908169872414)\n├─ chain\n│ ├─ put on (2)\n│ │ └─ H\n│ ├─ control(3)\n│ │ └─ (2,) shift(1.5707963267948966)\n│ └─ control(4)\n│ └─ (2,) shift(0.7853981633974483)\n├─ chain\n│ ├─ put on (3)\n│ │ └─ H\n│ └─ control(4)\n│ └─ (3,) shift(1.5707963267948966)\n└─ chain\n └─ put on (4)\n └─ H\n","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html#Wrap-QFT-to-an-external-block","page":"Quantum Fourier Transformation and Phase Estimation","title":"Wrap QFT to an external block","text":"","category":"section"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"In most cases, functions are enough to wrap quantum circuits, like A and B we defined above, but sometimes, we need to dispatch specialized methods on certain kinds of quantum circuit, or we want to define an external block to export, thus, it's useful to be able to wrap circuit to custom blocks.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"First, we define a new type as subtype of PrimitiveBlock since we are not going to use the subblocks of QFT, if you need to use its subblocks, it'd be better to define it under CompositeBlock.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"struct QFT <: PrimitiveBlock{2}\n n::Int\nend\n\nYaoBlocks.nqudits(q::QFT) = q.n","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Now, let's define its circuit","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"circuit(q::QFT) = qft(q.n)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"circuit (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"And forward mat to its circuit's matrix","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"YaoBlocks.mat(::Type{T}, x::QFT) where T = mat(T, circuit(x))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"You may notice, it is a little ugly to print QFT at the moment, this is because we print the type summary by default, you can define your own printing by overloading print_block","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"YaoBlocks.print_block(io::IO, x::QFT) = print(io, \"QFT($(x.n))\")","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Since it is possible to use FFT to simulate the results of QFT (like cheating), we could define our custom apply! method:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"using FFTW, LinearAlgebra\n\nfunction YaoBlocks.apply!(r::ArrayReg, x::QFT)\n α = sqrt(length(statevec(r)))\n invorder!(r)\n lmul!(α, ifft!(statevec(r)))\n return r\nend","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Now let's check if our apply! method is correct:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"r = rand_state(5)\nr1 = r |> copy |> QFT(5)\nr2 = r |> copy |> circuit(QFT(5))\nr1 ≈ r2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"true","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"We can get iQFT (inverse QFT) directly by calling adjoint","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"QFT(5)'","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":" [†]QFT(5)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"QFT and iQFT are different from FFT and IFFT in three ways,","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"they are different by a factor of sqrt2^n with n the number of qubits.\nthe bit numbering will exchange after applying QFT or iQFT.\ndue to the convention, QFT is more related to IFFT rather than FFT.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html#Phase-Estimation","page":"Quantum Fourier Transformation and Phase Estimation","title":"Phase Estimation","text":"","category":"section"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Since we have QFT and iQFT blocks we can then use them to realize phase estimation circuit, what we want to realize is the following circuit:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"(Image: phase estimation)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"First we call Hadamard gates repeatly on first n qubits.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Hadamards(n) = repeat(H, 1:n)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Hadamards (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Then in dashed box B, we have controlled unitaries:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ControlU(n, m, U) = chain(n+m, control(k, n+1:n+m=>matblock(U^(2^(k-1)))) for k in 1:n)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ControlU (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"each of them is a U of power 2^(k-1).","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Since we will only apply the qft and Hadamard on first n qubits, we could use Subroutine, which creates a context of a sub-scope of the qubits.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"PE(n, m, U) =\n chain(n+m, # total number of the qubits\n subroutine(Hadamards(n), 1:n), # apply H in local scope\n ControlU(n, m, U),\n subroutine(QFT(n)', 1:n))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"PE (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"we use the first n qubits as the output space to store phase ϕ, and the other m qubits as the input state which corresponds to an eigenvector of oracle matrix U.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"The subroutine here uses focus! and relax! to manage a local scope of quantum circuit, and only activate the first n qubits while applying the block inside the subroutine context, and the scope will be relax!ed back, after the context. This is equivalent to manually focus! then relax!","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"fullly activated","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"r = rand_state(5)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"first 3 qubits activated","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"focus!(r, 1:3)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 3/5\n nlevel: 2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"relax back to the original","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"relax!(r, 1:3)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"In this way, we will be able to apply small operator directly on the subset of the qubits.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Details about the algorithm can be found here: Quantum Phase Estimation Algorithm","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Now let's check the results of our phase estimation.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"First we need to set up a unitary with known phase, we set the phase to be 0.75, which is 0.75 * 2^3 == 6 == 0b110 .","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"N, M = 3, 5\nP = eigen(rand_unitary(1< PE(N, M, U)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 8/8\n nlevel: 2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Since our phase can be represented by 3 qubits precisely, we only need to measure once","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"results = measure(r, 1:N; nshots=1)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"1-element Vector{DitStr{2, 3, Int64}}:\n 011 ₍₂₎","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Recall that our QFT's bit numbering is reversed, let's reverse it back","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"using BitBasis\nestimated_phase = bfloat(results[]; nbits=N)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"0.75","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"the phase is exactly 0.75!","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"This page was generated using Literate.jl.","category":"page"},{"location":"man/bitbasis.html","page":"BitBasis","title":"BitBasis","text":"CurrentModule = BitBasis\nDocTestSetup = quote\n using Yao\n using Yao: YaoBlocks, YaoArrayRegister\n using YaoBlocks\n using YaoArrayRegister\nend","category":"page"},{"location":"man/bitbasis.html#BitBasis","page":"BitBasis","title":"BitBasis","text":"","category":"section"},{"location":"man/bitbasis.html","page":"BitBasis","title":"BitBasis","text":"Types and operations for basis represented by bits in linear algebra.","category":"page"},{"location":"man/bitbasis.html","page":"BitBasis","title":"BitBasis","text":"For more details please ref to BitBasis.jl.","category":"page"},{"location":"man/bitbasis.html","page":"BitBasis","title":"BitBasis","text":"Modules = [BitBasis]\nOrder = [:macro, :function, :type, :module]","category":"page"},{"location":"man/bitbasis.html#BitBasis.@bit_str-Tuple{Any}","page":"BitBasis","title":"BitBasis.@bit_str","text":"@bit_str -> BitStr64\n\nConstruct a bit string. such as bit\"0000\". The bit strings also supports string join. Just use it like normal strings.\n\nExample\n\njulia> bit\"10001\"\n10001 ₍₂₎\n\njulia> bit\"100_111_101\"\n100111101 ₍₂₎\n\njulia> join(bit\"1001\", bit\"11\", bit\"1110\")\n1001111110 ₍₂₎\n\njulia> onehot(bit\"1001\")\n16-element Vector{ComplexF64}:\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 1.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n\n\n\n\n\n\n","category":"macro"},{"location":"man/bitbasis.html#BitBasis.@dit_str-Tuple{Any}","page":"BitBasis","title":"BitBasis.@dit_str","text":"@dit_str -> DitStr64\n\nConstruct a dit string. such as dit\"0201;3\". The dit strings also supports string join. Just use it like normal strings.\n\nExample\n\njulia> dit\"10201;3\"\n10201 ₍₃₎\n\njulia> dit\"100_121_121;3\"\n100121121 ₍₃₎\n\njulia> join(dit\"1021;3\", dit\"11;3\", dit\"1210;3\")\n1021111210 ₍₃₎\n\njulia> onehot(dit\"1021;3\")\n81-element Vector{ComplexF64}:\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n ⋮\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n\n\n\n\n\n\n","category":"macro"},{"location":"man/bitbasis.html#BitBasis.@lbit_str-Tuple{Any}","page":"BitBasis","title":"BitBasis.@lbit_str","text":"@lbit_str -> LongBitStr\n\nLong bit string version of @bit_str macro.\n\n\n\n\n\n","category":"macro"},{"location":"man/bitbasis.html#BitBasis.@ldit_str-Tuple{Any}","page":"BitBasis","title":"BitBasis.@ldit_str","text":"@ldit_str -> LongDitStr\n\nLong dit string version of @dit_str macro.\n\n\n\n\n\n","category":"macro"},{"location":"man/bitbasis.html#Base.:==-Union{Tuple{N2}, Tuple{N1}, Tuple{D}, Tuple{BitBasis.SubDitStr{D, N1}, DitStr{D, N2}}} where {D, N1, N2}","page":"BitBasis","title":"Base.:==","text":"==(lhs::SubDitStr{D,N,T}, rhs::DitStr{D,N,T}) -> Bool\n==(lhs::DitStr{D,N,T}, rhs::SubDitStr{D,N,T}) -> Bool\n==(lhs::SubDitStr{D,N,T}, rhs::SubDitStr{D,N,T}) -> Bool\n\nCompare the equality between SubDitStr and DitStr. \n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.allone-Union{Tuple{T}, Tuple{T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.allone","text":"allone(index::Integer, mask::Integer) -> Bool\n\nReturn true if all masked position of index is 1.\n\nExample\n\ntrue if all masked positions are 1.\n\njulia> allone(0b1011, 0b1011)\ntrue\n\njulia> allone(0b1011, 0b1001)\ntrue\n\njulia> allone(0b1011, 0b0100)\nfalse\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.anyone-Union{Tuple{T}, Tuple{T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.anyone","text":"anyone(index::Integer, mask::Integer) -> Bool\n\nReturn true if any masked position of index is 1.\n\nExample\n\ntrue if any masked positions is 1.\n\njulia> anyone(0b1011, 0b1001)\ntrue\n\njulia> anyone(0b1011, 0b1100)\ntrue\n\njulia> anyone(0b1011, 0b0100)\nfalse\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.baddrs-Tuple{Integer}","page":"BitBasis","title":"BitBasis.baddrs","text":"baddrs(b::Integer) -> Vector\n\nget the locations of nonzeros bits, i.e. the inverse operation of bmask.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.basis-Tuple{DitStr}","page":"BitBasis","title":"BitBasis.basis","text":"basis(ditstr) -> UnitRange{DitStr{D,N,T}}\nbasis(DitStr{D,N,T}) -> UnitRange{DitStr{D,N,T}}\n\nReturns the UnitRange for basis in Hilbert Space of qudits.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bdistance-Union{Tuple{Ti}, Tuple{Ti, Ti}} where Ti<:Integer","page":"BitBasis","title":"BitBasis.bdistance","text":"bdistance(i::Integer, j::Integer) -> Int\n\nReturn number of different bits.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bfloat-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bfloat","text":"bfloat(b::Integer; nbits::Int=bit_length(b)) -> Float64\n\nfloat view, with current bit numbering. See also bfloat_r.\n\nRef: wiki: bit numbering\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bfloat-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.bfloat","text":"bfloat(b::BitStr) -> Float64\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bfloat_r-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bfloat_r","text":"bfloat_r(b::Integer; nbits::Int=bit_length(b)) -> Float64\n\nfloat view, with reversed bit numbering. See also bfloat.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bfloat_r-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.bfloat_r","text":"bfloat_r(b::BitStr) -> Float64\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bint-Tuple{BitStr}","page":"BitBasis","title":"BitBasis.bint","text":"bint(b::BitStr) -> Integer\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bint-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bint","text":"bint(b; nbits=nothing) -> Int\n\ninteger view, with LSB 0 bit numbering. See also wiki: bit numbering\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bint_r-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bint_r","text":"bint_r(b; nbits::Int) -> Integer\n\ninteger read in inverse order.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bint_r-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.bint_r","text":"bint_r(b::BitStr) -> Integer\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bit_length-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bit_length","text":"bit_length(x::Integer) -> Int\n\nReturn the number of bits required to represent input integer x.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bitarray-Union{Tuple{T}, Tuple{Vector{T}, Int64}} where T<:Number","page":"BitBasis","title":"BitBasis.bitarray","text":"bitarray(v::Vector, [nbits::Int]) -> BitArray\nbitarray(v::Int, nbits::Int) -> BitArray\nbitarray(nbits::Int) -> Function\n\nConstruct BitArray from an integer vector, if nbits not supplied, it is 64. If an integer is supplied, it returns a function mapping a Vector/Int to bitarray.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bmask","page":"BitBasis","title":"BitBasis.bmask","text":"bmask(::Type{T}) where T <: Integer -> zero(T)\nbmask([T::Type], positions::Int...) -> T\nbmask([T::Type], range::UnitRange{Int}) -> T\n\nReturn an integer mask of type T where 1 is the position masked according to positions or range. Directly use T will return an empty mask 0.\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.breflect","page":"BitBasis","title":"BitBasis.breflect","text":"breflect(b::Integer[, masks::Vector{Integer}]; nbits) -> Integer\n\nReturn left-right reflected integer.\n\nExample\n\nReflect the order of bits.\n\njulia> breflect(0b1011; nbits=4) == 0b1101\ntrue\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.breflect-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.breflect","text":"breflect(bit_str[, masks])\n\nReturn left-right reflected bit string.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bsizeof-Union{Tuple{Type{T}}, Tuple{T}} where T","page":"BitBasis","title":"BitBasis.bsizeof","text":"bsizeof(::Type)\n\nReturns the size of given type in number of binary digits.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.btruncate-Union{Tuple{T}, Tuple{T, Any}} where T<:Integer","page":"BitBasis","title":"BitBasis.btruncate","text":"btruncate(b, n)\n\nTruncate bits b to given length n.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.controldo-Union{Tuple{S}, Tuple{Union{Function, Type}, BitBasis.IterControl{S}}} where S","page":"BitBasis","title":"BitBasis.controldo","text":"controldo(f, itr::IterControl)\n\nExecute f while iterating itr.\n\nnote: Note\nthis is faster but equivalent than using itr as an iterator. See also itercontrol.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.controller-Tuple{Union{UnitRange{T}, NTuple{var\"#s14\", T} where var\"#s14\", Vector{T}, T} where T<:Integer, Union{UnitRange{T}, NTuple{var\"#s14\", T} where var\"#s14\", Vector{T}, T} where T<:Integer}","page":"BitBasis","title":"BitBasis.controller","text":"controller([T=Int, ]cbits, cvals) -> Function\n\nReturn a function that checks whether a basis at cbits takes specific value cvals.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.flip-Union{Tuple{T}, Tuple{T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.flip","text":"flip(index::Integer, mask::Integer) -> Integer\n\nReturn an Integer with bits at masked position flipped.\n\nExample\n\njulia> flip(0b1011, 0b1011) |> BitStr{4}\n0000 ₍₂₎\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.group_shift!-Tuple{Int64, AbstractVector{Int64}}","page":"BitBasis","title":"BitBasis.group_shift!","text":"group_shift!(nbits, positions)\n\nShift bits on positions together.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.hypercubic-Tuple{Array}","page":"BitBasis","title":"BitBasis.hypercubic","text":"hypercubic(A::Array) -> Array\n\nget the hypercubic representation for an array.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.indicator-Union{Tuple{T}, Tuple{Type{T}, Int64}} where T<:Integer","page":"BitBasis","title":"BitBasis.indicator","text":"indicator(::Type{T}, k) -> T\n\nReturn an integer with k-th bit set to 1.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.indices_with-Tuple{Int64, Vector{Int64}, Vector{Int64}}","page":"BitBasis","title":"BitBasis.indices_with","text":"indices_with(n::Int, locs::Vector{Int}, vals::Vector{Int}) -> Vector{Int}\n\nReturn indices with specific positions locs with value vals in a hilbert space of n qubits.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.invorder-Tuple{AbstractVecOrMat}","page":"BitBasis","title":"BitBasis.invorder","text":"invorder(X::AbstractVecOrMat)\n\nInverse the order of given vector/matrix X.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.ismatch-Union{Tuple{T}, Tuple{T, T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.ismatch","text":"ismatch(index::Integer, mask::Integer, target::Integer) -> Bool\n\nReturn true if bits at positions masked by mask equal to 1 are equal to target.\n\nExample\n\njulia> n = 0b11001; mask = 0b10100; target = 0b10000;\n\njulia> ismatch(n, mask, target)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.itercontrol-Tuple{Int64, AbstractVector, Any}","page":"BitBasis","title":"BitBasis.itercontrol","text":"itercontrol([T=Int], nbits, positions, bit_configs)\n\nReturns an iterator which iterate through controlled subspace of bits.\n\nExample\n\nTo iterate through all the bits satisfy 0xx10x1 where x means an arbitrary bit.\n\njulia> for each in itercontrol(7, [1, 3, 4, 7], (1, 0, 1, 0))\n println(string(each, base=2, pad=7))\n end\n0001001\n0001011\n0011001\n0011011\n0101001\n0101011\n0111001\n0111011\n\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.log2dim1-Tuple{Any}","page":"BitBasis","title":"BitBasis.log2dim1","text":"log2dim1(X)\n\nReturns the log2 of the first dimension's size.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.log2i","page":"BitBasis","title":"BitBasis.log2i","text":"log2i(x::Integer) -> Integer\n\nReturn log2(x), this integer version of log2 is fast but only valid for number equal to 2^n.\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.neg-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.neg","text":"neg(b::BitStr) -> BitStr\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.neg-Union{Tuple{T}, Tuple{T, Int64}} where T<:Integer","page":"BitBasis","title":"BitBasis.neg","text":"neg(index::Integer, nbits::Int) -> Integer\n\nReturn an integer with all bits flipped (with total number of bit nbits).\n\nExample\n\njulia> neg(0b1111, 4) |> BitStr{4}\n0000 ₍₂₎\n\njulia> neg(0b0111, 4) |> BitStr{4}\n1000 ₍₂₎\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.next_reordered_basis-Union{Tuple{T}, Tuple{N}, Tuple{T, NTuple{N, T}, NTuple{N, T}}} where {N, T}","page":"BitBasis","title":"BitBasis.next_reordered_basis","text":"next_reordered_basis(basis, takers, differ)\n\nReturns the next reordered basis accroding to current basis.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.onehot-Union{Tuple{T1}, Tuple{N}, Tuple{T}, Tuple{D}, Tuple{Type{T}, DitStr{D, N, T1}}} where {D, T, N, T1}","page":"BitBasis","title":"BitBasis.onehot","text":"onehot([T=Float64], dit_str[; nbatch])\n\nCreate an onehot vector in type Vector{T} or a batch of onehot vector in type Matrix{T}, where index x + 1 is one. One can specify the value of the nonzero entry by inputing a pair.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.packbits-Tuple{AbstractVector}","page":"BitBasis","title":"BitBasis.packbits","text":"packbits(arr::AbstractArray) -> AbstractArray\n\npack bits to integers, usually take a BitArray as input.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.readat-Union{Tuple{T}, Tuple{N}, Tuple{D}, Tuple{DitStr{D, N, T}, Vararg{Integer}}} where {D, N, T}","page":"BitBasis","title":"BitBasis.readat","text":"readat(x, loc...) -> Integer\n\nRead the dit config at given location.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.readbit-Union{Tuple{T}, Tuple{T, Int64}} where T<:Integer","page":"BitBasis","title":"BitBasis.readbit","text":"readbit(x, loc...)\n\nRead the bit config at given location.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.reorder","page":"BitBasis","title":"BitBasis.reorder","text":"reorder(X::AbstractArray, orders)\n\nReorder X according to orders.\n\ntip: Tip\nAlthough orders can be any iterable, Tuple is preferred inorder to gain as much performance as possible. But the conversion won't take much anyway.\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.setbit-Union{Tuple{T}, Tuple{T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.setbit","text":"setbit(index::Integer, mask::Integer) -> Integer\n\nset the bit at masked position to 1.\n\nExample\n\njulia> setbit(0b1011, 0b1100) |> BitStr{4}\n1111 ₍₂₎\n\njulia> setbit(0b1011, 0b0100) |> BitStr{4}\n1111 ₍₂₎\n\njulia> setbit(0b1011, 0b0000) |> BitStr{4}\n1011 ₍₂₎\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.swapbits-Union{Tuple{T}, Tuple{T, Int64, Int64}} where T<:Integer","page":"BitBasis","title":"BitBasis.swapbits","text":"swapbits(n::Integer, mask_ij::Integer) -> Integer\nswapbits(n::Integer, i::Int, j::Int) -> Integer\n\nReturn an integer with bits at i and j flipped.\n\nExample\n\njulia> swapbits(0b1011, 0b1100) == 0b0111\ntrue\n\ntip: Tip\nlocations i and j specified by mask could be faster when bmask is not straight forward but known by constant.\n\nwarning: Warning\nmask_ij should only contain two 1, swapbits will not check it, use at your own risk.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.unsafe_reorder","page":"BitBasis","title":"BitBasis.unsafe_reorder","text":"unsafe_reorder(X::AbstractArray, orders)\n\nReorder X according to orders.\n\nwarning: Warning\nunsafe_reorder won't check whether the length of orders and the size of first dimension of X match, use at your own risk.\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.unsafe_sub-Union{Tuple{T}, Tuple{N}, Tuple{UnitRange{T}, NTuple{N, T}}} where {N, T}","page":"BitBasis","title":"BitBasis.unsafe_sub","text":"unsafe_sub(a::UnitRange, b::NTuple{N}) -> NTuple{N}\n\nReturns result in type Tuple of a .- b. This will not check the length of a and b, use at your own risk.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.unsafe_sub-Union{Tuple{T}, Tuple{UnitRange{T}, Vector{T}}} where T","page":"BitBasis","title":"BitBasis.unsafe_sub","text":"unsafe_sub(a::UnitRange{T}, b::Vector{T}) where T\n\nReturns a .- b, fallback version when b is a Vector.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.BitStr","page":"BitBasis","title":"BitBasis.BitStr","text":"BitStr{N,T} <: Integer\n\nThe struct for bit string with fixed length N and storage type T. It is an alias of DitStr{2,N,T}.\n\nBitStr{N,T}(integer)\nBitStr64{N}(integer)\nBitStr64(vector)\nLongBitStr{N}(integer)\nLongBitStr(vector)\n\nReturns a BitStr. When the input is an integer, the bits are read from right to left. When the input is a vector, the bits are read from left to right.\n\nExamples\n\nBitStr supports some basic arithmetic operations. It acts like an integer, but supports some frequently used methods for binary basis.\n\njulia> bit\"0101\" * 2\n1010 ₍₂₎\n\njulia> join([bit\"101\" for i in 1:10])\n\"101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎\"\n\njulia> repeat(bit\"101\", 2)\n101101 ₍₂₎\n\njulia> bit\"1101\"[2]\n0\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.DitStr","page":"BitBasis","title":"BitBasis.DitStr","text":"DitStr{D,N,T<:Integer} <: Integer\n\nThe struct for dit string with fixed length N and storage type T, where dit is a extension of dit from binary system to a d-ary system.\n\nDitStr{D,N,T}(integer)\nDitStr{D,N}(integer)\nDitStr{D}(vector)\n\nReturns a DitStr. When the input is an integer, the dits are read from right to left. When the input is a vector, the dits are read from left to right.\n\nExamples\n\njulia> DitStr{3}([1,2,1,1,0])\n01121 ₍₃₎\n\njulia> DitStr{3, 5}(71)\n02122 ₍₃₎\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.DitStr-Union{Tuple{BitBasis.SubDitStr{D, N, T}}, Tuple{T}, Tuple{N}, Tuple{D}} where {D, N, T}","page":"BitBasis","title":"BitBasis.DitStr","text":"DitStr(dit::SubDitStr{D,N,T}) -> DitStr{D,N,T}\n\nRaise type SubDitStr to DitStr.\n\njulia> x = DitStr{3, 5}(71)\n02122 ₍₃₎\n\njulia> sx = SubDitStr(x, 2, 4)\nSubDitStr{3, 5, Int64}(02122 ₍₃₎, 1, 3)\n\njulia> DitStr(sx)\n212 ₍₃₎\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.IterControl","page":"BitBasis","title":"BitBasis.IterControl","text":"IterControl{S}\nIterControl(n::Int, base::Int, masks, factors) -> IterControl\n\nIterator to iterate through controlled subspace. See also itercontrol. S is the number of chunks, n is the size of Hilbert space, base is the base of counter, masks and factors are helpers for enumerating over the target Hilbert Space.\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.LongLongUInt","page":"BitBasis","title":"BitBasis.LongLongUInt","text":"LongLongUInt{C} <: Integer\n\nA LongLongUInt{C} is an integer with C UInt numbers to store the value.\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.ReorderedBasis","page":"BitBasis","title":"BitBasis.ReorderedBasis","text":"ReorderedBasis{N, T}\n\nLazy reorderd basis.\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.ReorderedBasis-Union{Tuple{Tuple{T, Vararg{T, N}}}, Tuple{T}, Tuple{N}} where {N, T<:Integer}","page":"BitBasis","title":"BitBasis.ReorderedBasis","text":"ReorderedBasis(orders::NTuple{N, <:Integer})\n\nReturns a lazy set of reordered basis.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.SubDitStr","page":"BitBasis","title":"BitBasis.SubDitStr","text":"SubDitStr{D,N,T<:Integer} <: Integer\n\nThe struct as a SubString-like object for DitStr(SubString is an official implementation of sliced strings, see String for reference). This slicing returns a view into the parent DitStr instead of making a copy (similar to the @views macro for strings).\n\nSubDitStr can be used to describe the qubit configuration within the subspace of the entire Hilbert space.It provides similar getindex, length functions as DitStr. \n\nSubDitStr(dit::DitStr{D,N,T}, i::Int, j::Int)\nSubDitStr(dit::DitStr{D,N,T}, r::AbstractUnitRange{<:Integer})\n\nOr by @views macro for DitStr (this macro makes your life easier by supporting begin and end syntax):\n\n@views dit[i:j]\n\nReturns a SubDitStr.\n\nExamples\n\njulia> x = DitStr{3, 5}(71)\n02122 ₍₃₎\n\njulia> sx = SubDitStr(x, 2, 4) \nSubDitStr{3, 5, Int64}(02122 ₍₃₎, 1, 3)\n\njulia> @views x[2:end] \nSubDitStr{3, 5, Int64}(02122 ₍₃₎, 1, 4)\n\njulia> sx == dit\"212;3\"\ntrue\n\n\n\n\n\n","category":"type"},{"location":"index.html","page":"Home","title":"Home","text":"CurrentModule = Yao","category":"page"},{"location":"index.html#Yao","page":"Home","title":"Yao","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"A General Purpose Quantum Computation Simulation Framework","category":"page"},{"location":"index.html","page":"Home","title":"Home","text":"Welcome to Yao, a Flexible, Extensible, Efficient Framework for Quantum Algorithm Design. Yao (幺) is the Chinese character for normalized but not orthogonal.","category":"page"},{"location":"index.html","page":"Home","title":"Home","text":"We aim to provide a powerful tool for researchers, students to study and explore quantum computing in near term future, before quantum computer being used in large-scale.","category":"page"},{"location":"index.html#Quick-Starts","page":"Home","title":"Quick Starts","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"You can learn how to use Yao with some quick examples in this section. There are three badges on the top of each tutorial that allows you to open it in mybinder, preview it in nbviewer or download the tutorial as .zip file, which includes the notebook and the scripts and other related materials.","category":"page"},{"location":"index.html#Contribution","page":"Home","title":"Contribution","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"If you are interesting in polishing or contributing our tutorial, you can just open a PR in our tutorial repo.","category":"page"},{"location":"index.html#Syntax","page":"Home","title":"Syntax","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"The tutorials are written with Literate.","category":"page"},{"location":"index.html#Pluto-Notebooks","page":"Home","title":"Pluto Notebooks","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"There is also a set of Pluto notebooks available in the notebooks folder","category":"page"},{"location":"index.html#Manual","page":"Home","title":"Manual","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"Pages = [\n \"man/array_registers.md\",\n \"man/blocks.md\",\n \"man/registers.md\",\n \"man/extending_blocks.md\",\n]\nDepth = 1","category":"page"},{"location":"man/simplification.html#Simplification","page":"Simplification","title":"Simplification","text":"","category":"section"},{"location":"man/simplification.html","page":"Simplification","title":"Simplification","text":"The simplification for YaoBlocks is currently implemented in a limited and straightforward fashion, there is only one interface simplify to call.","category":"page"},{"location":"man/simplification.html#APIs","page":"Simplification","title":"APIs","text":"","category":"section"},{"location":"man/simplification.html","page":"Simplification","title":"Simplification","text":"Modules = [YaoBlocks.Optimise]\nOrder = [:function, :macro]","category":"page"},{"location":"man/simplification.html#YaoBlocks.Optimise.is_pauli-Tuple","page":"Simplification","title":"YaoBlocks.Optimise.is_pauli","text":"is_pauli(x)\n\nCheck if x is an element of pauli group.\n\n\n\n\n\n","category":"method"},{"location":"man/simplification.html#YaoBlocks.Optimise.replace_block-Tuple{Any, AbstractBlock}","page":"Simplification","title":"YaoBlocks.Optimise.replace_block","text":"replace_block(actor, tree::AbstractBlock) -> AbstractBlock\nreplace_block(pair::Pair{Type{ST}, TT}, tree::AbstractBlock) -> AbstractBlock\n\nreplace blocks in a circuit, where actor is a function that given input block, returns the block to replace, or nothing for skip replacing and visit sibling. If pair is provided, then replace original block with type ST with new block (pair.second).\n\n\n\n\n\n","category":"method"},{"location":"man/simplification.html#YaoBlocks.Optimise.simplify-Tuple{AbstractBlock}","page":"Simplification","title":"YaoBlocks.Optimise.simplify","text":"simplify(block[; rules=__default_simplification_rules__])\n\nSimplify a block tree accroding to given rules, default to use YaoBlocks.Optimise.__default_simplification_rules__.\n\n\n\n\n\n","category":"method"},{"location":"man/simplification.html#YaoBlocks.Optimise.to_basictypes","page":"Simplification","title":"YaoBlocks.Optimise.to_basictypes","text":"to_basictypes(block::AbstractBlock)\n\nconvert gates to basic types\n\n* ChainBlock\n* PutBlock\n* PrimitiveBlock\n\n\n\n\n\n","category":"function"}] +[{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"CurrentModule = YaoBlocks\nDocTestSetup = quote\n using Yao\n using Yao: YaoBlocks, YaoArrayRegister\n using YaoBlocks\n using YaoArrayRegister\nend","category":"page"},{"location":"man/blocks.html#Blocks","page":"Blocks","title":"Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Blocks are the basic building blocks of a quantum circuit in Yao. It simply means a quantum operator, thus, all the blocks have matrices in principal and one can get its matrix by mat. The basic blocks required to build an arbitrary quantum circuit is defined in the component package YaoBlocks.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Block Tree serves as an intermediate representation for Yao to analysis, optimize the circuit, then it will be lowered to instructions like for simulations, blocks will be lowered to instruct! calls.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"The structure of blocks is the same with a small type system, it consists of two basic kinds of blocks: CompositeBlock (like composite types), and PrimitiveBlock (like primitive types). By combining these two kinds of blocks together, we'll be able to construct a quantum circuit and represent it in a tree data structure.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"AbstractBlock\nPrimitiveBlock\nCompositeBlock","category":"page"},{"location":"man/blocks.html#YaoAPI.AbstractBlock","page":"Blocks","title":"YaoAPI.AbstractBlock","text":"AbstractBlock{D}\n\nAbstract type for quantum circuit blocks. while D is the number level in each qudit.\n\nRequired Methods\n\napply!.\nmat.\noccupied_locs.\nprint_block\n\nOptional Methods\n\ncontent\nchcontent\nsubblocks.\nchsubblocks.\nBase.hash\nBase.:(==)\nnlevel.\ngetiparams.\nsetiparams!.\nparameters.\nnparameters.\niparams_eltype.\nparameters_eltype.\ndispatch!.\nrender_params.\napply_back!.\nmat_back!.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoAPI.PrimitiveBlock","page":"Blocks","title":"YaoAPI.PrimitiveBlock","text":"PrimitiveBlock{D} <: AbstractBlock{D}\n\nAbstract type that all primitive block will subtype from. A primitive block is a concrete block who can not be decomposed into other blocks. All composite block can be decomposed into several primitive blocks.\n\nnote: Note\nsubtype for primitive block with parameter should implement hash and == method to enable key value cache.\n\nRequired Methods\n\napply!\nmat\nprint_block\nBase.hash\nBase.:(==)\n\nOptional Methods\n\nnlevel.\ngetiparams.\nsetiparams!.\nparameters.\nnparameters.\niparams_eltype.\nparameters_eltype.\ndispatch!.\nrender_params.\napply_back!.\nmat_back!.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoAPI.CompositeBlock","page":"Blocks","title":"YaoAPI.CompositeBlock","text":"CompositeBlock{D} <: AbstractBlock{D}\n\nAbstract supertype which composite blocks will inherit from. Composite blocks are blocks composited from other AbstractBlocks, thus it is a AbstractBlock as well.\n\nRequired Methods\n\napply!\nmat\noccupied_locs.\nsubblocks.\nchsubblocks.\n\nOptional Methods\n\nnlevel.\ngetiparams.\nsetiparams!.\nparameters.\nnparameters.\niparams_eltype.\nparameters_eltype.\ndispatch!.\nrender_params.\napply_back!.\nmat_back!.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#Primitive-Blocks","page":"Blocks","title":"Primitive Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Primitive blocks are subtypes of PrimitiveBlock, they are the leaf nodes in a block tree, thus primitive types do not have subtypes.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"We provide the following primitive blocks:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Modules = [YaoBlocks]\nFilter = t ->(t isa Type && t <: YaoBlocks.PrimitiveBlock)","category":"page"},{"location":"man/blocks.html#YaoBlocks.GeneralMatrixBlock","page":"Blocks","title":"YaoBlocks.GeneralMatrixBlock","text":"GeneralMatrixBlock{D, MT} <: PrimitiveBlock{D}\nGeneralMatrixBlock{D}(m, n, A, tag=\"matblock(...)\")\nGeneralMatrixBlock(A; nlevel=2, tag=\"matblock(...)\")\n\nGeneral matrix gate wraps a matrix operator to quantum gates. This is the most general form of a quantum gate.\n\nArguments\n\nm and n are the number of dits in row and column.\nA is a matrix.\ntag is the printed information.\nD and nlevel are the number of levels in each qudit.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.IdentityGate","page":"Blocks","title":"YaoBlocks.IdentityGate","text":"IdentityGate{D} <: TrivialGate{D}\n\nThe identity gate.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Measure","page":"Blocks","title":"YaoBlocks.Measure","text":"Measure{D,K, OT, LT, PT, RNG} <: PrimitiveBlock{D}\nMeasure(n::Int; rng=Random.GLOBAL_RNG, operator=ComputationalBasis(), locs=1:n, resetto=nothing, remove=false, nlevel=2)\n\nMeasure operator, currently only qudits are supported.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Measure-Union{Tuple{Int64}, Tuple{RNG}, Tuple{OT}} where {OT, RNG}","page":"Blocks","title":"YaoBlocks.Measure","text":"Measure(n::Int; rng=Random.GLOBAL_RNG, operator=ComputationalBasis(), locs=AllLocs(), resetto=nothing, remove=false)\n\nCreate a Measure block with number of qudits n.\n\nExamples\n\nYou can create a Measure block on given basis (default is the computational basis).\n\njulia> Measure(4)\nMeasure(4)\n\nOr you could specify which qudits you are going to measure\n\njulia> Measure(4; locs=1:3)\nMeasure(4;locs=(1, 2, 3))\n\nby default this will collapse the current register to measure results.\n\njulia> r = normalize!(arrayreg(bit\"000\") + arrayreg(bit\"111\"))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> state(r)\n8×1 Matrix{ComplexF64}:\n 0.7071067811865475 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.7071067811865475 + 0.0im\n\njulia> r |> Measure(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> state(r)\n8×1 Matrix{ComplexF64}:\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 1.0 + 0.0im\n\nBut you can also specify the target bit configuration you want to collapse to with keyword resetto.\n\n```jldoctest; setup=:(using Yao) julia> m = Measure(4; resetto=bit\"0101\") Measure(4;postprocess=ResetTo{BitStr{4,Int64}}(0101 ₍₂₎))\n\njulia> m.postprocess ResetTo{BitStr{4,Int64}}(0101 ₍₂₎)```\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.PhaseGate","page":"Blocks","title":"YaoBlocks.PhaseGate","text":"PhaseGate\n\nGlobal phase gate.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Projector","page":"Blocks","title":"YaoBlocks.Projector","text":"struct Projector{D, T, AT<:(AbstractArrayReg{D, T})} <: PrimitiveBlock{D}\n\nProjection operator to target state psi.\n\nDefinition\n\nprojector(s) defines the following operator.\n\ns ss\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.ReflectGate","page":"Blocks","title":"YaoBlocks.ReflectGate","text":"ReflectGate{D, T, Tt, AT<:AbstractArrayReg{D, T}} = TimeEvolution{D,Tt,Projector{D,T,AT}}\n\nLet |v⟩ be a quantum state vector, a reflection gate is a unitary operator that defined as the following operation.\n\nv 1 - (1-exp(-iθ)) vv\n\nWhen θ = π, it defines a standard reflection gate 1-2vv.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.RotationGate","page":"Blocks","title":"YaoBlocks.RotationGate","text":"RotationGate{D,T,GT<:AbstractBlock{D}} <: PrimitiveBlock{D}\n\nRotationGate, with GT both hermitian and isreflexive.\n\nDefinition\n\nExpression rot(G, θ) defines the following gate\n\ncos fractheta2I - i sin fractheta2 G\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.ShiftGate","page":"Blocks","title":"YaoBlocks.ShiftGate","text":"ShiftGate <: PrimitiveBlock\n\nPhase shift gate.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.TimeEvolution","page":"Blocks","title":"YaoBlocks.TimeEvolution","text":"TimeEvolution{D, TT, GT} <: PrimitiveBlock{D}\n\nTimeEvolution, where GT is block type. input matrix should be hermitian.\n\nnote: Note\nTimeEvolution contructor check hermicity of the input block by default, but sometimes it can be slow. Turn off the check manually by specifying optional parameter check_hermicity = false.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"@const_gate","category":"page"},{"location":"man/blocks.html#YaoBlocks.ConstGate.@const_gate","page":"Blocks","title":"YaoBlocks.ConstGate.@const_gate","text":"@const_gate = \n@const_gate :: = \n@const_gate ::\n\nThis macro simplify the definition of a constant gate. It will automatically bind the matrix form to a constant which will reduce memory allocation in the runtime.\n\nExamples\n\n@const_gate X = ComplexF64[0 1;1 0]\n\nor\n\n@const_gate X::ComplexF64 = [0 1;1 0]\n\nYou can bind new element types by simply re-declare with a type annotation.\n\n@const_gate X::ComplexF32\n\n\n\n\n\n","category":"macro"},{"location":"man/blocks.html#Composite-Blocks","page":"Blocks","title":"Composite Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Composite blocks are subtypes of CompositeBlock, they are the composition of blocks.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"We provide the following composite blocks:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Modules = [YaoBlocks]\nFilter = t -> t isa Type && t <: YaoBlocks.CompositeBlock","category":"page"},{"location":"man/blocks.html#YaoBlocks.AbstractAdd","page":"Blocks","title":"YaoBlocks.AbstractAdd","text":"AbstractAdd{D} <: CompositeBlock{D}\n\nThe abstract add interface, aimed to support Hamiltonian types.\n\nRequired Interfaces\n\nchsubblocks\nsubblocks\n\nProvides\n\nunsafe_apply! and its backward\nmat and its backward\nadjoint\noccupied_locs\ngetindex over dit strings\nishermitian\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Add","page":"Blocks","title":"YaoBlocks.Add","text":"Add{D} <: AbstractAdd{D}\nAdd(blocks::AbstractBlock...) -> Add\n\nType for block addition.\n\njulia> X + X\nnqubits: 1\n+\n├─ X\n└─ X\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.CachedBlock","page":"Blocks","title":"YaoBlocks.CachedBlock","text":"CachedBlock{ST, BT, D} <: TagBlock{BT, D}\n\nA label type that tags an instance of type BT. It forwards every methods of the block it contains, except mat and apply!, it will cache the matrix form whenever the program has.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.ChainBlock","page":"Blocks","title":"YaoBlocks.ChainBlock","text":"ChainBlock{D} <: CompositeBlock{D}\n\nChainBlock is a basic construct tool to create user defined blocks horizontically. It is a Vector like composite type.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.ControlBlock","page":"Blocks","title":"YaoBlocks.ControlBlock","text":"A control block is a composite block that applies a block when the control qubits are all ones.\n\nnote: Note\nIf control qubit index is negative, it means the inverse control, i.e., the block is applied when the control qubit is zero.\n\nFields\n\nn::Int64\nctrl_locs::NTuple{C, Int64} where C\nctrl_config::NTuple{C, Int64} where C\ncontent::AbstractBlock\nlocs::NTuple{M, Int64} where M\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Daggered","page":"Blocks","title":"YaoBlocks.Daggered","text":"Daggered{BT, D} <: TagBlock{BT,D}\n\nWrapper block allowing to execute the inverse of a block of quantum circuit.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Daggered-Union{Tuple{BT}, Tuple{D}} where {D, BT<:AbstractBlock{D}}","page":"Blocks","title":"YaoBlocks.Daggered","text":"Daggered(block)\n\nCreate a Daggered block. Let G be a input block, G' or Daggered(block) in code represents G^dagger.\n\nExamples\n\nThe inverse QFT is not hermitian, thus it will be tagged with a Daggered block.\n\njulia> A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1))));\n\njulia> B(n, i) = chain(n, i==j ? put(i=>H) : A(j, i) for j in i:n);\n\njulia> qft(n) = chain(B(n, i) for i in 1:n);\n\njulia> struct QFT <: PrimitiveBlock{2} n::Int end\n\njulia> YaoBlocks.nqudits(q::QFT) = q.n\n\n\njulia> circuit(q::QFT) = qft(nqubits(q));\n\njulia> YaoBlocks.mat(x::QFT) = mat(circuit(x));\n\njulia> QFT(2)'\n [†]QFT\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.KronBlock","page":"Blocks","title":"YaoBlocks.KronBlock","text":"KronBlock{D,M,MT<:NTuple{M,Any}} <: CompositeBlock{D}\n\ncomposite block that combine blocks by kronecker product.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.OnLevels","page":"Blocks","title":"YaoBlocks.OnLevels","text":"OnLevels{D, Ds, T <: AbstractBlock{Ds}} <: TagBlock{T, D}\n\nDefine a gate that is applied to a subset of levels.\n\nFields\n\ngate: the gate to be applied.\nlevels: the levels to apply the gate to.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.PSwap","page":"Blocks","title":"YaoBlocks.PSwap","text":"PSwap = PutBlock{2,2,RotationGate{2,T,G}} where {G<:ConstGate.SWAPGate}\nPSwap(n::Int, locs::Tuple{Int,Int}, θ::Real)\n\nParametrized swap gate that swaps two qubits with a phase, defined as\n\nrm SWAP(θ) = e^-iθrm SWAP2\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.PutBlock","page":"Blocks","title":"YaoBlocks.PutBlock","text":"PutBlock{D,C,GT<:AbstractBlock} <: AbstractContainer{GT,D}\n\nType for putting a block at given locations.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.RepeatedBlock","page":"Blocks","title":"YaoBlocks.RepeatedBlock","text":"RepeatedBlock{D,C,GT<:AbstractBlock} <: AbstractContainer{GT,D}\n\nRepeat the same block on given locations.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Scale","page":"Blocks","title":"YaoBlocks.Scale","text":"Scale{S <: Union{Number, Val}, D, BT <: AbstractBlock{D}} <: TagBlock{BT, D}\nScale(factor, block)\n\nMultiply a block with a scalar factor, which can be a number or a Val. If the factor is a number, it is regarded as a parameter that can be changed dynamically. If the factor is a Val, it is regarded as a constant.\n\nExamples\n\njulia> 2 * X\n[scale: 2] X\n\njulia> im * Z\n[+im] Z\n\njulia> -im * Z\n[-im] Z\n\njulia> -Z\n[-] Z\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Subroutine","page":"Blocks","title":"YaoBlocks.Subroutine","text":"Subroutine{D, BT <: AbstractBlock, C} <: AbstractContainer{BT, D}\n\nSubroutine node on given locations. This allows you to shoehorn a smaller circuit to a larger one.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.Swap","page":"Blocks","title":"YaoBlocks.Swap","text":"Swap = PutBlock{2,2,G} where {G<:ConstGate.SWAPGate}\nSwap(n::Int, locs::Tuple{Int,Int})\n\nSwap gate, which swaps two qubits.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#YaoBlocks.UnitaryChannel","page":"Blocks","title":"YaoBlocks.UnitaryChannel","text":"UnitaryChannel{D, W<:AbstractVector} <: CompositeBlock{D}\nUnitaryChannel(operators, probs)\n\nCreate a unitary channel, where probs is a real vector that sum up to 1.\n\n\n\n\n\n","category":"type"},{"location":"man/blocks.html#Operations-on-Blocks","page":"Blocks","title":"Operations on Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"unsafe_apply!\napply!\napply\n\nniparams\ngetiparams\nrender_params\nnparameters\n\noccupied_locs\nprint_block\n\napply_back!\nmat_back!","category":"page"},{"location":"man/blocks.html#YaoAPI.unsafe_apply!","page":"Blocks","title":"YaoAPI.unsafe_apply!","text":"unsafe_apply!(r, block)\n\nSimilar to apply!, but will not check the size of the register and block, this is mainly used for overloading new blocks, use at your own risk.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.apply!","page":"Blocks","title":"YaoAPI.apply!","text":"apply!(register, block)\n\nApply a block (of quantum circuit) to a quantum register.\n\nnote: Note\nto overload apply! for a new block, please overload the unsafe_apply! function with same interface. Then the apply! interface will do the size checks on inputs automatically.\n\nExamples\n\njulia> r = zero_state(2)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/2\n nlevel: 2\n\njulia> apply!(r, put(2, 1=>X))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/2\n nlevel: 2\n\njulia> measure(r;nshots=10)\n10-element Vector{DitStr{2, 2, Int64}}:\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n 01 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.apply","page":"Blocks","title":"YaoBlocks.apply","text":"apply(register, block)\n\nThe non-inplace version of applying a block (of quantum circuit) to a quantum register. Check apply! for the faster inplace version.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.niparams","page":"Blocks","title":"YaoAPI.niparams","text":"niparam(block) -> Int\n\nReturn number of intrinsic parameters in block. See also nparameters.\n\nExamples\n\njulia> niparams(Rx(0.1))\n1\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.getiparams","page":"Blocks","title":"YaoAPI.getiparams","text":"getiparams(block)\n\nReturns the intrinsic parameters of node block, default is an empty tuple.\n\nExamples\n\njulia> getiparams(Rx(0.1))\n0.1\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.render_params","page":"Blocks","title":"YaoAPI.render_params","text":"render_params(r::AbstractBlock, params)\n\nThis function renders the input parameter to a consumable type to r. params can be a number or a symbol like :zero and :random.\n\nExamples\n\njulia> collect(render_params(Rx(0.1), :zero))\n1-element Vector{Float64}:\n 0.0\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.nparameters","page":"Blocks","title":"YaoAPI.nparameters","text":"nparameters(block) -> Int\n\nReturn number of parameters in block. See also niparams.\n\nExamples\n\njulia> nparameters(chain(Rx(0.1), Rz(0.2)))\n2\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.occupied_locs","page":"Blocks","title":"YaoAPI.occupied_locs","text":"occupied_locs(x)\n\nReturn a tuple of occupied locations of x.\n\nExamples\n\njulia> occupied_locs(kron(5, 1=>X, 3=>X))\n(1, 3)\n\njulia> occupied_locs(kron(5, 1=>X, 3=>I2))\n(1,)\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.print_block","page":"Blocks","title":"YaoAPI.print_block","text":"print_block(io, block)\n\nDefine how blocks are printed as text in one line.\n\nExamples\n\njulia> print_block(stdout, X)\nX\n\njulia> print_block(stdout, put(2, 1=>X))\nput on (1)\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.apply_back!","page":"Blocks","title":"YaoAPI.apply_back!","text":"apply_back!((ψ, ∂L/∂ψ*), circuit::AbstractBlock, collector) -> AbstractRegister\n\nback propagate and calculate the gradient ∂L/∂θ = 2Re(∂L/∂ψ⋅∂ψ/∂θ), given ∂L/∂ψ. ψ is the output register, ∂L/∂ψ* should also be register type.\n\nNote: gradients are stored in Diff blocks, it can be access by either diffblock.grad or gradient(circuit). Note2: now apply_back! returns the inversed gradient!\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.mat_back!","page":"Blocks","title":"YaoAPI.mat_back!","text":"mat_back!(T, rb::AbstractBlock, adjy, collector)\n\nBack propagate the matrix gradients.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#Error-and-Exceptions","page":"Blocks","title":"Error and Exceptions","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Modules = [YaoBlocks]\nPages = [\"error.jl\"]","category":"page"},{"location":"man/blocks.html#Extending-Blocks","page":"Blocks","title":"Extending Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Blocks are defined as a sub-type system inside Julia, you could extend it by defining new Julia types by subtyping abstract types we provide. But we also provide some handy tools to help you create your own blocks.","category":"page"},{"location":"man/blocks.html#Define-Custom-Constant-Blocks","page":"Blocks","title":"Define Custom Constant Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Constant blocks are used quite often and in numerical simulation we would expect it to be a real constant in the program, which means it won't allocate new memory when we try to get its matrix for several times, and it won't change with parameters.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"In Yao, you can simply define a constant block with @const_gate, with the corresponding matrix:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"using YaoBlocks, BitBasis # hide\n@const_gate Rand = rand(ComplexF64, 4, 4)","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"This will automatically create a type RandGate{T} and a constant binding Rand to the instance of RandGate{ComplexF64}, and it will also bind a Julia constant for the given matrix, so when you call mat(Rand), no allocation will happen.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"@allocated mat(Rand)","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"If you want to use other data type like ComplexF32, you could directly call Rand(ComplexF32), which will create a new instance with data type ComplexF32.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Rand(ComplexF32)","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"But remember this won't bind the matrix, it only binds the matrix you give","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"@allocated mat(Rand(ComplexF32))","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"so if you want to make the matrix call mat for ComplexF32 to have zero allocation as well, you need to do it explicitly.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"@const_gate Rand::ComplexF32","category":"page"},{"location":"man/blocks.html#Define-Custom-Blocks","page":"Blocks","title":"Define Custom Blocks","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Primitive blocks are the most basic block to build a quantum circuit, if a primitive block has a certain structure, like containing tweakable parameters, it cannot be defined as a constant, thus create a new type by subtyping PrimitiveBlock is necessary","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"using YaoBlocks\n\nmutable struct PhaseGate{T <: Real} <: PrimitiveBlock{1}\n theta::T\nend","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"If your insterested block is a composition of other blocks, you should define a CompositeBlock, e.g","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"struct ChainBlock{N} <: CompositeBlock{N}\n blocks::Vector{AbstractBlock{N}}\nend","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Besides types, there are several interfaces you could define for a block, but don't worry, they should just error if it doesn't work.","category":"page"},{"location":"man/blocks.html#Define-the-matrix","page":"Blocks","title":"Define the matrix","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"The matrix form of a block is the minimal requirement to make a custom block functional, defining it is super simple, e.g for phase gate:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"mat(::Type{T}, gate::PhaseGate) where T = exp(T(im * gate.theta)) * Matrix{Complex{T}}(I, 2, 2)","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Or for composite blocks, you could just calculate the matrix by call mat on its subblocks.","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"mat(::Type{T}, c::ChainBlock) where T = prod(x->mat(T, x), reverse(c.blocks))","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"The rest will just work, but might be slow since you didn't define any specification for this certain block.","category":"page"},{"location":"man/blocks.html#Define-how-blocks-are-applied-to-registers","page":"Blocks","title":"Define how blocks are applied to registers","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Although, having its matrix is already enough for applying a block to register, we could improve the performance or dispatch to other actions by overloading apply! interface, e.g we can use specialized instruction to make X gate (a builtin gate defined @const_gate) faster:","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"function apply!(r::ArrayReg, x::XGate)\n nactive(r) == 1 || throw(QubitMismatchError(\"register size $(nactive(r)) mismatch with block size $N\"))\n instruct!(matvec(r.state), Val(:X), (1, ))\n return r\nend","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"In Yao, this interface allows us to provide more aggressive specialization on different patterns of quantum circuits to accelerate the simulation etc.","category":"page"},{"location":"man/blocks.html#Define-Parameters","page":"Blocks","title":"Define Parameters","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"If you want to use some member of the block to be parameters, you need to declare them explicitly","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"niparams(::Type{<:PhaseGate}) = 1\ngetiparams(x::PhaseGate) = x.theta\nsetiparams!(r::PhaseGate, param::Real) = (r.theta = param; r)","category":"page"},{"location":"man/blocks.html#Define-Adjoint","page":"Blocks","title":"Define Adjoint","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Since blocks are actually quantum operators, it makes sense to call their adjoint as well. We provide Daggered for general purpose, but some blocks may have more specific transformation rules for adjoints, e.g","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Base.adjoint(x::PhaseGate) = PhaseGate(-x.theta)","category":"page"},{"location":"man/blocks.html#Define-Cache-Keys","page":"Blocks","title":"Define Cache Keys","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"To enable cache, you should define cache_key, e.g for phase gate, we only cares about its phase, instead of the whole instance","category":"page"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"cache_key(gate::PhaseGate) = gate.theta","category":"page"},{"location":"man/blocks.html#APIs","page":"Blocks","title":"APIs","text":"","category":"section"},{"location":"man/blocks.html","page":"Blocks","title":"Blocks","text":"Modules = [YaoBlocks]\nOrder = [:function, :macro]","category":"page"},{"location":"man/blocks.html#Base.:|>-Tuple{AbstractRegister, AbstractBlock}","page":"Blocks","title":"Base.:|>","text":"|>(register, circuit) -> register\n\nApply a quantum circuits to register, which modifies the register directly.\n\nExample\n\njulia> arrayreg(bit\"0\") |> X |> Y\n\nwarning: Warning\n|> is equivalent to apply!, which means it has side effects. You need to use apply if you do not want to change it in-place.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.kron-Tuple{Int64, Vararg{Pair{<:Any, <:AbstractBlock}}}","page":"Blocks","title":"Base.kron","text":"kron(n, locs_and_blocks::Pair{<:Any, <:AbstractBlock}...) -> KronBlock\n\nReturns a n-qudit KronBlock. The inputs contains a list of location-block pairs, where a location can be an integer or a range. It is conceptually a chain of put block without address conflicts, but it has a richer type information that can be useful for various purposes such as more efficient mat function.\n\nLet I be a 2times 2 identity matrix, G and H be two 2times 2 matrix, the matrix representation of kron(n, i=>G, j=>H) (assume j i) is defined as\n\nI^otimes n-j otimes H otimes I^otimes j-i-1 otimes G otimes I^i-1\n\nFor multiple locations, the expression can be complicated.\n\nExamples\n\nUse kron to construct a KronBlock, it will put an X gate on the 1st qubit, and a Y gate on the 3rd qubit.\n\njulia> kron(4, 1=>X, 3=>Y)\nnqubits: 4\nkron\n├─ 1=>X\n└─ 3=>Y\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.kron-Tuple{Vararg{AbstractBlock}}","page":"Blocks","title":"Base.kron","text":"kron(blocks::AbstractBlock...)\nkron(n, itr)\n\nReturn a KronBlock, with total number of qubits n, and blocks should use all the locations on n wires in quantum circuits.\n\nExamples\n\nYou can use kronecker product to composite small blocks to a large blocks.\n\njulia> kron(X, Y, Z, Z)\nnqubits: 4\nkron\n├─ 1=>X\n├─ 2=>Y\n├─ 3=>Z\n└─ 4=>Z\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.kron-Tuple{Vararg{Pair{<:Any, <:AbstractBlock}}}","page":"Blocks","title":"Base.kron","text":"kron(blocks...) -> f(n)\nkron(itr) -> f(n)\n\nReturn a lambda, which will take the total number of qubits as input.\n\nExamples\n\nIf you don't know the number of qubit yet, or you are just too lazy, it is fine.\n\njulia> kron(put(1=>X) for _ in 1:2)\n(n -> kron(n, ((n -> put(n, 1 => X)), (n -> put(n, 1 => X)))...))\n\njulia> kron(X for _ in 1:2)\nnqubits: 2\nkron\n├─ 1=>X\n└─ 2=>X\n\njulia> kron(1=>X, 3=>Y)\n(n -> kron(n, (1 => X, 3 => Y)...))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.repeat-Tuple{AbstractBlock, Any}","page":"Blocks","title":"Base.repeat","text":"repeat(x::AbstractBlock, locs)\n\nLazy curried version of repeat.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#Base.repeat-Tuple{Int64, AbstractBlock, Vararg{Int64}}","page":"Blocks","title":"Base.repeat","text":"repeat(n, subblock::AbstractBlock[, locs]) -> RepeatedBlock{n}\n\nCreate a n-qudit RepeatedBlock block, which is conceptually a [kron] block with all gates being the same. If locs is provided, repeat on locs, otherwise repeat on all locations. Let G be a 2times 2 matrix, the matrix representation of repeat(n, X) is\n\nX^otimes n\n\nThe RepeatedBlock can be used to accelerate repeated applying certain gate types: X, Y, Z, S, T, Sdag, and Tdag.\n\nExamples\n\nThis will create a repeat block which puts 4 X gates on each location.\n\njulia> repeat(4, X)\nnqubits: 4\nrepeat on (1, 2, 3, 4)\n└─ X\n\nYou can also specify the location\n\njulia> repeat(4, X, (1, 2))\nnqubits: 4\nrepeat on (1, 2)\n└─ X\n\nBut repeat won't copy the gate, thus, if it is a gate with parameter, e.g a phase(0.1), the parameter will change simultaneously.\n\njulia> g = repeat(4, phase(0.1))\nnqubits: 4\nrepeat on (1, 2, 3, 4)\n└─ phase(0.1)\n\njulia> g.content\nphase(0.1)\n\njulia> g.content.theta = 0.2\n0.2\n\njulia> g\nnqubits: 4\nrepeat on (1, 2, 3, 4)\n└─ phase(0.2)\n\nRepeat over certain gates will provide speed up.\n\njulia> reg = rand_state(20);\n\njulia> @time apply!(reg, repeat(20, X));\n 0.002252 seconds (5 allocations: 656 bytes)\n\njulia> @time apply!(reg, chain([put(20, i=>X) for i=1:20]));\n 0.049362 seconds (82.48 k allocations: 4.694 MiB, 47.11% compilation time)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#LinearAlgebra.ishermitian-Tuple{Any}","page":"Blocks","title":"LinearAlgebra.ishermitian","text":"ishermitian(op::AbstractBlock) -> Bool\n\nReturns true if op is hermitian.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.chcontent-Tuple{AbstractContainer, Any}","page":"Blocks","title":"YaoAPI.chcontent","text":"chcontent(x, blk)\n\nCreate a similar block of x and change its content to blk.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.chsubblocks-Tuple{AbstractBlock, Any}","page":"Blocks","title":"YaoAPI.chsubblocks","text":"chsubblocks(composite_block, itr)\n\nChange the sub-blocks of a CompositeBlock with given iterator itr.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.content-Tuple{AbstractContainer}","page":"Blocks","title":"YaoAPI.content","text":"content(x)\n\nReturns the content of x.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.dispatch!-Tuple{Union{Nothing, Function}, AbstractBlock, Any}","page":"Blocks","title":"YaoAPI.dispatch!","text":"dispatch!(x::AbstractBlock, collection)\n\nDispatch parameters in collection to block tree x.\n\nnote: Note\nit will try to dispatch the parameters in collection first.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.expect-Tuple{AbstractBlock, AbstractRegister}","page":"Blocks","title":"YaoAPI.expect","text":"expect(op::AbstractBlock, reg) -> Real\nexpect(op::AbstractBlock, reg => circuit) -> Real\nexpect(op::AbstractBlock, density_matrix) -> Real\n\nGet the expectation value of an operator, the second parameter can be a register reg or a pair of input register and circuit reg => circuit.\n\nexpect'(op::AbstractBlock, reg=>circuit) -> Pair expect'(op::AbstractBlock, reg) -> AbstracRegister\n\nObtain the gradient with respect to registers and circuit parameters. For pair input, the second return value is a pair of gψ=>gparams, with gψ the gradient of input state and gparams the gradients of circuit parameters. For register input, the return value is a register.\n\nnote: Note\nFor batched register, expect(op, reg=>circuit) returns a vector of size number of batch as output. However, one can not differentiate over a vector loss, so expect'(op, reg=>circuit) accumulates the gradient over batch, rather than returning a batched gradient of parameters.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.getiparams-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.getiparams","text":"getiparams(block)\n\nReturns the intrinsic parameters of node block, default is an empty tuple.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.iparams_eltype-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.iparams_eltype","text":"iparams_eltype(block)\n\nReturn the element type of getiparams.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.mat-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.mat","text":"mat([T=ComplexF64], blk)\n\nReturns the matrix form of given block.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.mat-Tuple{GeneralMatrixBlock}","page":"Blocks","title":"YaoAPI.mat","text":"mat(A::GeneralMatrixBlock)\n\nReturn the matrix of general matrix block.\n\nwarn: Warn\nInstead of converting it to the default data type ComplexF64, this will return its contained matrix.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.operator_fidelity-Tuple{AbstractBlock, AbstractBlock}","page":"Blocks","title":"YaoAPI.operator_fidelity","text":"operator_fidelity(b1::AbstractBlock, b2::AbstractBlock) -> Number\n\nOperator fidelity defined as\n\nF^2 = frac1dleftrm Tr(b1^dagger b2)right\n\nHere, d is the size of the Hilbert space. Note this quantity is independant to global phase. See arXiv: 0803.2940v2, Equation (2) for reference.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.parameters-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.parameters","text":"parameters(block)\n\nReturns all the parameters contained in block tree with given root block.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.parameters_eltype-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.parameters_eltype","text":"parameters_eltype(x)\n\nReturn the element type of parameters.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoAPI.setiparams!","page":"Blocks","title":"YaoAPI.setiparams!","text":"setiparams!([f], block, itr)\nsetiparams!([f], block, params...)\n\nSet the parameters of block. When f is provided, set parameters of block to the value in collection mapped by f. iter can be an iterator or a symbol, the symbol can be :zero, :random.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoAPI.subblocks-Tuple{AbstractBlock}","page":"Blocks","title":"YaoAPI.subblocks","text":"subblocks(x)\n\nReturns an iterator of the sub-blocks of a composite block. Default is empty.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.Rx-Tuple{Any}","page":"Blocks","title":"YaoBlocks.Rx","text":"Rx(theta)\n\nReturn a RotationGate on X axis.\n\nExample\n\njulia> Rx(0.1)\nrot(X, 0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.Ry-Tuple{Any}","page":"Blocks","title":"YaoBlocks.Ry","text":"Ry(theta)\n\nReturn a RotationGate on Y axis.\n\nExample\n\njulia> Ry(0.1)\nrot(Y, 0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.Rz-Tuple{Any}","page":"Blocks","title":"YaoBlocks.Rz","text":"Rz(theta)\n\nReturn a RotationGate on Z axis.\n\nExample\n\njulia> Rz(0.1)\nrot(Z, 0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.apply-Union{Tuple{D}, Tuple{AbstractRegister{D}, Any}} where D","page":"Blocks","title":"YaoBlocks.apply","text":"apply(register, block)\n\nThe non-inplace version of applying a block (of quantum circuit) to a quantum register. Check apply! for the faster inplace version.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.applymatrix-Tuple{Any, AbstractBlock}","page":"Blocks","title":"YaoBlocks.applymatrix","text":"applymatrix(g::AbstractBlock) -> Matrix\n\nTransform the apply! function of specific block to dense matrix.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.bit_flip_channel-Tuple{Real}","page":"Blocks","title":"YaoBlocks.bit_flip_channel","text":"bit_flip_channel(p::Real)\n\nCreate a bit flip channel as a UnitaryChannel.\n\n(1-p)ρ + pXρX\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cache","page":"Blocks","title":"YaoBlocks.cache","text":"cache(x[, level=1; recursive=false])\n\nCreate a CachedBlock with given block x, which will cache the matrix of x for the first time it calls mat, and use the cached matrix in the following calculations.\n\nExamples\n\njulia> cache(control(3, 1, 2=>X))\nnqubits: 3\n[cached] control(1)\n └─ (2,) X\n\n\njulia> chain(cache(control(3, 1, 2=>X)), repeat(H))\nnqubits: 3\nchain\n└─ [cached] control(1)\n └─ (2,) X\n\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.cache_key-Tuple{AbstractBlock}","page":"Blocks","title":"YaoBlocks.cache_key","text":"cache_key(block)\n\nReturns the key that identify the matrix cache of this block. By default, we use the returns of parameters as its key.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cache_type-Tuple{Type{<:AbstractBlock}}","page":"Blocks","title":"YaoBlocks.cache_type","text":"cache_type(::Type) -> DataType\n\nReturn the element type that a CacheFragment will use.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.chain-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.chain","text":"chain(n)\n\nReturn an empty ChainBlock which can be used like a list of blocks.\n\nExamples\n\njulia> chain(2)\nnqubits: 2\nchain\n\n\njulia> chain(2; nlevel=3)\nnqudits: 2\nchain\n\n\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.chain-Tuple{}","page":"Blocks","title":"YaoBlocks.chain","text":"chain()\n\nReturn an lambda n->chain(n).\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.chain-Union{Tuple{Vararg{AbstractBlock{D}}}, Tuple{D}} where D","page":"Blocks","title":"YaoBlocks.chain","text":"chain(blocks...) -> ChainBlock\nchain(n) -> ChainBlock\n\nReturn a ChainBlock which chains a list of blocks with the same number of qudits. Let G_i be a sequence of n-qudit blocks, the matrix representation of block chain(G_1, G_2, ..., G_m) is\n\nG_m G_m-1ldots G_1\n\nIt is almost equivalent to matrix multiplication except the order is reversed. We make its order different from regular matrix multiplication because quantum circuits can be represented more naturally in this form.\n\nExamples\n\njulia> chain(X, Y, Z)\nnqubits: 1\nchain\n├─ X\n├─ Y\n└─ Z\n\njulia> chain(2, put(1=>X), put(2=>Y), cnot(2, 1))\nnqubits: 2\nchain\n├─ put on (1)\n│ └─ X\n├─ put on (2)\n│ └─ Y\n└─ control(2)\n └─ (1,) X\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.chmeasureoperator-Union{Tuple{D}, Tuple{Measure{D, K} where K, AbstractBlock}} where D","page":"Blocks","title":"YaoBlocks.chmeasureoperator","text":"chmeasureoperator(m::Measure, op::AbstractBlock)\n\nchange the measuring operator. It will also discard existing measuring results.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cleanup-Tuple{EntryTable}","page":"Blocks","title":"YaoBlocks.cleanup","text":"cleanup(entries::EntryTable; zero_threshold=0.0)\n\nClean up the entry table by 1) sort entries, 2) merge items and 3) clean up zeros. Any value with amplitude ≤ zero_threshold will be regarded as zero.\n\njulia> et = EntryTable([bit\"000\",bit\"011\",bit\"101\",bit\"101\",bit\"011\",bit\"110\",bit\"110\",bit\"011\",], [1.0 + 0.0im,-1, 1,1,1,-1,1,1,-1])\nEntryTable{DitStr{2, 3, Int64}, ComplexF64}:\n 000 ₍₂₎ 1.0 + 0.0im\n 011 ₍₂₎ -1.0 + 0.0im\n 101 ₍₂₎ 1.0 + 0.0im\n 101 ₍₂₎ 1.0 + 0.0im\n 011 ₍₂₎ 1.0 + 0.0im\n 110 ₍₂₎ -1.0 + 0.0im\n 110 ₍₂₎ 1.0 + 0.0im\n 011 ₍₂₎ 1.0 + 0.0im\n\n\njulia> cleanup(et)\nEntryTable{DitStr{2, 3, Int64}, ComplexF64}:\n 000 ₍₂₎ 1.0 + 0.0im\n 011 ₍₂₎ 1.0 + 0.0im\n 101 ₍₂₎ 2.0 + 0.0im\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cnot-Tuple{Int64, Any, Int64}","page":"Blocks","title":"YaoBlocks.cnot","text":"cnot([n, ]ctrl_locs, location)\n\nReturn a speical ControlBlock, aka CNOT gate with number of active qubits n and locs of control qubits ctrl_locs, and location of X gate.\n\nExamples\n\njulia> cnot(3, (2, 3), 1)\nnqubits: 3\ncontrol(2, 3)\n└─ (1,) X\n\njulia> cnot(2, 1)\n(n -> cnot(n, 2, 1))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.collect_blocks-Union{Tuple{T}, Tuple{Type{T}, AbstractBlock}} where T<:AbstractBlock","page":"Blocks","title":"YaoBlocks.collect_blocks","text":"collect_blocks(block_type, root)\n\nReturn a ChainBlock with all block of block_type in root.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.control-Tuple{Any, Pair}","page":"Blocks","title":"YaoBlocks.control","text":"control(ctrl_locs, target) -> f(n)\n\nReturn a lambda that takes the number of total active qubits as input. See also control.\n\nExamples\n\njulia> control((2, 3), 1=>X)\n(n -> control(n, (2, 3), 1 => X))\n\njulia> control(2, 1=>X)\n(n -> control(n, 2, 1 => X))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.control-Tuple{Int64, Any, Pair}","page":"Blocks","title":"YaoBlocks.control","text":"control(n, ctrl_locs, locations => subblock)\n\nReturn a n-qubit ControlBlock, where the control locations ctrl_locs and the subblock locations in the third argument can be an integer, a tuple or a range, and the size of the subblock should match the length of locations. Let I be the 2 times 2 identity matrix, G be a 2 times 2 subblock, P_0=0ranglelangle 0 and P_1=1ranglelangle 1 be two single qubit projection operators to subspace 0rangle and 1rangle, i and j be two integers that ij. The matrix representation of control(n, i, j=>G) is\n\nbeginalign\nI^otimes n-i P_0 otimes I^otimes i-j-1 otimes Iotimes I^otimes j-1\n+\n I^otimes n-i P_1 otimes I^otimes i-j-1 otimes Gotimes I^otimes j-1\nendalign\n\nThe multi-controlled multi-qubit controlled block is more complicated, it means apply the gate when control qubits are all ones. Each control location can take a negative sign to represent the inverse control, meaning only when this qubit is 0, the controlled gate is applied.\n\nExamples\n\njulia> control(4, (1, 2), 3=>X)\nnqubits: 4\ncontrol(1, 2)\n└─ (3,) X\n\njulia> control(4, 1, 3=>X)\nnqubits: 4\ncontrol(1)\n└─ (3,) X\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.cunmat","page":"Blocks","title":"YaoBlocks.cunmat","text":"cunmat(nbit::Int, cbits::NTuple{C, Int}, cvals::NTuple{C, Int}, U0::AbstractMatrix, locs::NTuple{M, Int}) where {C, M} -> AbstractMatrix\n\ncontrol-unitary matrix\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.cz-Tuple{Int64, Any, Int64}","page":"Blocks","title":"YaoBlocks.cz","text":"cz([n, ]ctrl_locs, location)\n\nReturn a special ControlBlock, aka CZ gate with number of active qubits n and locs of control qubits ctrl_locs, and location of Z gate. See also cnot.\n\nExamples\n\njulia> cz(2, 1, 2)\nnqubits: 2\ncontrol(1)\n└─ (2,) Z\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.decode_sign-Union{Tuple{NTuple{N, Int64}}, Tuple{N}} where N","page":"Blocks","title":"YaoBlocks.decode_sign","text":"decode_sign(ctrls...)\n\nDecode signs into control sequence on control or inversed control.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.depolarizing_channel-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.depolarizing_channel","text":"depolarizing_channel(n::Int; p::Real)\n\nCreate a global depolarizing channel.\n\nArguments\n\nn: number of qubits.\n\nKeyword Arguments\n\np: probability of this error to occur.\n\nSee also\n\nsingle_qubit_depolarizing_channel and two_qubit_depolarizing_channel for depolarizing channels acting on only one or two qubits.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.dispatch-Tuple{Union{Nothing, Function}, AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.dispatch","text":"dispatch(x::AbstractBlock, collection)\n\nDispatch parameters in collection to block tree x, the generic non-inplace version.\n\nnote: Note\nit will try to dispatch the parameters in collection first.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.dump_gate","page":"Blocks","title":"YaoBlocks.dump_gate","text":"dump_gate(blk::AbstractBlock) -> Expr\n\nconvert a gate to a YaoScript expression for serization. The fallback is GateTypeName(fields...)\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.eigenbasis-Union{Tuple{AbstractBlock{D}}, Tuple{D}} where D","page":"Blocks","title":"YaoBlocks.eigenbasis","text":"eigenbasis(op::AbstractBlock)\n\nReturn the eigenvalue and eigenvectors of target operator. By applying eigenvector' to target state, one can swith the basis to the eigenbasis of this operator. However, eigenvalues does not have a specific form.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.gate_expr-Union{Tuple{G}, Tuple{Val{G}, Any, Any}} where G","page":"Blocks","title":"YaoBlocks.gate_expr","text":"gate_expr(::Val{G}, args, info)\n\nObtain the gate constructior from its YaoScript expression. G is a symbol for the gate type, the default constructor is G(args...). info contains the informations about the number of qubit and Yao version.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.getcol-Tuple{LuxurySparse.SDSparseMatrixCSC, Int64}","page":"Blocks","title":"YaoBlocks.getcol","text":"getcol(csc::SDparseMatrixCSC, icol::Int) -> (View, View)\n\nget specific col of a CSC matrix, returns a slice of (rowval, nzval)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.igate-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.igate","text":"igate(n::Int; nlevel=2)\n\nThe constructor for IdentityGate. Let I_d be a d times d identity matrix, igate(n; nlevel=d) is defined as I_d^otimes n.\n\nExamples\n\njulia> igate(2)\nigate(2)\n\njulia> igate(2; nlevel=3)\nigate(2;nlevel=3)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.isclean-Tuple{EntryTable}","page":"Blocks","title":"YaoBlocks.isclean","text":"isclean(entries::EntryTable; zero_threshold=0.0)\n\nReturn true if the entries are ordered, unique and amplitudes are nonzero. Any value with amplitude ≤ zero_threshold will be regarded as zero.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.map_address","page":"Blocks","title":"YaoBlocks.map_address","text":"map_address(block::AbstractBlock, info::AddressInfo) -> AbstractBlock\n\nmap the locations in block to target locations.\n\nExample\n\nmap_address can be used to embed a sub-circuit to a larger one.\n\njulia> c = chain(5, repeat(H, 1:5), put(2=>X), kron(1=>X, 3=>Y))\nnqubits: 5\nchain\n├─ repeat on (1, 2, 3, 4, 5)\n│ └─ H\n├─ put on (2)\n│ └─ X\n└─ kron\n ├─ 1=>X\n └─ 3=>Y\n\n\njulia> map_address(c, AddressInfo(10, [6,7,8,9,10]))\nnqubits: 10\nchain\n├─ repeat on (6, 7, 8, 9, 10)\n│ └─ H\n├─ put on (7)\n│ └─ X\n└─ kron\n ├─ 6=>X\n └─ 8=>Y\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.matblock-Tuple{AbstractMatrix}","page":"Blocks","title":"YaoBlocks.matblock","text":"matblock(mat_or_block; nlevel=2, tag=\"matblock(...)\")\n\nCreate a GeneralMatrixBlock with a matrix m.\n\nExamples\n\njulia> matblock(ComplexF64[0 1;1 0])\nmatblock(...)\n\n!!!warn\n\nInstead of converting it to the default data type `ComplexF64`,\nthis will return its contained matrix when calling `mat`.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.num_nonzero","page":"Blocks","title":"YaoBlocks.num_nonzero","text":"num_nonzero(nbits, nctrls, U, [N])\n\nReturn number of nonzero entries of the matrix form of control-U gate. nbits is the number of qubits, and nctrls is the number of control qubits.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.parameters!-Tuple{Any, AbstractBlock}","page":"Blocks","title":"YaoBlocks.parameters!","text":"parameters!(out, block)\n\nAppend all the parameters contained in block tree with given root block to out.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.parameters_range-Tuple{AbstractBlock}","page":"Blocks","title":"YaoBlocks.parameters_range","text":"parameters_range(block)\n\nReturn the range of real parameters present in block.\n\nnote: Note\nIt may not be the case that length(parameters_range(block)) == nparameters(block).\n\nExample\n\njulia> YaoBlocks.parameters_range(RotationGate(X, 0.1))\n1-element Vector{Tuple{Float64, Float64}}:\n (0.0, 6.283185307179586)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.parse_block","page":"Blocks","title":"YaoBlocks.parse_block","text":"parse_block(n, ex)\n\nThis function parse the julia object ex to a quantum block, it defines the syntax of high level interfaces. ex can be a function takes number of qubits n as input or it can be a pair.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.pauli_error_channel-Tuple{}","page":"Blocks","title":"YaoBlocks.pauli_error_channel","text":"pauli_error_channel(; px::Real, py::Real=px, pz::Real=px)\n\nCreate the Pauli error channel as a UnitaryChannel\n\n (1 - (p_x + p_y + p_z))ρ + p_xXρX + p_yYρY + p_zZρZ\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.phase-Tuple{Real}","page":"Blocks","title":"YaoBlocks.phase","text":"phase(theta)\n\nReturns a global phase gate. Defined with following matrix form:\n\ne^iθ I\n\nExamples\n\nYou can create a global phase gate with a phase (a real number).\n\njulia> phase(0.1)\nphase(0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.phase_flip_channel-Tuple{Real}","page":"Blocks","title":"YaoBlocks.phase_flip_channel","text":"phase_flip_channel(::Real)\n\nCreate a phase flip channel as UnitaryChannel.\n\n(1-p)ρ + pZρZ\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.popdispatch!-Tuple{AbstractBlock, Vector}","page":"Blocks","title":"YaoBlocks.popdispatch!","text":"popdispatch!(block, list)\n\nPop the first nparameters parameters of list, then dispatch them to the block tree block. See also dispatch!.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.popdispatch!-Tuple{Function, AbstractBlock, Vector}","page":"Blocks","title":"YaoBlocks.popdispatch!","text":"popdispatch!(f, block, list)\n\nPop the first nparameters parameters of list, map them with a function f, then dispatch them to the block tree block. See also dispatch!.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.postwalk-Tuple{Union{Function, Type}, AbstractBlock}","page":"Blocks","title":"YaoBlocks.postwalk","text":"postwalk(f, src::AbstractBlock)\n\nWalk the tree and call f after the children are visited.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.prewalk-Tuple{Union{Function, Type}, AbstractBlock}","page":"Blocks","title":"YaoBlocks.prewalk","text":"prewalk(f, src::AbstractBlock)\n\nWalk the tree and call f once the node is visited.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.print_annotation-Tuple{IO, Vararg{Any, 4}}","page":"Blocks","title":"YaoBlocks.print_annotation","text":"print_annotation(io, root, node, child, k)\n\nPrint the annotation of k-th child of node, aka the k-th element of subblocks(node).\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.print_prefix-Tuple{IO, Any, Any, Any}","page":"Blocks","title":"YaoBlocks.print_prefix","text":"print_prefix(io, depth, charset, active_levels)\n\nprint prefix of a tree node in a single line.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.print_subtypetree","page":"Blocks","title":"YaoBlocks.print_subtypetree","text":"print_subtypetree(::Type[, level=1, indent=4])\n\nPrint subtype tree, level specify the depth of the tree.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.print_title-Tuple{IO, AbstractBlock}","page":"Blocks","title":"YaoBlocks.print_title","text":"print_title(io, block)\n\nPrint the title of given block of an AbstractBlock.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.print_tree","page":"Blocks","title":"YaoBlocks.print_tree","text":"print_tree(io, root, node[, depth=1, active_levels=()]; kwargs...)\n\nPrint the block tree.\n\nKeywords\n\nmaxdepth: max tree depth to print\ncharset: default is ('├','└','│','─'). See also YaoBlocks.BlockTreeCharSet.\ntitle: control whether to print the title, true or false, default is true\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.print_tree-Tuple{Any}","page":"Blocks","title":"YaoBlocks.print_tree","text":"print_tree([io=stdout], root)\n\nPrint the block tree.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.projection-Tuple{AbstractMatrix, AbstractMatrix}","page":"Blocks","title":"YaoBlocks.projection","text":"projection(y::AbstractMatrix, op::AbstractMatrix) -> typeof(y)\n\nProject op to sparse matrix with same sparsity as y.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.projector-Tuple{AbstractArrayReg}","page":"Blocks","title":"YaoBlocks.projector","text":"projector(v::AbstractArrayReg) -> Projector\n\n\nCreate a Projector with an quantum state vector v.\n\nExample\n\njulia> projector(rand_state(3))\n|s⟩⟨s|, nqudits = 3\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.projector-Tuple{Any}","page":"Blocks","title":"YaoBlocks.projector","text":"projector(x)\n\nReturn projector on 0 or projector on 1.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.pswap-Tuple{Int64, Int64, Int64, Real}","page":"Blocks","title":"YaoBlocks.pswap","text":"pswap(n::Int, i::Int, j::Int, α::Real)\npswap(i::Int, j::Int, α::Real) -> f(n)\n\nparametrized swap gate.\n\nExamples\n\njulia> pswap(2, 1, 2, 0.1)\nnqubits: 2\nput on (1, 2)\n└─ rot(SWAP, 0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.put-Tuple{Pair}","page":"Blocks","title":"YaoBlocks.put","text":"put(pair) -> f(n)\n\nLazy curried version of put.\n\nExamples\n\njulia> put(1=>X)\n(n -> put(n, 1 => X))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.put-Union{Tuple{M}, Tuple{Int64, Pair{NTuple{M, Int64}, <:AbstractBlock}}} where M","page":"Blocks","title":"YaoBlocks.put","text":"put(n::Int, locations => subblock) => PutBlock\n\nCreate a n-qudit PutBlock. The second argument is a pair of locations and subblock, where the locations can be a tuple, an integer or a range and the subblock size should match the length of locations. Let I be a 2times 2 identity matrix and G be a 2times 2 matrix, the matrix representation of put(n, i=>G) is defined as\n\nI^otimes n-i otimes G otimes I^otimes i-1\n\nFor multiple locations, the expression can be complicated, which corresponds to the matrix representation of multi-qubit gate applied on n-qubit space in quantum computing.\n\nExamples\n\njulia> put(4, 1=>X)\nnqubits: 4\nput on (1)\n└─ X\n\nIf you want to put a multi-qubit gate on specific locations, you need to write down all possible locations.\n\njulia> put(4, (1, 3)=>kron(X, Y))\nnqubits: 4\nput on (1, 3)\n└─ kron\n ├─ 1=>X\n └─ 2=>Y\n\nThe outter locations creates a scope which make it seems to be a contiguous two qubits for the block inside PutBlock.\n\ntips: Tips\nIt is better to use subroutine instead of put for large blocks, since put will use the matrix of its contents directly instead of making use of what's in it. put is more efficient for small blocks.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.rand_hermitian-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.rand_hermitian","text":"rand_hermitian([T=ComplexF64], N::Int) -> Matrix\n\nCreate a random hermitian matrix.\n\njulia> ishermitian(rand_hermitian(2))\ntrue\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.rand_unitary-Tuple{Int64}","page":"Blocks","title":"YaoBlocks.rand_unitary","text":"rand_unitary([T=ComplexF64], N::Int) -> Matrix\n\nCreate a random unitary matrix.\n\nExamples\n\njulia> isunitary(rand_unitary(2))\ntrue\n\njulia> eltype(rand_unitary(ComplexF32, 2))\nComplexF32 (alias for Complex{Float32})\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.reflect","page":"Blocks","title":"YaoBlocks.reflect","text":"reflect(\n v::AbstractArrayReg\n) -> ReflectGate{D, T, Irrational{:π}, AT} where {D, T, AT<:(AbstractArrayReg{D, T})}\nreflect(\n v::AbstractArrayReg,\n θ::Real\n) -> ReflectGate{_A, T, Tt, AT} where {_A, Tt<:Real, T, AT<:(AbstractArrayReg{_A, T})}\n\n\nCreate a ReflectGate with respect to an quantum state vector v.\n\nExample\n\njulia> reflect(rand_state(3))\nTime Evolution Δt = π, tol = 1.0e-7\n|s⟩⟨s|, nqudits = 3\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.rmlines-Tuple{Expr}","page":"Blocks","title":"YaoBlocks.rmlines","text":"rmlines(ex)\n\nRemove LineNumberNode from an Expr.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.rot-Tuple{AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.rot","text":"rot(U, theta)\n\nReturn a RotationGate on U axis.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.sandwich-Tuple{AbstractArrayReg, AbstractBlock, AbstractArrayReg}","page":"Blocks","title":"YaoBlocks.sandwich","text":"sandwich(bra::AbstractRegister, op::AbstractBlock, ket::AbstracRegister) -> Complex\n\nCompute the sandwich function ⟨bra|op|ket⟩.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.setcol!-Tuple{SparseMatrixCSC, Int64, AbstractVector, Any}","page":"Blocks","title":"YaoBlocks.setcol!","text":"setcol!(csc::SparseMatrixCSC, icol::Int, rowval::AbstractVector, nzval) -> SparseMatrixCSC\n\nset specific col of a CSC matrix\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.setiparams","page":"Blocks","title":"YaoBlocks.setiparams","text":"setiparams([f], block, itr)\nsetiparams([f], block, params...)\n\nSet the parameters of block, the non-inplace version. When f is provided, set parameters of block to the value in collection mapped by f. iter can be an iterator or a symbol, the symbol can be :zero, :random.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.shift-Tuple{Any}","page":"Blocks","title":"YaoBlocks.shift","text":"shift(θ)\n\nCreate a ShiftGate with phase θ.\n\nbeginpmatrix\n1 0\n0 e^itheta\nendpmatrix\n\nExamples\n\njulia> shift(0.1)\nshift(0.1)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.simple_commute_eachother-Union{Tuple{Vector{<:AbstractBlock{D}}}, Tuple{D}} where D","page":"Blocks","title":"YaoBlocks.simple_commute_eachother","text":"Return true if operators commute to each other.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.single_qubit_depolarizing_channel-Tuple{Real}","page":"Blocks","title":"YaoBlocks.single_qubit_depolarizing_channel","text":"single_qubit_depolarizing_channel(p::Real)\n\nCreate a single-qubit depolarizing channel.\n\nThe factor of 3/4 in front of p ensures that single_qubit_depolarizing_channel(p) == depolarizing_channel(1, p)\n\n(1 - 3p4 ρ) + p4(XρX + YρY + ZρZ)\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.sprand_hermitian-Tuple{Int64, Any}","page":"Blocks","title":"YaoBlocks.sprand_hermitian","text":"sprand_hermitian([T=ComplexF64], N, density)\n\nCreate a sparse random hermitian matrix.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.sprand_unitary-Tuple{Int64, Real}","page":"Blocks","title":"YaoBlocks.sprand_unitary","text":"sprand_unitary([T=ComplexF64], N::Int, density) -> SparseMatrixCSC\n\nCreate a random sparse unitary matrix.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.subroutine-Tuple{AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.subroutine","text":"subroutine(block, locs) -> f(n)\n\nLazy curried version of subroutine.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.subroutine-Tuple{Int64, AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.subroutine","text":"subroutine(n, block, locs)\n\nCreate a n-qudit Subroutine block, where the subblock is a subprogram of size m, and locs is a tuple or range of length m. It runs a quantum subprogram with smaller size on a subset of locations. While its mathematical definition is the same as the put block, while it is more suited for running a larger chunk of circuit.\n\nExamples\n\nSubroutine is equivalent to put a block on given position mathematically, but more efficient and convenient for large blocks.\n\njulia> r = rand_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> apply!(copy(r), subroutine(X, 1)) ≈ apply!(copy(r), put(1=>X))\ntrue\n\nIt works for in-contigious locs as well\n\njulia> r = rand_state(4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> cc = subroutine(4, kron(X, Y), (1, 3))\nnqubits: 4\nSubroutine: (1, 3)\n└─ kron\n ├─ 1=>X\n └─ 2=>Y\n\njulia> pp = chain(4, put(1=>X), put(3=>Y))\nnqubits: 4\nchain\n├─ put on (1)\n│ └─ X\n└─ put on (3)\n └─ Y\n\njulia> apply!(copy(r), cc) ≈ apply!(copy(r), pp)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.swap-Tuple{Int64, Int64, Int64}","page":"Blocks","title":"YaoBlocks.swap","text":"swap(n, loc1, loc2)\n\nCreate a n-qubit Swap gate which swap loc1 and loc2.\n\nExamples\n\njulia> swap(4, 1, 2)\nnqubits: 4\nput on (1, 2)\n└─ SWAP\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.swap-Tuple{Int64, Int64}","page":"Blocks","title":"YaoBlocks.swap","text":"swap(loc1, loc2) -> f(n)\n\nCreate a lambda that takes the total number of active qubits as input. Lazy curried version of swap(n, loc1, loc2). See also Swap.\n\nExamples\n\njulia> swap(1, 2)\n(n -> swap(n, 1, 2))\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.time_evolve-Tuple{AbstractBlock, Any}","page":"Blocks","title":"YaoBlocks.time_evolve","text":"time_evolve(H, dt[; tol=1e-7, check_hermicity=true])\n\nCreate a TimeEvolution block with Hamiltonian H and time step dt. The TimeEvolution block will use Krylove based expv to calculate time propagation. TimeEvolution block can also be used for imaginary time evolution if dt is complex. Let H be a hamiltonian and t be a time, the matrix representation of time_evolve(H, t) is e^-iHt.\n\nArguments\n\nH the hamiltonian represented as an AbstractBlock.\ndt: the evolution duration (start time is zero).\n\nKeyword Arguments\n\ntol::Real=1e-7: error tolerance.\ncheck_hermicity=true: check hermicity or not.\n\nExamples\n\njulia> time_evolve(kron(2, 1=>X, 2=>X), 0.1)\nTime Evolution Δt = 0.1, tol = 1.0e-7\nkron\n├─ 1=>X\n└─ 2=>X\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.two_qubit_depolarizing_channel-Tuple{Real}","page":"Blocks","title":"YaoBlocks.two_qubit_depolarizing_channel","text":"two_qubit_depolarizing_channel(p::Real)\n\nCreate a two-qubit depolarizing channel. Note that this is not the same as kron(single_qubit_depolarizing_channel(p), single_qubit_depolarizing_channel(p)).\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.u1ij!","page":"Blocks","title":"YaoBlocks.u1ij!","text":"u1ij!(target, i, j, a, b, c, d)\n\nsingle u1 matrix into a target matrix.\n\nnote: Note\nFor coo, we take an additional parameter * ptr: starting position to store new data.\n\n\n\n\n\n","category":"function"},{"location":"man/blocks.html#YaoBlocks.unitary_channel-Tuple{Any, AbstractVector}","page":"Blocks","title":"YaoBlocks.unitary_channel","text":"unitary_channel(operators, probs) -> UnitaryChannel\n\nReturns a UnitaryChannel instance, where `operators is a list of operators, probs is a real vector that sum up to 1. The unitary channel is defined as below\n\nphi(rho) = sum_i p_i U_i ρ U_i^dagger\n\nwhere rho in a DensityMatrix as the register to apply on, p_i is the i-th element in probs, U_i is the i-th operator in operators.\n\nExamples\n\njulia> unitary_channel([X, Y, Z], [0.1, 0.2, 0.7])\nnqubits: 1\nunitary_channel\n├─ [0.1] X\n├─ [0.2] Y\n└─ [0.7] Z\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.unmat-Tuple{Val{2}, Int64, AbstractMatrix, NTuple{N, T} where {N, T}}","page":"Blocks","title":"YaoBlocks.unmat","text":"unmat(::Val{D}, nbit::Int, U::AbstractMatrix, locs::NTuple) -> AbstractMatrix\n\nReturn the matrix representation of putting matrix at locs.\n\n\n\n\n\n","category":"method"},{"location":"man/blocks.html#YaoBlocks.@yao_str-Tuple{String}","page":"Blocks","title":"YaoBlocks.@yao_str","text":"@yao_str\nyao\"...\"\n\nThe mark up language for quantum circuit.\n\n\n\n\n\n","category":"macro"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"CurrentModule = YaoPlots\nDocTestSetup = quote\n using Yao\n using Yao: YaoBlocks, YaoArrayRegister, YaoSym\n using YaoBlocks\n using YaoArrayRegister\n using YaoPlots\nend","category":"page"},{"location":"man/plot.html#Quantum-Circuit-Visualization","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"YaoPlots is the Quantum circuit visualization component for Yao.","category":"page"},{"location":"man/plot.html#Examples","page":"Quantum Circuit Visualization","title":"Examples","text":"","category":"section"},{"location":"man/plot.html#Example-1:-Visualize-a-QBIR-define-in-Yao","page":"Quantum Circuit Visualization","title":"Example 1: Visualize a QBIR define in Yao","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"using Yao.EasyBuild, YaoPlots\n\n# show a qft circuit\nvizcircuit(qft_circuit(5))","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"If you are using a Pluto/Jupyter notebook, Atom/VSCode editor, you should see the above image in your plotting panel.","category":"page"},{"location":"man/plot.html#Example-2:-Visualize-a-single-qubit","page":"Quantum Circuit Visualization","title":"Example 2: Visualize a single qubit","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"using YaoPlots, Yao\n\nreg = zero_state(1) |> Rx(π/8) |> Rx(π/8)\nrho = density_matrix(ghz_state(2), 1)\n\nbloch_sphere(\"|ψ⟩\"=>reg, \"ρ\"=>rho; show_projection_lines=true)","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"See more examples.","category":"page"},{"location":"man/plot.html#Adjusting-the-plot-attributes","page":"Quantum Circuit Visualization","title":"Adjusting the plot attributes","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"Various attributes of the visualizations can be altered. The plot can be modified, if we change the following attributes","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"YaoPlots.CircuitStyles.linecolor[] for line color, default value being \"#000000\" (black color)\nYaoPlots.CircuitStyles.gate_bgcolor[] for background color of square blocks, the default value being \"#FFFFFF\" (white color)\nYaoPlots.CircuitStyles.textcolor[] for text color, default value being \"#000000\nYaoPlots.CircuitStyles.lw[] for line width, default value being 1 (pt)\nYaoPlots.CircuitStyles.textsize[] for text size, default value being 16 (pt)\nYaoPlots.CircuitStyles.paramtextsize[] for parameter text size, for parameterized gates, default value being 10 (pt)","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"For example,","category":"page"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"using YaoPlots, Yao\nYaoPlots.CircuitStyles.linecolor[] = \"pink\" \nYaoPlots.CircuitStyles.gate_bgcolor[] = \"yellow\" \nYaoPlots.CircuitStyles.textcolor[] = \"#000080\" # the navy blue color\nYaoPlots.CircuitStyles.fontfamily[] = \"JuliaMono\"\nYaoPlots.CircuitStyles.lw[] = 2.5\nYaoPlots.CircuitStyles.textsize[] = 13\nYaoPlots.CircuitStyles.paramtextsize[] = 8\n\t\t\nvizcircuit(chain(3, put(1=>X), repeat(3, H), put(2=>Y), repeat(3, Rx(π/2))))","category":"page"},{"location":"man/plot.html#Circuit-Visualization","page":"Quantum Circuit Visualization","title":"Circuit Visualization","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"vizcircuit\nplot","category":"page"},{"location":"man/plot.html#YaoPlots.vizcircuit","page":"Quantum Circuit Visualization","title":"YaoPlots.vizcircuit","text":"vizcircuit(circuit; w_depth=0.85, w_line=0.75, format=:svg, filename=nothing,\n show_ending_bar=false, starting_texts=nothing, starting_offset=-0.3,\n ending_texts=nothing, ending_offset=0.3)\n\nVisualize a Yao quantum circuit.\n\nKeyword Arguments\n\nw_depth is the circuit column width.\nw_line is the circuit row width.\nformat can be :svg, :png or :pdf.\nfilename can be \"*.svg\", \"*.png\", \"*.pdf\" or nothing (not saving to a file).\nstarting_texts and ending_texts are texts shown before and after the circuit.\nstarting_offset and end_offset are offsets (real values) for starting and ending texts.\nshow_ending_bar is a boolean switch to show ending bar.\n\nStyles\n\nTo change the gates styles like colors and lines, please modify the constants in submodule CircuitStyles. They are defined as:\n\nCircuitStyles.unit = Ref(60) # number of points in a unit\nCircuitStyles.r = Ref(0.2) # size of nodes\nCircuitStyles.lw = Ref(1.0) # line width\nCircuitStyles.textsize = Ref(16.0) # text size\nCircuitStyles.paramtextsize = Ref(10.0) # text size (longer texts)\nCircuitStyles.fontfamily = Ref(\"JuliaMono\") # font family\nCircuitStyles.linecolor = Ref(\"#000000\") # line color\nCircuitStyles.gate_bgcolor = Ref(\"transparent\") # gate background color\nCircuitStyles.textcolor = Ref(\"#000000\") # text color\n\n\n\n\n\n","category":"function"},{"location":"man/plot.html#YaoPlots.plot","page":"Quantum Circuit Visualization","title":"YaoPlots.plot","text":"An alias of vizcircuit\n\n\n\n\n\n","category":"function"},{"location":"man/plot.html#Bloch-Sphere-Visualization","page":"Quantum Circuit Visualization","title":"Bloch Sphere Visualization","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"CircuitStyles\nbloch_sphere\nBlochStyles","category":"page"},{"location":"man/plot.html#YaoPlots.CircuitStyles","page":"Quantum Circuit Visualization","title":"YaoPlots.CircuitStyles","text":"CircuitStyles\n\nA module to define the styles of the circuit visualization. To change the styles, please modify the variables in this module, e.g.\n\njulia> using YaoPlots\n\njulia> YaoPlots.CircuitStyles.unit[] = 40\n40\n\nStyle variables\n\nSizes\n\nunit is the number of pixels in a unit.\nr is the size of nodes.\nlw is the line width.\n\nTexts\n\ntextsize is the text size.\nparamtextsize is the text size for longer texts.\nfontfamily is the font family.\n\nColors\n\nlinecolor is the line color.\ngate_bgcolor is the gate background color.\ntextcolor is the text color.\n\n\n\n\n\n","category":"module"},{"location":"man/plot.html#YaoPlots.bloch_sphere","page":"Quantum Circuit Visualization","title":"YaoPlots.bloch_sphere","text":"bloch_sphere(\n states...;\n textsize,\n color,\n drawing_size,\n offset_x,\n offset_y,\n filename,\n format,\n fontfamily,\n background_color,\n lw,\n eye_point,\n extra_kwargs...\n) -> Luxor.Drawing\n\n\nDraw a bloch sphere, with the inputs being a list of string => state pairs, where the string is a label for the state and a state can be a complex vector of size 2, a Yao register or DensityMatrix. If you want to get a raw drawing, use draw_bloch_sphere instead.\n\nKeyword Arguments\n\nNote: The default values can be specified in submodule BlochStyles.\n\ntextsize: the size of the text\ncolor: the color of the drawing\ndrawing_size: the size of the drawing\noffset_x: the offset of the drawing in x direction\noffset_y: the offset of the drawing in y direction\nfilename: the filename of the output file, if not specified, a temporary file will be used\nformat: the format of the output file, if not specified, the format will be inferred from the filename\nfontfamily: the font family of the text\nbackground_color: the background color of the drawing\nlw: the line width of the drawing\neye_point: the eye point of the drawing\nextra_kwargs: extra keyword arguments passed to draw_bloch_sphere\ndot_size: the size of the dot\nball_size: the size of the ball\nshow_projection_lines: whether to show the projection lines\nshow_angle_texts: whether to show the angle texts\nshow_line: whether to show the line\nshow01: whether to show the 0 and 1 states\ncolors: the colors of the states\naxes_lw: the line width of the axes\naxes_textsize: the size of the axes texts\naxes_colors: the colors of the axes\naxes_texts: the texts of the axes\n\nExamples\n\njulia> using YaoPlots, YaoArrayRegister\n\njulia> bloch_sphere(\"|ψ⟩\"=>rand_state(1), \"ρ\"=>density_matrix(rand_state(2), 1));\n\n\n\n\n\n","category":"function"},{"location":"man/plot.html#YaoPlots.BlochStyles","page":"Quantum Circuit Visualization","title":"YaoPlots.BlochStyles","text":"BlochStyles\n\nThe module to define the default styles for bloch sphere drawing. To change the default styles, you can modify the values in this module, e.g.\n\nusing YaoPlots\nYaoPlots.BlochStyles.lw[] = 2.0\n\nStyle variables\n\nGeneric\n\nlw: the line width of the drawing\ntextsize: the size of the text\nfontfamily: the font family of the text\nbackground_color: the background color of the drawing\ncolor: the color of the drawing\n\nSphere\n\nball_size: the size of the ball\ndot_size: the size of the dot\neye_point: the eye point of the drawing\n\nAxis\n\naxes_lw: the line width of the axes\naxes_colors: the colors of the axes\naxes_texts: the texts of the axes, default to [\"x\", \"y\", \"z\"]\n\nState display\n\nshow_projection_lines: whether to show the projection lines\nshow_angle_texts: whether to show the angle texts\nshow_line: whether to show the line\nshow01: whether to show the 0 and 1 states\n\n\n\n\n\n","category":"module"},{"location":"man/plot.html#Themes","page":"Quantum Circuit Visualization","title":"Themes","text":"","category":"section"},{"location":"man/plot.html","page":"Quantum Circuit Visualization","title":"Quantum Circuit Visualization","text":"darktheme!\nlighttheme!","category":"page"},{"location":"man/plot.html#YaoPlots.darktheme!","page":"Quantum Circuit Visualization","title":"YaoPlots.darktheme!","text":"darktheme!()\n\nChange the default theme to dark.\n\n\n\n\n\n","category":"function"},{"location":"man/plot.html#YaoPlots.lighttheme!","page":"Quantum Circuit Visualization","title":"YaoPlots.lighttheme!","text":"lighttheme!()\n\nChange the default theme to light.\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#Tensor-network-backend","page":"Tensor network backend","title":"Tensor network backend","text":"","category":"section"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"Simulating quantum circuits using tensor networks has been studied in the literature[Markov2008][Pan2022]. The YaoToEinsum package provides a convenient way to convert Yao circuits to tensor networks, which can be used for further analysis and optimization.","category":"page"},{"location":"man/yao2einsum.html#Tutorial","page":"Tensor network backend","title":"Tutorial","text":"","category":"section"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"The main function is","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"yao2einsum(circuit; initial_state=Dict(), final_state=Dict(), optimizer=TreeSA())","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"which transforms a Yao circuit to a tensor network that generalizes the hyper-graph (einsum notation). The return value is a TensorNetwork object.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"initial_state and final_state are for specifying the initial state and final state. Left the qubits unspecified if you want to keep them as the open indices.\noptimizer is for specifying the contraction order optimizing algorithm of the tensor network. The default value is the TreeSA() algorithm that developed in [Kalachev2021][Liu2023]. Please check the README of OMEinsumEinsumContractors.jl for more information.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"In the following example, we show how to convert a quantum Fourier transform circuit to a tensor network and contract it to","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"Get the matrix representation of the circuit.\nGet the probability of measuring the zero state after applying the circuit on the zero state.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"import Yao\nusing Yao.EasyBuild: qft_circuit\nn = 10;\ncircuit = qft_circuit(n); # build a quantum Fourier transform circuit\nnetwork = Yao.yao2einsum(circuit) # convert this circuit to tensor network\nreshape(Yao.contract(network), 1<0 for i=1:n]), final_state=Dict([i=>0 for i=1:n]),\n optimizer=Yao.YaoToEinsum.TreeSA(; nslices=3)) # slicing technique\nYao.contract(network)[] ≈ Yao.zero_state(n)' * (Yao.zero_state(n) |> circuit)","category":"page"},{"location":"man/yao2einsum.html#API","page":"Tensor network backend","title":"API","text":"","category":"section"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"yao2einsum\nTensorNetwork\noptimize_code\ncontraction_complexity\ncontract","category":"page"},{"location":"man/yao2einsum.html#YaoToEinsum.yao2einsum","page":"Tensor network backend","title":"YaoToEinsum.yao2einsum","text":"yao2einsum(circuit; initial_state=Dict(), final_state=Dict(), optimizer=TreeSA())\nyao2einsum(circuit, initial_state::Dict, final_state::Dict, optimizer)\n\nTransform a Yao circuit to a generalized tensor network (einsum) notation. The return value is a TensorNetwork instance.\n\nArguments\n\ncircuit is a Yao block as the input.\ninitial_state and final_state are dictionaries to specify the initial states and final states (taking conjugate).\nIn the first interface, a state is specified as an integer, e.g. Dict(1=>1, 2=>1, 3=>0, 4=>1) specifies a product state |1⟩⊗|1⟩⊗|0⟩⊗|1⟩.\nIn the second interface, a state is specified as an ArrayReg, e.g. Dict(1=>rand_state(1), 2=>rand_state(1)).\n\nIf any qubit in initial state or final state is not specified, it will be treated as a free leg in the tensor network.\n\noptimizer is the optimizer used to optimize the tensor network. The default is TreeSA().\n\nPlease check OMEinsumContractors.jl for more information.\n\njulia> using Yao\n\njulia> c = chain(3, put(3, 2=>X), put(3, 1=>Y), control(3, 1, 3=>Y))\nnqubits: 3\nchain\n├─ put on (2)\n│ └─ X\n├─ put on (1)\n│ └─ Y\n└─ control(1)\n └─ (3,) Y\n\n\njulia> yao2einsum(c; initial_state=Dict(1=>0, 2=>1), final_state=Dict(1=>ArrayReg([0.6, 0.8im]), 2=>1))\nTensorNetwork\nTime complexity: 2^4.700439718141093\nSpace complexity: 2^2.0\nRead-write complexity: 2^6.0\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#YaoToEinsum.TensorNetwork","page":"Tensor network backend","title":"YaoToEinsum.TensorNetwork","text":"TensorNetwork\n\nA (generalized) tensor network representation of a quantum circuit.\n\nFields\n\ncode::AbstractEinsum: The einsum code.\ntensors::Vector: The tensors in the network.\n\n\n\n\n\n","category":"type"},{"location":"man/yao2einsum.html#OMEinsumContractionOrders.optimize_code","page":"Tensor network backend","title":"OMEinsumContractionOrders.optimize_code","text":"optimize_code(c::TensorNetwork, optimizer=TreeSA())\n\nOptimize the code of the tensor network.\n\nArguments\n\nc::TensorNetwork: The tensor network.\noptimizer::Optimizer: The optimizer to use, default is TreeSA(). Please check OMEinsumContractors.jl for more information.\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#OMEinsumContractionOrders.contraction_complexity","page":"Tensor network backend","title":"OMEinsumContractionOrders.contraction_complexity","text":"contraction_complexity(c::TensorNetwork)\n\nReturn the contraction complexity of the tensor network.\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#YaoToEinsum.contract","page":"Tensor network backend","title":"YaoToEinsum.contract","text":"contract(c::TensorNetwork)\n\nContract the tensor network, and return the result tensor.\n\n\n\n\n\n","category":"function"},{"location":"man/yao2einsum.html#References","page":"Tensor network backend","title":"References","text":"","category":"section"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"[Pan2022]: Pan, Feng, and Pan Zhang. \"Simulation of quantum circuits using the big-batch tensor network method.\" Physical Review Letters 128.3 (2022): 030501.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"[Kalachev2021]: Kalachev, Gleb, Pavel Panteleev, and Man-Hong Yung. \"Recursive multi-tensor contraction for xeb verification of quantum circuits.\" arXiv preprint arXiv:2108.05665 (2021).","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"[Markov2008]: Markov, Igor L., and Yaoyun Shi. \"Simulating quantum computation by contracting tensor networks.\" SIAM Journal on Computing 38.3 (2008): 963-981.","category":"page"},{"location":"man/yao2einsum.html","page":"Tensor network backend","title":"Tensor network backend","text":"[Liu2023]: Liu, Jin-Guo, et al. \"Computing solution space properties of combinatorial optimization problems via generic tensor networks.\" SIAM Journal on Scientific Computing 45.3 (2023): A1239-A1270.","category":"page"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"CurrentModule = YaoSym\nDocTestSetup = quote\n using Yao\n using Yao: YaoBlocks, YaoArrayRegister, YaoSym\n using YaoBlocks\n using YaoArrayRegister\n using YaoSym\nend","category":"page"},{"location":"man/symbolic.html#Symbolic-Computation","page":"Symbolic Computation","title":"Symbolic Computation","text":"","category":"section"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"The symbolic engine of Yao is based on SymEngine.jl. It allows one to define quantum circuits with symbolic parameters and perform symbolic computation on them. Two macro/functions play a key role in the symbolic computation:","category":"page"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"@vars for defining symbolic variables\nsubs for substituting symbolic variables with concrete values","category":"page"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"using Yao\n@vars θ\ncircuit = chain(2, put(1=>H), put(2=>Ry(θ)))\nmat(circuit)\nnew_circuit = subs(circuit, θ=>π/2)\nmat(new_circuit)","category":"page"},{"location":"man/symbolic.html#API","page":"Symbolic Computation","title":"API","text":"","category":"section"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"The following functions are for working with symbolic states.","category":"page"},{"location":"man/symbolic.html","page":"Symbolic Computation","title":"Symbolic Computation","text":"@ket_str\n@bra_str\nszero_state","category":"page"},{"location":"man/symbolic.html#YaoSym.@ket_str","page":"Symbolic Computation","title":"YaoSym.@ket_str","text":"@ket_str\n\nCreate a ket register. See also @bra_str.\n\nExamples\n\na symbolic quantum state can be created simply by\n\njulia> ket\"110\" + 2ket\"111\"\n|110⟩ + 2.0|111⟩\n\nqubits can be partially actived by focus!\n\njulia> ket\"100\" + ket\"111\" |> focus!(1:2)\n|100⟩ + |111⟩\n\n\n\n\n\n","category":"macro"},{"location":"man/symbolic.html#YaoSym.@bra_str","page":"Symbolic Computation","title":"YaoSym.@bra_str","text":"@bra_str\n\nCreate a bra register. See also @ket_str.\n\nExamples\n\nSimilar to @ket_str literal, a symbolic quantum state can be created by\n\njulia> bra\"111\" + 2bra\"101\"\n2.0⟨101| + ⟨111|\n\njulia> bra\"111\" * (ket\"101\" + ket\"111\")\n1\n\n\n\n\n\n","category":"macro"},{"location":"man/symbolic.html#YaoSym.szero_state","page":"Symbolic Computation","title":"YaoSym.szero_state","text":"szero_state(n; nbatch=1)\n\nCreate a symbolic zero state, same as ket\"000\", but allows you use an integer.\n\n\n\n\n\n","category":"function"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"EditURL = \"../../../examples/4.shor-algorithm/main.jl\"","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"(Image: )","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#Shor","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html#References","page":"Shor's Algorithm","title":"References","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Neilsen\nAn Insightful Blog","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"The main program of a Shor's algorithm can be summrized in several lines of code. For the theory part, please refer the reference materials above. It factorize an integer L, and returns one of the factors.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"using Yao, BitBasis\nusing Yao.EasyBuild: qft_circuit","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#Number-theory-basic","page":"Shor's Algorithm","title":"Number theory basic","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Before entering the main program, let us defined some useful functions in number theory.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"module NumberTheory\n\nexport Z_star, Eulerφ, continued_fraction, mod_inverse, rand_primeto, factor_a_power_b\nexport is_order, order_from_float, find_order\n\n\"\"\"\n Z_star(N::Int) -> Vector\n\nreturns the Z* group elements of `N`, i.e. {x | gcd(x, N) == 1}\n\"\"\"\nZ_star(N::Int) = filter(i->gcd(i, N)==1, 0:N-1)\nEulerφ(N) = length(Z_star(N))\n\n\"\"\"\n continued_fraction(ϕ, niter::Int) -> Rational\n\nobtain `s` and `r` from `ϕ` that satisfies `|s/r - ϕ| ≦ 1/2r²`\n\"\"\"\ncontinued_fraction(ϕ, niter::Int) = niter==0 || isinteger(ϕ) ? floor(Int, ϕ) : floor(Int, ϕ) + 1//continued_fraction(1/mod(ϕ, 1), niter-1)\ncontinued_fraction(ϕ::Rational, niter::Int) = niter==0 || ϕ.den==1 ? floor(Int, ϕ) : floor(Int, ϕ) + 1//continued_fraction(1/mod(ϕ, 1), niter-1)\n\n\"\"\"\n mod_inverse(x::Int, N::Int) -> Int\n\nReturn `y` that `(x*y)%N == 1`, notice the `(x*y)%N` operations in Z* forms a group and this is the definition of inverse.\n\"\"\"\nfunction mod_inverse(x::Int, N::Int)\n for i=1:N\n (x*i)%N == 1 && return i\n end\n throw(ArgumentError(\"Can not find the inverse, $x is probably not in Z*($N)!\"))\nend\n\n\"\"\"\n is_order(r, x, N) -> Bool\n\nReturns true if `r` is the order of `x`, i.e. `r` satisfies `x^r % N == 1`.\n\"\"\"\nis_order(r, x, N) = powermod(x, r, N) == 1\n\n\"\"\"\n find_order(x::Int, N::Int) -> Int\n\nFind the order of `x` by brute force search.\n\"\"\"\nfunction find_order(x::Int, N::Int)\n findfirst(r->is_order(r, x, N), 1:N)\nend\n\n\"\"\"\n rand_primeto(N::Int) -> Int\n\nReturns a random number `2 ≦ x < N` that is prime to `N`.\n\"\"\"\nfunction rand_primeto(N::Int)\n while true\n x = rand(2:N-1)\n d = gcd(x, N)\n if d == 1\n return x\n end\n end\nend\n\n\"\"\"\n order_from_float(ϕ, x, L) -> Int\n\nEstimate the order of `x` to `L`, `r`, from a floating point number `ϕ ∼ s/r` using the continued fraction method.\n\"\"\"\nfunction order_from_float(ϕ, x, L)\n k = 1\n rnum = continued_fraction(ϕ, k)\n while rnum.den < L && k < 100\n r = rnum.den\n if is_order(r, x, L)\n return r\n end\n k += 1\n rnum = continued_fraction(ϕ, k)\n end\n return nothing\nend\n\n\"\"\"\n factor_a_power_b(N::Int) -> (Int, Int) or nothing\n\nFactorize `N` into the power form `a^b`.\n\"\"\"\nfunction factor_a_power_b(N::Int)\n y = log2(N)\n for b = 2:ceil(Int, y)\n x = 2^(y/b)\n u1 = floor(Int, x)\n u1^b == N && return (u1, b)\n (u1+1)^b == N && return (u1+1, b)\n end\nend\n\nend","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Main.var\"##235\".NumberTheory","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#A-quantum-function-to-compute-mod","page":"Shor's Algorithm","title":"A quantum function to compute mod","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Before introducing the main program, let us customize a block for computing the classical function mod. In a more practical setup, it should be compiled to basic quantum gates. Here we just hack this function for simplicity.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"\"\"\"\n KMod <: PrimitiveBlock{2}\n\nThe first `k` qubits are exponent, and the rest `n-k` are base `a`,\nit calculates `mod(a^k*x, L)`, notice `gcd(a, L)` should be 1.\n\"\"\"\nstruct KMod <: PrimitiveBlock{2}\n n::Int\n k::Int\n a::Int\n L::Int\n function KMod(n, k, a, L)\n @assert gcd(a, L) == 1 && L<=1<<(n-k)\n new(n, k, a, L)\n end\nend\n\nYao.nqudits(m::KMod) = m.n\n\nfunction bint2_reader(T, k::Int)\n mask = bmask(T, 1:k)\n return b -> (b&mask, b>>k)\nend\n\nfunction Yao.unsafe_apply!(reg::AbstractArrayReg, m::KMod)\n nstate = zero(reg.state)\n\n reader = bint2_reader(Int, m.k)\n for b in 0:1<= m.L ? i : mod(i*powermod(m.a, k, m.L), m.L)\n _b = k + _i<= m.L ? i : mod(i*powermod(m.a, k, m.L), m.L)\n _b = k + _i< c; nshots=nshots)\n for r in res\n # split bit string b into lower bits `k` and higher bits `r`.\n mask = bmask(1:ncbit)\n k,i = r&mask, r>>ncbit\n # get s/r\n ϕ = bfloat(k) #\n ϕ == 0 && continue\n\n # order_from_float: given a floating point number,\n # return the closest rational number with bounded number of continued fraction steps.\n order = NumberTheory.order_from_float(ϕ, x, L)\n if order === nothing\n continue\n else\n return order\n end\n end\n return nothing\nend","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"get_order (generic function with 2 methods)","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#The-circuit-used-for-finding-order","page":"Shor's Algorithm","title":"The circuit used for finding order","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"\"\"\"\n order_finding_circuit(x::Int, L::Int; nbit::Int=bit_length(L-1), ncbit::Int=estimate_ncbit(nbit, 0.25)) -> AbstractBlock\n\nReturns the circuit for finding the order of `x` to `L`,\nfeeding input `|1>⊗|0>` will get the resulting quantum register with the desired \"phase\" information.\n\"\"\"\nfunction order_finding_circuit(x::Int, L::Int; nbit::Int, ncbit::Int)\n N = nbit+ncbit\n chain(N, repeat(N, H, 1:ncbit), KMod(N, ncbit, x, L),\n subroutine(N, qft_circuit(ncbit)', 1:ncbit))\nend","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Main.var\"##235\".order_finding_circuit","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"The circuit for order finding is consisted of three parts","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Hadamard gates,\nKMod that computes a classical function mod(a^k*x, L).","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"k is the integer stored in first K (or ncbit) qubits and the rest N-K qubits stores a. Notice it is not a basic gate, it should have been compiled to multiple gates, which is not implemented in Yao for the moment. To learn more about implementing arithmatics on a quantum circuit, please read this paper.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Inverse quantum fourier transformation.","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html#Run","page":"Shor's Algorithm","title":"Run","text":"","category":"section"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"Factorizing 15, you should see 3 or 5, please report a bug if it is not...","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"shor(15, Val(:quantum))","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"3","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"","category":"page"},{"location":"generated/examples/4.shor-algorithm/index.html","page":"Shor's Algorithm","title":"Shor's Algorithm","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"EditURL = \"../../../examples/8.riemannian-gradient-flow/main.jl\"","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"(Image: )","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html#Riemannian-gradient-flow-optimizer","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"","category":"section"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"In this tutorial we will present the Riemannian gradient descent algorithm described in Miao and Barthel (2021) and Wiersema and Killoran (2022) As opposed to most standard optimization algorithms that optimize parameters of variational quantum circuits, this algorithm optimizes a function directly over the special unitary group by following the gradient flow over the manifold. Let's start by importing the necessary packages.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"using Yao, Yao.EasyBuild, Plots, Random\nusing KrylovKit: eigsolve","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Variational quantum eigensolver (VQE) is one of the most celebrated near-term quantum algorithms. In the usual setting, VQE tries to reach the ground state by minimizing the energy cost function","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"mathcalL(theta) = textTrHU(theta)rho_0U^dagger(theta)","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"with respect to parameters theta which parameterize a quantum circuit U(theta), where rho_0 = psi_0ranglelanglepsi_0 is some initial state and H the Hamiltonian whose ground state we want to approximate. We can solve the optimization problem textmin_thetamathcalL(theta) by following the direction of the steepest descent in parameter space which is given by the gradient of the cost function, i.e. by considering the following gradient flow","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"dottheta = -textgradmathcalL(theta)","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Discretizing the equation above, we recover the well-known gradient descent algorithm","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"theta_k + 1 = theta_k - alphatextgradmathcalL(theta)","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"where alpha is the learning rate. Let's demonstrate it on the example of finding the ground state of the transverse field Ising model.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"n = 8\nh = transverse_ising(n, 1.0)\nw, v = eigsolve(mat(h), 1, :SR, ishermitian=true)\n\nRandom.seed!(0)\ncircuit = dispatch!(variational_circuit(n, 100), :random);\nhistory = Float64[]\nfor i in 1:100\n _, grad = expect'(h, zero_state(n) => circuit)\n dispatch!(-, circuit, 0.01 * grad)\n push!(history, real.(expect(h, zero_state(n)=>circuit)))\nend\n\nPlots.plot(history, legend=false)\nPlots.plot!(1:100, [w[1] for i=1:100])\nxlabel!(\"steps\")\nylabel!(\"energy\")","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Let's now consider the energy cost function directly over the special unitary group mathcalL textSU(2^n) rightarrow mathbbR","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"mathcalL(U) = textTrHUrho_0U^dagger","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"To minimize the cost function we can follow the Riemannian gradient flow defined through the following differential equation","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"dotU = -textgradmathcalL(U) = Urho_0U^dagger HU","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Discretizing the flow we get the following recursive update rule","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"U_k + 1 = expalphaU_krho_0U^dagger_k HU_k = expalpharho_k HU_k","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"where alpha is the appropriate learning rate and U_0 = I.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"We can expand the commutator in the exponent in the basis of Pauli strings P^j","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"rho_k H = frac12^nsum_j = 1^4^n - 1omega^j_kP^j","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"where","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"omega^j_k = textTrrho_k HP^j = textTrH P^jrho_k = langleH P^jrangle_rho_k","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"It turns out that omega^j_k can easily be evaluated with the help of a parameter shift rule","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"omega^j_k = langleH P^jrangle_rho_k = -ilangle V^dagger_j(pi4)HV_j(pi4) - V^dagger_j(-pi4)HV_j(-pi4)rangle_rho_k","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"where V_j(t) = exp-itP^j.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Next, we write a function for generation of 2-local Pauli operators. We will restrict the Riemannian gradient to this subspace of the Lie algebra since otherwise the number of parameters to calculate would be 4^8 - 1 = 65535 which is too much for a reasonable runtime of the algorithm.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"function generate_2local_pauli_strings(n)\n pauli_strings = []\n for i = 1:n\n push!(pauli_strings, kron(n, i => X))\n push!(pauli_strings, kron(n, i => Y))\n push!(pauli_strings, kron(n, i => Z))\n end\n for i = 1:n-1\n for j = i+1:n\n for P1 in [X, Y, Z]\n for P2 in [X, Y, Z]\n push!(pauli_strings, kron(n, i => P1, j => P2))\n end\n end\n end\n end\n pauli_strings\nend;","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Next we write functions for calculating the expansion coefficients and a single optimization step. We will absorb the factor of 12^n into the learning rate.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"function calculate_omegas(n, reg, h, pauli_strings)\n iω = []\n for P in pauli_strings\n push!(iω, real(expect(h, reg => time_evolve(P, π/4)) - expect(h, reg => time_evolve(P, -π/4))))\n end\n iω\nend;\n\nfunction step_and_cost!(n, circuit, h, α, pauli_strings)\n iω = calculate_omegas(n, zero_state(n) |> circuit, h, pauli_strings)\n\n for (iωʲ, P) in zip(iω, pauli_strings)\n if abs(iωʲ) > 1e-6 # we will only keep the ones that actually contribute\n append!(circuit, chain(n, time_evolve(P, -α * iωʲ)))\n end\n end\n\n real(expect(h, zero_state(n) => circuit))\nend;","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"Finally, let's try it out. We initialize the state 0rangle and apply several optimization steps.","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"circuit = chain(n)\npauli_strings = generate_2local_pauli_strings(n)\nhistory = Float64[]\n\nfor i=1:100\n cost = step_and_cost!(n, circuit, h, 0.01, pauli_strings)\n push!(history, cost)\nend\n\nPlots.plot(history, legend=false)\nPlots.plot!(1:100, [w[1] for i=1:100])\nxlabel!(\"steps\")\nylabel!(\"energy\")","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"\"Riemannian","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"When we compare the final states achieved with the Riemannian gradient flow optimizer and with the standard VQE we can notice that the former has lower quality. This is because the Riemannian gradient flow optimizer has only a local view of the cost landscape while VQE can access these directions since the ansatz we used is universal. However, if we were able to calculate all of the 4^n - 1 projections, Riemannian gradient flow optimizer would be guaranteed to converge given the appropriate learning rate!","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"","category":"page"},{"location":"generated/examples/8.riemannian-gradient-flow/index.html","page":"Riemannian gradient flow optimizer","title":"Riemannian gradient flow optimizer","text":"This page was generated using Literate.jl.","category":"page"},{"location":"dev/index.html#Developer-Notes","page":"Developer Notes","title":"Developer Notes","text":"","category":"section"},{"location":"dev/index.html#Overview-of-the-Architecture","page":"Developer Notes","title":"Overview of the Architecture","text":"","category":"section"},{"location":"dev/index.html","page":"Developer Notes","title":"Developer Notes","text":"The following is an overview of the entire ecosystem, where Yao and CuYao are two meta-packages.","category":"page"},{"location":"dev/index.html","page":"Developer Notes","title":"Developer Notes","text":"(Image: stack)","category":"page"},{"location":"dev/index.html#The-role-of-QBIR","page":"Developer Notes","title":"The role of QBIR","text":"","category":"section"},{"location":"dev/index.html","page":"Developer Notes","title":"Developer Notes","text":"Currently the main functionality is built on the Quantum Block Intermediate Representation (QBIR). A quantum program is defined by QBIR and then interpreted to different targets, such as different simulation backend or matrix representation.","category":"page"},{"location":"dev/index.html","page":"Developer Notes","title":"Developer Notes","text":"(Image: framework)","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"EditURL = \"../../../examples/7.variation-quantum-eigen-solver/main.jl\"","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"(Image: )","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html#Variational-Quantum-Eigen-Solver","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"","category":"section"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"using Yao, Yao.AD, Yao.EasyBuild","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"number of qubits","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"n = 4","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"4","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"depth","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"d = 5\ncircuit = dispatch!(variational_circuit(n, d),:random)\n\ngatecount(circuit)\n\nnparameters(circuit)\n\nh = heisenberg(n)","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"nqubits: 4\n+\n├─ +\n│ ├─ repeat on (1, 2)\n│ │ └─ X\n│ ├─ repeat on (1, 2)\n│ │ └─ Y\n│ └─ repeat on (1, 2)\n│ └─ Z\n├─ +\n│ ├─ repeat on (2, 3)\n│ │ └─ X\n│ ├─ repeat on (2, 3)\n│ │ └─ Y\n│ └─ repeat on (2, 3)\n│ └─ Z\n├─ +\n│ ├─ repeat on (3, 4)\n│ │ └─ X\n│ ├─ repeat on (3, 4)\n│ │ └─ Y\n│ └─ repeat on (3, 4)\n│ └─ Z\n└─ +\n ├─ repeat on (1, 4)\n │ └─ X\n ├─ repeat on (1, 4)\n │ └─ Y\n └─ repeat on (1, 4)\n └─ Z\n","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"pick the one you like either reverse-mode or forward mode grad = faithfulgrad(h, zerostate(n) => circuit; nshots=100)","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"for i in 1:1000\n _, grad = expect'(h, zero_state(n) => circuit)\n dispatch!(-, circuit, 1e-2 * grad)\n println(\"Step $i, energy = $(real.(expect(h, zero_state(n)=>circuit)))\")\nend\n\nusing LinearAlgebra\nw, _ = eigen(Matrix(mat(h)))","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"LinearAlgebra.Eigen{ComplexF64, Float64, Matrix{ComplexF64}, Vector{Float64}}\nvalues:\n16-element Vector{Float64}:\n -7.9999999999999964\n -4.0\n -3.9999999999999956\n -3.999999999999994\n -7.437659514860159e-32\n -4.426399962566284e-32\n 0.0\n 2.7369110631344083e-48\n 2.003298162163793e-32\n 3.552713678800501e-15\n 4.440892098500626e-15\n 3.9999999999999987\n 3.9999999999999996\n 4.0\n 4.0\n 4.0\nvectors:\n16×16 Matrix{ComplexF64}:\n 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 1.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.559869+0.0im 0.43191+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im 2.22045e-16+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.288675+0.0im 9.56933e-17+0.0im 6.41024e-18+0.0im 0.0+0.0im 0.481733+0.0im -0.624453+0.0im 0.0+0.0im -0.211325+0.0im 1.34897e-17+0.0im 0.0+0.0im -0.288675+0.0im -6.41024e-18+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im -0.559869+0.0im -0.43191+0.0im 0.0+0.0im 0.0+0.0im 2.22045e-16+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n -0.57735+0.0im 0.707107+0.0im -1.30125e-33+0.0im 0.0+0.0im -1.30736e-32+0.0im 0.0+0.0im 0.0+0.0im -8.71576e-33+0.0im 3.06708e-33+0.0im 0.0+0.0im -1.97795e-16+0.0im 1.30125e-33+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.288675+0.0im 9.56933e-17+0.0im -2.39233e-17+0.0im 0.0+0.0im -0.12908+0.0im 0.167322+0.0im 0.0+0.0im 0.788675+0.0im 2.77891e-17+0.0im 0.0+0.0im -0.288675+0.0im 2.39233e-17+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.0+0.0im -4.71028e-16+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im -1.29477e-16+0.0im 6.29876e-17+0.0im 0.0+0.0im 6.06671e-17+0.0im -0.707107+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.288675+0.0im 9.56933e-17+0.0im 1.75131e-17+0.0im 0.0+0.0im -0.352653+0.0im 0.457131+0.0im 0.0+0.0im -0.57735+0.0im -4.12788e-17+0.0im 0.0+0.0im -0.288675+0.0im -1.75131e-17+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n -0.57735+0.0im -0.707107+0.0im 1.30125e-33+0.0im 0.0+0.0im 1.30736e-32+0.0im 0.0+0.0im 0.0+0.0im 8.71576e-33+0.0im -3.06708e-33+0.0im 0.0+0.0im -3.14995e-16+0.0im -1.30125e-33+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.707107+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im\n 0.288675+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.866025+0.0im 0.0+0.0im -0.408248+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im -0.707107+0.0im 0.0+0.0im 0.0+0.0im -4.71028e-16+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5+0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.707107+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im -0.5-0.0im 0.0+0.0im\n 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 1.0+0.0im","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"","category":"page"},{"location":"generated/examples/7.variation-quantum-eigen-solver/index.html","page":"Variational Quantum Eigen Solver","title":"Variational Quantum Eigen Solver","text":"This page was generated using Literate.jl.","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"EditURL = \"../../../examples/5.shor-9-code/main.jl\"","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"(Image: )","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html#Shor's-9-qubit-code","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"","category":"section"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"The well-known Shor's 9 qubit code can correct any single Pauli error, but it can also correct some other kinds of errors. Its circuit is shown as below (Image: shor-9-circuit) which can be constructed by the following code","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"using Yao\nusing SymEngine\n\nshor(E) = chain(9,\n # encode circuit\n cnot(1, 4), cnot(1, 7),\n put(1=>H), put(4=>H), put(7=>H),\n cnot(1,2), cnot(1,3), cnot(4,5), cnot(4,6), cnot(7,8), cnot(7,9),\n E, # the error\n # decode circuit\n cnot(1,2), cnot(1,3), cnot((2, 3), 1),\n cnot(4,5), cnot(4,6), cnot((5, 6), 4),\n cnot(7,8), cnot(7,9), cnot((8, 9), 7),\n put(1=>H), put(4=>H), put(7=>H), cnot(1, 4), cnot(1, 7), cnot((4, 7), 1)\n)","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"shor (generic function with 1 method)","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"Now we can check whether it can correct a given error by doing symbolic computation on an arbitrary 1-qubit pure quantum state α0 + β1 and a specific weight-9 error.","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"@vars α β\ns = α * ket\"0\" + β * ket\"1\" |> append_qudits!(8)\nE = kron(1=>X, 2=>Z, 3=>Z, 4=>X, 5=>Z, 6=>Z, 7=>X, 8=>Z, 9=>Z);\ns |> shor(E) |> expand","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"α|110110110⟩ + β|110110111⟩","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"","category":"page"},{"location":"generated/examples/5.shor-9-code/index.html","page":"Shor's 9 qubit code","title":"Shor's 9 qubit code","text":"This page was generated using Literate.jl.","category":"page"},{"location":"benchmarks.html#Benchmarks","page":"Benchmarks","title":"Benchmarks","text":"","category":"section"},{"location":"benchmarks.html#Benchmark-Guard","page":"Benchmarks","title":"Benchmark Guard","text":"","category":"section"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"To ensure some PR do not contain performance regression, we defined package benchmarks with PkgBenchmark in each component package, you can run the benchmark suite and compare the performance between different version and commits.","category":"page"},{"location":"benchmarks.html#Benchmark-with-Other-Packages","page":"Benchmarks","title":"Benchmark with Other Packages","text":"","category":"section"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"We also provide benchmarks comparing to other packages, you can find a complete benchmark results here: quantum-benchmarks","category":"page"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"a glance of Yao's benchmark comparing to other packages:","category":"page"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"(Image: relative-gate)","category":"page"},{"location":"benchmarks.html","page":"Benchmarks","title":"Benchmarks","text":"(Image: relative-circuit)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"EditURL = \"../../../examples/1.prepare-ghz-state/main.jl\"","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"(Image: )","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#example-ghz","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"First, you have to use this package in Julia.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"using Yao","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Now, we just define the circuit according to the circuit image below: (Image: ghz)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"circuit = chain(\n 4,\n put(1=>X),\n repeat(H, 2:4),\n control(2, 1=>X),\n control(4, 3=>X),\n control(3, 1=>X),\n control(4, 3=>X),\n repeat(H, 1:4),\n)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nchain\n├─ put on (1)\n│ └─ X\n├─ repeat on (2, 3, 4)\n│ └─ H\n├─ control(2)\n│ └─ (1,) X\n├─ control(4)\n│ └─ (3,) X\n├─ control(3)\n│ └─ (1,) X\n├─ control(4)\n│ └─ (3,) X\n└─ repeat on (1, 2, 3, 4)\n └─ H\n","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Let me explain what happens here.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Put-single-qubit-gate-X-to-location-1","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Put single qubit gate X to location 1","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"we have an X gate applied to the first qubit. We need to tell Yao to put this gate on the first qubit by","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"put(4, 1=>X)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nput on (1)\n└─ X","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"We use Julia's Pair to denote the gate and its location in the circuit, for two-qubit gate, you could also use a tuple of locations:","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"put(4, (1, 2)=>swap(2, 1, 2))","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nput on (1, 2)\n└─ put on (1, 2)\n └─ SWAP\n","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"But, wait, why there's no 4 in the definition above? This is because all the functions in Yao that requires to input the number of qubits as its first arguement could be lazy (curried), and let other constructors to infer the total number of qubits later, e.g","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"put(1=>X)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"(n -> put(n, 1 => X))","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"which will return a lambda that ask for a single arguement n.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"put(1=>X)(4)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nput on (1)\n└─ X","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Apply-the-same-gate-on-different-locations","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Apply the same gate on different locations","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"next we should put Hadmard gates on all locations except the 1st qubits.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"We provide repeat to apply the same block repeatly, repeat can take an iterator of desired locations, and like put, we can also leave the total number of qubits there.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"repeat(H, 2:4)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"(n -> repeat(n, H, 2:4...))","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Define-control-gates","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Define control gates","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"In Yao, we could define controlled gates by feeding a gate to control","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"control(4, 2, 1=>X)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\ncontrol(2)\n└─ (1,) X","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Like many others, you could leave the number of total qubits there, and infer it later.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"control(2, 1=>X)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"(n -> control(n, 2, 1 => X))","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Composite-each-part-together","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Composite each part together","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"This will create a ControlBlock, the concept of block in Yao basically just means quantum operators, since the quantum circuit itself is a quantum operator, we could create a quantum circuit by composite each part of.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Here, we use chain to chain each part together, a chain of quantum operators means to apply each operators one by one in the chain. This will create a ChainBlock.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"circuit = chain(\n 4,\n put(1=>X),\n repeat(H, 2:4),\n control(2, 1=>X),\n control(4, 3=>X),\n control(3, 1=>X),\n control(4, 3=>X),\n repeat(H, 1:4),\n)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"nqubits: 4\nchain\n├─ put on (1)\n│ └─ X\n├─ repeat on (2, 3, 4)\n│ └─ H\n├─ control(2)\n│ └─ (1,) X\n├─ control(4)\n│ └─ (3,) X\n├─ control(3)\n│ └─ (1,) X\n├─ control(4)\n│ └─ (3,) X\n└─ repeat on (1, 2, 3, 4)\n └─ H\n","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"You can check the type of it with typeof","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"typeof(circuit)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ChainBlock{2}","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Construct-GHZ-state-from-00...00","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Construct GHZ state from 00...00","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"For simulation, we provide a builtin register type called ArrayReg, we will use the simulated register in this example.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"First, let's create 0000, you can create it with zero_state","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"zero_state(4)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Or we also provide bit string literals to create arbitrary eigen state","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ArrayReg(bit\"0000\")","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"They will both create a register with Julia's builtin Array as storage.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html#Feed-Registers-to-Circuits","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Feed Registers to Circuits","text":"","category":"section"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"Circuits can be applied to registers with apply!","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"apply!(zero_state(4), circuit)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"or you can use pipe operator |>, when you want to chain several operations together, here we measure the state right after the circuit for 1000 times","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"results = zero_state(4) |> circuit |> r->measure(r, nshots=1000)\n\nusing StatsBase, Plots\n\nhist = fit(Histogram, Int.(results), 0:16)\nbar(hist.edges[1] .- 0.5, hist.weights, legend=:none)","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"GHZ state will collapse to 0000 or 1111.","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"","category":"page"},{"location":"generated/examples/1.prepare-ghz-state/index.html","page":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","title":"Prepare Greenberger–Horne–Zeilinger state with Quantum Circuit","text":"This page was generated using Literate.jl.","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"CurrentModule = Yao","category":"page"},{"location":"man/cuda.html#CUDA-extension-CuYao","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"","category":"section"},{"location":"man/cuda.html#Tutorial","page":"CUDA extension - CuYao","title":"Tutorial","text":"","category":"section"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"CuYao is a CUDA extension of Yao, which allows you to run Yao circuits on GPU. The usage of CuYao is similar to Yao, but with some extra APIs to upload and download registers between CPU and GPU:","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"cu(reg) to upload a registe reg to GPU, and\ncpu(cureg) to download a register cureg from GPU to CPU.","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"julia> using Yao, CUDA\n\n# create a register on GPU\njulia> cureg = rand_state(9; nbatch=1000) |> cu; # or `curand_state(9; nbatch=1000)`.\n\n# run a circuit on GPU\njulia> cureg |> put(9, 2=>Z);\n\n# measure the register on GPU\njulia> measure!(cureg)\n1000-element CuArray{DitStr{2, 9, Int64}, 1, CUDA.Mem.DeviceBuffer}:\n 110110100 ₍₂₎\n 000100001 ₍₂₎\n 111111001 ₍₂₎\n ⋮\n 010001101 ₍₂₎\n 000100110 ₍₂₎\n\n# download the register to CPU\njulia> reg = cureg |> cpu;","category":"page"},{"location":"man/cuda.html#Features","page":"CUDA extension - CuYao","title":"Features","text":"","category":"section"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"Supported gates:","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"general U(N) gate\ngeneral U(1) gate\nX, Y, Z gate\nT, S gate\nSWAP gate\ncontrol gates","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"Supported register operations:","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"measure!, measurereset!, measureremove!, select\nappendqudits!, appendqubits!\ninsertqudit!, insertqubits!\nfocus!, relax!\njoin\ndensity_matrix\nfidelity\nexpect","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"Autodiff:","category":"page"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"autodiff is supported when the only parameterized gates are rotation gates in a circuit.","category":"page"},{"location":"man/cuda.html#API","page":"CUDA extension - CuYao","title":"API","text":"","category":"section"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"cpu\ncurand_state\ncuzero_state\ncuproduct_state\ncuuniform_state\ncughz_state","category":"page"},{"location":"man/cuda.html#Yao.cpu","page":"CUDA extension - CuYao","title":"Yao.cpu","text":"cpu(cureg)\n\nDownload the register state from GPU to CPU.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.curand_state","page":"CUDA extension - CuYao","title":"Yao.curand_state","text":"curand_state([T=ComplexF64], n::Int; nbatch=1)\n\nThe GPU version of rand_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.cuzero_state","page":"CUDA extension - CuYao","title":"Yao.cuzero_state","text":"cuzero_state([T=ComplexF64], n::Int; nbatch=1)\n\nThe GPU version of zero_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.cuproduct_state","page":"CUDA extension - CuYao","title":"Yao.cuproduct_state","text":"cuproduct_state([T=ComplexF64], total::Int, bit_config::Integer; nbatch=NoBatch())\n\nThe GPU version of product_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.cuuniform_state","page":"CUDA extension - CuYao","title":"Yao.cuuniform_state","text":"cuuniform_state([T=ComplexF64], n::Int; nbatch=1)\n\nThe GPU version of uniform_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html#Yao.cughz_state","page":"CUDA extension - CuYao","title":"Yao.cughz_state","text":"cughz_state([T=ComplexF64], n::Int; nbatch=1)\n\nThe GPU version of ghz_state.\n\n\n\n\n\n","category":"function"},{"location":"man/cuda.html","page":"CUDA extension - CuYao","title":"CUDA extension - CuYao","text":"note: Note\nthe cu function is not documented in this module, but it is used to upload a register to GPU.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"EditURL = \"../../../examples/3.grover-search/main.jl\"","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"(Image: )","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Grover","page":"Grover Search","title":"Grover Search","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"using Yao\nusing Yao.EasyBuild: variational_circuit\nusing LinearAlgebra","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Grover-Step","page":"Grover Search","title":"Grover Step","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"A single grover step is consist of applying oracle circuit and reflection circuit. The reflection_circuit function takes the wave function generator U as the input and returns U|0><0|U'.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"function grover_step!(reg::AbstractRegister, oracle, U::AbstractBlock)\n apply!(reg |> oracle, reflect_circuit(U))\nend\n\nfunction reflect_circuit(gen::AbstractBlock)\n N = nqubits(gen)\n reflect0 = control(N, -collect(1:N-1), N=>-Z)\n chain(gen', reflect0, gen)\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"reflect_circuit (generic function with 1 method)","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"Compute the propotion of target states to estimate the number of iterations, which requires computing the output state.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"function solution_state(oracle, gen::AbstractBlock)\n N = nqubits(gen)\n reg= zero_state(N) |> gen\n reg.state[real.(statevec(ArrayReg(ones(ComplexF64, 1< oracle)) .> 0] .= 0\n normalize!(reg)\nend\n\nfunction num_grover_step(oracle, gen::AbstractBlock)\n N = nqubits(gen)\n reg = zero_state(N) |> gen\n ratio = abs2(solution_state(oracle, gen)'*reg)\n Int(round(pi/4/sqrt(ratio)))-1\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"num_grover_step (generic function with 1 method)","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Run","page":"Grover Search","title":"Run","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"First, we define the problem by an oracle, it finds bit string bit\"000001100100\".","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"num_bit = 12\noracle = matblock(Diagonal((v = ones(ComplexF64, 1< gen\n\ntarget_state = solution_state(oracle, gen)\n\nfor i = 1:num_grover_step(oracle, gen)\n grover_step!(reg, oracle, gen)\n overlap = abs(reg'*target_state)\n println(\"step $(i-1), overlap = $overlap\")\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"step 0, overlap = 0.04685974121093736\nstep 1, overlap = 0.0780487209558483\nstep 2, overlap = 0.10916148124670066\nstep 3, overlap = 0.14016763852852288\nstep 4, overlap = 0.17103691335084453\nstep 5, overlap = 0.20173915993747182\nstep 6, overlap = 0.23224439562572258\nstep 7, overlap = 0.26252283014636996\nstep 8, overlap = 0.29254489471570244\nstep 9, overlap = 0.322281270911289\nstep 10, overlap = 0.35170291930325104\nstep 11, overlap = 0.3807811078130809\nstep 12, overlap = 0.40948743977231195\nstep 13, overlap = 0.4377938816536402\nstep 14, overlap = 0.46567279044741594\nstep 15, overlap = 0.49309694065677034\nstep 16, overlap = 0.5200395508850146\nstep 17, overlap = 0.5464743099893477\nstep 18, overlap = 0.5723754027753314\nstep 19, overlap = 0.5977175352070423\nstep 20, overlap = 0.6224759591082774\nstep 21, overlap = 0.6466264963306958\nstep 22, overlap = 0.6701455623652912\nstep 23, overlap = 0.6930101893741392\nstep 24, overlap = 0.7151980486199263\nstep 25, overlap = 0.7366874722713579\nstep 26, overlap = 0.7574574745631494\nstep 27, overlap = 0.7774877722899375\nstep 28, overlap = 0.7967588046140988\nstep 29, overlap = 0.8152517521681291\nstep 30, overlap = 0.8329485554329328\nstep 31, overlap = 0.8498319323740713\nstep 32, overlap = 0.8658853953187506\nstep 33, overlap = 0.8810932670570639\nstep 34, overlap = 0.8954406961517668\nstep 35, overlap = 0.9089136714416339\nstep 36, overlap = 0.9214990357242339\nstep 37, overlap = 0.9331844986047592\nstep 38, overlap = 0.9439586484983656\nstep 39, overlap = 0.953810963774298\nstep 40, overlap = 0.9627318230309194\nstep 41, overlap = 0.9707125144916121\nstep 42, overlap = 0.9777452445123718\nstep 43, overlap = 0.983823145192787\nstep 44, overlap = 0.9889402810829753\nstep 45, overlap = 0.9930916549799182\nstep 46, overlap = 0.9962732128075449\nstep 47, overlap = 0.9984818475757891\nstep 48, overlap = 0.9997154024147601\n","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Rejection-Sampling","page":"Grover Search","title":"Rejection Sampling","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"In practise, it is often not possible to determine the number of iterations before actual running. we can use rejection sampling technique to avoid estimating the number of grover steps.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"In a single try, we apply the grover algorithm for nstep times.","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"function single_try(oracle, gen::AbstractBlock, nstep::Int; nbatch::Int)\n N = nqubits(gen)\n reg = zero_state(N+1; nbatch)\n focus(reg, (1:N...,)) do r\n r |> gen\n for i = 1:nstep\n grover_step!(r, oracle, gen)\n end\n return r\n end\n reg |> checker\n res = measure!(RemoveMeasured(), reg, (N+1))\n return res, reg\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"single_try (generic function with 1 method)","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"After running the grover search, we have a checker program that flips the ancilla qubit if the output is the desired value, we assume the checker program can be implemented in polynomial time. to gaurante the output is correct. We contruct a checker \"program\", if the result is correct, flip the ancilla qubit","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"ctrl = -collect(1:num_bit); ctrl[[3,6,7]] *= -1\nchecker = control(num_bit+1,ctrl, num_bit+1=>X)","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"nqubits: 13\ncontrol(¬1, ¬2, 3, ¬4, ¬5, 6, 7, ¬8, ¬9, ¬10, ¬11, ¬12)\n└─ (13,) X","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"The register is batched, with batch dimension nshot. focus! views the first 1-N qubts as system. For a batched register, measure! returns a vector of bitstring as output.","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Run-2","page":"Grover Search","title":"Run","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"maxtry = 100\nnshot = 3\n\nfor nstep = 0:maxtry\n println(\"number of iter = $nstep\")\n res, regi = single_try(oracle, gen, nstep; nbatch=3)\n\n # success!\n if any(==(1), res)\n overlap_final = viewbatch(regi, findfirst(==(1), res))'*target_state\n println(\"success, overlap = $(overlap_final)\")\n break\n end\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"number of iter = 0\nnumber of iter = 1\nnumber of iter = 2\nnumber of iter = 3\nnumber of iter = 4\nnumber of iter = 5\nnumber of iter = 6\nnumber of iter = 7\nsuccess, overlap = -1.0 + 0.0im\n","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"The final state has an overlap of 1 with the target state.","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Amplitude-Amplification","page":"Grover Search","title":"Amplitude Amplification","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"Given a circuit to generate a state, now we want to project out the subspace with [1,3,5,8,9,11,12] fixed to 1 and [4,6] fixed to 0. We can construct an oracle","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"evidense = [1, 3, -4, 5, -6, 8, 9, 11, 12]\nfunction inference_oracle(nbit::Int, locs::Vector{Int})\n control(nbit, locs[1:end-1], abs(locs[end]) => (locs[end]>0 ? Z : -Z))\nend\noracle = inference_oracle(nqubits(reg), evidense)","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"nqubits: 12\ncontrol(1, 3, ¬4, 5, ¬6, 8, 9, 11)\n└─ (12,) Z","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"We use a variational circuit generator defined in Yao.EasyBuild","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"gen = dispatch!(variational_circuit(num_bit), :random)\nreg = zero_state(num_bit) |> gen","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 12/12\n nlevel: 2","category":"page"},{"location":"generated/examples/3.grover-search/index.html#Run-3","page":"Grover Search","title":"Run","text":"","category":"section"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"solution = solution_state(oracle, gen)\nfor i = 1:num_grover_step(oracle, gen)\n grover_step!(reg, oracle, gen)\n println(\"step $(i-1), overlap = $(abs(reg'*solution))\")\nend","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"step 0, overlap = 0.11480007965675817\nstep 1, overlap = 0.19058324193670428\nstep 2, overlap = 0.2652457005602443\nstep 3, overlap = 0.33834841120466996\nstep 4, overlap = 0.40946150147259774\nstep 5, overlap = 0.4781667987090151\nstep 6, overlap = 0.5440602890192854\nstep 7, overlap = 0.6067544930281308\nstep 8, overlap = 0.6658807444092039\nstep 9, overlap = 0.7210913577866083\nstep 10, overlap = 0.7720616732602615\nstep 11, overlap = 0.8184919655324984\nstep 12, overlap = 0.8601092064095035\nstep 13, overlap = 0.89666867031338\nstep 14, overlap = 0.9279553733638201\nstep 15, overlap = 0.9537853375670116\nstep 16, overlap = 0.974006672677868\nstep 17, overlap = 0.9885004693737958\nstep 18, overlap = 0.997181498487807\n","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"","category":"page"},{"location":"generated/examples/3.grover-search/index.html","page":"Grover Search","title":"Grover Search","text":"This page was generated using Literate.jl.","category":"page"},{"location":"man/automatic_differentiation.html#Automatic-Differentiation","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"","category":"section"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"Yao currently contains builtin automatic differentiation engine (an operator overloading based) especially for quantum circuits. It uses the reversible context of quantum computation to optimize the performance during simulation, thus you may find this is way faster than any other AD engine at the moment.","category":"page"},{"location":"man/automatic_differentiation.html#Builtin-Reverse-mode-AD-engine-for-simulation","page":"Automatic Differentiation","title":"Builtin Reverse mode AD engine for simulation","text":"","category":"section"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"As for expectation, the usage is pretty simple, since the evluation of expectations are just","category":"page"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"expect(H, rand_state(10)=>circuit)","category":"page"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"to get the gradients, simply add an adjoint","category":"page"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"expect'(H, rand_state(10)=>circuit)","category":"page"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"which will return the pair of gradients, one is the gradient of input register and the other is the gradient of circuit parameters.","category":"page"},{"location":"man/automatic_differentiation.html#Integration-with-General-purpose-AD-engine","page":"Automatic Differentiation","title":"Integration with General purpose AD engine","text":"","category":"section"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"The builtin AD engine for Yao only provides the differentiation of quantum circuits, but you can plug it into a general AD engine, such as Zygote, since we have ported these rules to ChainRules.","category":"page"},{"location":"man/automatic_differentiation.html#APIs","page":"Automatic Differentiation","title":"APIs","text":"","category":"section"},{"location":"man/automatic_differentiation.html","page":"Automatic Differentiation","title":"Automatic Differentiation","text":"Modules = [YaoBlocks.AD]\nOrder = [:function, :macro]","category":"page"},{"location":"man/automatic_differentiation.html#YaoBlocks.AD.apply_back-Tuple{Tuple{AbstractArrayReg, AbstractArrayReg}, AbstractBlock}","page":"Automatic Differentiation","title":"YaoBlocks.AD.apply_back","text":"apply_back(st::Tuple{<:AbstractArrayReg, <:AbstractArrayReg}, block::AbstractBlock; kwargs...) -> (out, outδ), paramsδ\n\nThe backward function of apply!. Returns a tuple of ((input register, gradient of input register), parameter gradients)\n\n\n\n\n\n","category":"method"},{"location":"man/automatic_differentiation.html#YaoBlocks.AD.generator-Tuple{RotationGate}","page":"Automatic Differentiation","title":"YaoBlocks.AD.generator","text":"generator(rot::Rotor) -> AbstractBlock\n\nReturn the generator of rotation block.\n\n\n\n\n\n","category":"method"},{"location":"man/automatic_differentiation.html#YaoBlocks.AD.mat_back-Union{Tuple{T}, Tuple{AbstractBlock, AbstractMatrix{T}}} where T","page":"Automatic Differentiation","title":"YaoBlocks.AD.mat_back","text":"mat_back([::Type{T}, ]block::AbstractBlock, adjm::AbstractMatrix) -> Vector\n\nThe backward function of mat. Returns the gradients of parameters.\n\n\n\n\n\n","category":"method"},{"location":"man/automatic_differentiation.html#YaoBlocks.AD.rotgrad-Union{Tuple{T}, Tuple{D}, Tuple{Type{T}, RotationGate{D, T, GT} where {T, GT<:AbstractBlock{D}}}} where {D, T}","page":"Automatic Differentiation","title":"YaoBlocks.AD.rotgrad","text":"The matrix gradient of a rotation block.\n\n\n\n\n\n","category":"method"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"EditURL = \"../../../examples/6.quantum-circuit-born-machine/main.jl\"","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"(Image: )","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#qcbm","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Yao is designed with variational quantum circuits in mind, and this tutorial will introduce how to use Yao for this kind of task by implementing a quantum circuit born machine described in Jin-Guo Liu, Lei Wang (2018)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"let's use the packages first","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"using Yao, LinearAlgebra, Plots","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Training-Target","page":"Quantum Circuit Born Machine","title":"Training Target","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"In this tutorial, we will ask the variational circuit to learn the most basic distribution: a guassian distribution. It is defined as follows:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"f(x left mu sigma^2right) = frac1sqrt2pisigma^2 e^-frac(x-mu)^22sigma^2","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We implement it as gaussian_pdf:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"function gaussian_pdf(x, μ::Real, σ::Real)\n pl = @. 1 / sqrt(2pi * σ^2) * exp(-(x - μ)^2 / (2 * σ^2))\n pl / sum(pl)\nend\npg = gaussian_pdf(1:1<<6, 1<<5-0.5, 1<<4);","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We can plot the distribution, it looks like","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Plots.plot(pg)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Create-the-Circuit","page":"Quantum Circuit Born Machine","title":"Create the Circuit","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"A quantum circuit born machine looks like the following:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"(Image: differentiable ciruit)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"It is composited by two different layers: rotation layer and entangler layer.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Rotation-Layer","page":"Quantum Circuit Born Machine","title":"Rotation Layer","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Arbitrary rotation is built with Rotation Gate on Z, X, Z axis with parameters.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Rz(theta) cdot Rx(theta) cdot Rz(theta)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Since our input will be a 0dots 0rangle state. The first layer of arbitrary rotation can just use Rx(theta) cdot Rz(theta) and the last layer of arbitrary rotation could just use Rz(theta)cdot Rx(theta)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"In 幺, every Hilbert operator is a block type, this ncludes all quantum gates and quantum oracles. In general, operators appears in a quantum circuit can be divided into Composite Blocks and Primitive Blocks.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We follow the low abstraction principle and thus each block represents a certain approach of calculation. The simplest Composite Block is a Chain Block, which chains other blocks (oracles) with the same number of qubits together. It is just a simple mathematical composition of operators with same size. e.g.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"textchain(X Y Z) iff X cdot Y cdot Z","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We can construct an arbitrary rotation block by chain Rz, Rx, Rz together.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"chain(Rz(0.0), Rx(0.0), Rz(0.0))","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"nqubits: 1\nchain\n├─ rot(Z, 0.0)\n├─ rot(X, 0.0)\n└─ rot(Z, 0.0)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Rx, Rz will construct new rotation gate, which are just shorthands for rot(X, 0.0), etc.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Then let's chain them up","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"layer(nbit::Int, x::Symbol) = layer(nbit, Val(x))\nlayer(nbit::Int, ::Val{:first}) = chain(nbit, put(i=>chain(Rx(0), Rz(0))) for i = 1:nbit);","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We do not need to feed the first n parameter into put here. All factory methods can be lazy evaluate the first arguements, which is the number of qubits. It will return a lambda function that requires a single interger input. The instance of desired block will only be constructed until all the information is filled. When you filled all the information in somewhere of the declaration, 幺 will be able to infer the others. We will now define the rest of rotation layers","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"layer(nbit::Int, ::Val{:last}) = chain(nbit, put(i=>chain(Rz(0), Rx(0))) for i = 1:nbit)\nlayer(nbit::Int, ::Val{:mid}) = chain(nbit, put(i=>chain(Rz(0), Rx(0), Rz(0))) for i = 1:nbit);","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Entangler","page":"Quantum Circuit Born Machine","title":"Entangler","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Another component of quantum circuit born machine are several CNOT operators applied on different qubits.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"entangler(pairs) = chain(control(ctrl, target=>X) for (ctrl, target) in pairs);","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We can then define such a born machine","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"function build_circuit(n, nlayers, pairs)\n circuit = chain(n)\n push!(circuit, layer(n, :first))\n for i in 2:nlayers\n push!(circuit, cache(entangler(pairs)))\n push!(circuit, layer(n, :mid))\n end\n push!(circuit, cache(entangler(pairs)))\n push!(circuit, layer(n, :last))\n return circuit\nend","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"build_circuit (generic function with 1 method)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We use the method cache here to tag the entangler block that it should be cached after its first run, because it is actually a constant oracle. Let's see what will be constructed","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"build_circuit(4, 1, [1=>2, 2=>3, 3=>4])","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"nqubits: 4\nchain\n├─ chain\n│ ├─ put on (1)\n│ │ └─ chain\n│ │ ├─ rot(X, 0.0)\n│ │ └─ rot(Z, 0.0)\n│ ├─ put on (2)\n│ │ └─ chain\n│ │ ├─ rot(X, 0.0)\n│ │ └─ rot(Z, 0.0)\n│ ├─ put on (3)\n│ │ └─ chain\n│ │ ├─ rot(X, 0.0)\n│ │ └─ rot(Z, 0.0)\n│ └─ put on (4)\n│ └─ chain\n│ ├─ rot(X, 0.0)\n│ └─ rot(Z, 0.0)\n├─ [cached] chain\n│ ├─ control(1)\n│ │ └─ (2,) X\n│ ├─ control(2)\n│ │ └─ (3,) X\n│ └─ control(3)\n│ └─ (4,) X\n└─ chain\n ├─ put on (1)\n │ └─ chain\n │ ├─ rot(Z, 0.0)\n │ └─ rot(X, 0.0)\n ├─ put on (2)\n │ └─ chain\n │ ├─ rot(Z, 0.0)\n │ └─ rot(X, 0.0)\n ├─ put on (3)\n │ └─ chain\n │ ├─ rot(Z, 0.0)\n │ └─ rot(X, 0.0)\n └─ put on (4)\n └─ chain\n ├─ rot(Z, 0.0)\n └─ rot(X, 0.0)\n","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#MMD-Loss-and-Gradients","page":"Quantum Circuit Born Machine","title":"MMD Loss & Gradients","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"The MMD loss is describe below:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"beginaligned\nmathcalL = left sum_x p theta(x) phi(x) - sum_x pi(x) phi(x) right^2\n = langle K(x y) rangle_x sim p_theta ysim p_theta - 2 langle K(x y) rangle_xsim p_theta ysim pi + langle K(x y) rangle_xsimpi ysimpi\nendaligned","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"We will use a squared exponential kernel here.","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"struct RBFKernel\n σ::Float64\n m::Matrix{Float64}\nend\n\nfunction RBFKernel(σ::Float64, space)\n dx2 = (space .- space').^2\n return RBFKernel(σ, exp.(-1/2σ * dx2))\nend\n\nkexpect(κ::RBFKernel, x, y) = x' * κ.m * y","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"kexpect (generic function with 1 method)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"There are two different way to define the loss:","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"In simulation we can use the probability distribution of the state directly","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"get_prob(qcbm) = probs(zero_state(nqubits(qcbm)) |> qcbm)\n\nfunction loss(κ, c, target)\n p = get_prob(c) - target\n return kexpect(κ, p, p)\nend","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"loss (generic function with 1 method)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Or if you want to simulate the whole process with measurement (which is entirely physical), you should define the loss with measurement results, for convenience we directly use the simulated results as our loss","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html#Gradients","page":"Quantum Circuit Born Machine","title":"Gradients","text":"","category":"section"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"the gradient of MMD loss is","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"beginaligned\nfracpartial mathcalLpartial theta^i_l = langle K(x y) rangle_xsim p_theta^+ ysim p_theta - langle K(x y) rangle_xsim p_theta^- ysim p_theta\n- langle K(x y) rangle _xsim p_theta^+ ysimpi + langle K(x y) rangle_xsim p_theta^- ysimpi\nendaligned","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"which can be implemented as","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"function gradient(qcbm, κ, ptrain)\n n = nqubits(qcbm)\n prob = get_prob(qcbm)\n grad = zeros(Float64, nparameters(qcbm))\n\n count = 1\n for k in 1:2:length(qcbm), each_line in qcbm[k], gate in content(each_line)\n dispatch!(+, gate, π/2)\n prob_pos = probs(zero_state(n) |> qcbm)\n\n dispatch!(-, gate, π)\n prob_neg = probs(zero_state(n) |> qcbm)\n\n dispatch!(+, gate, π/2) # set back\n\n grad_pos = kexpect(κ, prob, prob_pos) - kexpect(κ, prob, prob_neg)\n grad_neg = kexpect(κ, ptrain, prob_pos) - kexpect(κ, ptrain, prob_neg)\n grad[count] = grad_pos - grad_neg\n count += 1\n end\n return grad\nend","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"gradient (generic function with 1 method)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"Now let's setup the training","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"import Optimisers\nqcbm = build_circuit(6, 10, [1=>2, 3=>4, 5=>6, 2=>3, 4=>5, 6=>1])\ndispatch!(qcbm, :random) # initialize the parameters\n\nκ = RBFKernel(0.25, 0:2^6-1)\npg = gaussian_pdf(1:1<<6, 1<<5-0.5, 1<<4);\nopt = Optimisers.setup(Optimisers.ADAM(0.01), parameters(qcbm));\n\nfunction train(qcbm, κ, opt, target)\n history = Float64[]\n for _ in 1:100\n push!(history, loss(κ, qcbm, target))\n ps = parameters(qcbm)\n Optimisers.update!(opt, ps, gradient(qcbm, κ, target))\n dispatch!(qcbm, ps)\n end\n return history\nend\n\nhistory = train(qcbm, κ, opt, pg)\ntrained_pg = probs(zero_state(nqubits(qcbm)) |> qcbm)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"64-element Vector{Float64}:\n 0.004446054657298753\n 0.004331157645300311\n 0.005835850732537775\n 0.005836326060827502\n 0.006572217842013155\n 0.0075577836174582904\n 0.008049808007401531\n 0.008851524894909079\n 0.009743607822144324\n 0.010528610129109328\n 0.011478611161272094\n 0.012431473989718075\n 0.013292480438956596\n 0.014546249912351756\n 0.01525412618005244\n 0.016560007178163545\n 0.017336804464180428\n 0.018419677210259496\n 0.019281125874896513\n 0.020026705759927953\n 0.020943354659739614\n 0.021945779730180776\n 0.02265330315848815\n 0.023451074736356034\n 0.02395534540947105\n 0.02455544195711308\n 0.024956887715311314\n 0.025591250870995643\n 0.025880777464795172\n 0.02601395500724068\n 0.026055570857316045\n 0.026017126001370815\n 0.026024252450169285\n 0.025849329915048843\n 0.02560132889392464\n 0.025129103668838446\n 0.024634149085080933\n 0.023981785924987162\n 0.023328590610284416\n 0.022669945822563688\n 0.022006605927837153\n 0.020996101110117016\n 0.020020881452901977\n 0.019331699335207675\n 0.018092360081346556\n 0.017423526856525047\n 0.016177651572765794\n 0.015236136561980132\n 0.014483802363532233\n 0.01345447804491319\n 0.012658255566757901\n 0.011566055592914945\n 0.010704366966141325\n 0.009898455311057716\n 0.00867751468056457\n 0.008222897629418413\n 0.007283275767419372\n 0.006682452030052422\n 0.006074115300337746\n 0.005354124439857948\n 0.00433052204952558\n 0.004399982209411372\n 0.003744869866319961\n 0.0035613117650391936","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"The history of training looks like below","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"title!(\"training history\")\nxlabel!(\"steps\"); ylabel!(\"loss\")\nPlots.plot(history)","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"And let's check what we got","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"fig2 = Plots.plot(1:1<<6, trained_pg; label=\"trained\")\nPlots.plot!(fig2, 1:1<<6, pg; label=\"target\")\ntitle!(\"distribution\")\nxlabel!(\"x\"); ylabel!(\"p\")","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"So within 50 steps, we got a pretty close estimation of our target distribution!","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"","category":"page"},{"location":"generated/examples/6.quantum-circuit-born-machine/index.html","page":"Quantum Circuit Born Machine","title":"Quantum Circuit Born Machine","text":"This page was generated using Literate.jl.","category":"page"},{"location":"quick-start.html#Quick-Start","page":"Quick Start","title":"Quick Start","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"In this quick start, we list several common use cases for Yao before you go deeper into the manual.","category":"page"},{"location":"quick-start.html#Create-a-quantum-register/state","page":"Quick Start","title":"Create a quantum register/state","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"A register is an object that describes a device with an internal state. See Registers for more details. Yao use registers to represent quantum states. The most common register is the ArrayReg, you can create it by feeding a state vector to it, e.g","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"using Yao\nArrayReg(randn(ComplexF64, 2^3)) # a random unnormalized 3-qubit state\nzero_state(5) # |00000⟩\nrand_state(5) # a random state\nproduct_state(bit\"10100\") # |10100⟩\nghz_state(5) # (|00000⟩ + |11111⟩)/√2","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"the internal quantum state can be accessed via statevec method","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"statevec(ghz_state(2))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"for more functionalities about registers please refer to the manual of Registers.","category":"page"},{"location":"quick-start.html#Create-quantum-circuit","page":"Quick Start","title":"Create quantum circuit","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"Yao introduces an abstract representation for linear maps, called \"block\"s, which can be used to represent quantum circuits, Hamiltonians, and other quantum operations. The following code creates a 2-qubit circuit","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"chain(2, put(1=>H), put(2=>X))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"where H gate is at 1st qubit, X gate is at 2nd qubit. A more advanced example is the quantum Fourier transform circuit","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1)))) # a cphase gate\nB(n, k) = chain(n, j==k ? put(k=>H) : A(j, k) for j in k:n)\nqft(n) = chain(B(n, k) for k in 1:n)\ncircuit = qft(3) # a 3-qubit QFT circuit\nmat(circuit) # the matrix representation of the circuit\napply!(zero_state(3), circuit) # apply the circuit to a zero state","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"More details about available blocks can be found in the manual of Blocks.","category":"page"},{"location":"quick-start.html#Create-Hamiltonian","page":"Quick Start","title":"Create Hamiltonian","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"We can create a simple Ising Hamiltonian on 1D chain as following","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"h = sum([kron(5, i=>Z, mod1(i+1, 5)=>Z) for i in 1:5]) # a 5-qubit Ising Hamiltonian\nmat(h) # the matrix representation of the Hamiltonian","category":"page"},{"location":"quick-start.html#Differentiating-a-quantum-circuit","page":"Quick Start","title":"Differentiating a quantum circuit","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"Yao has its own automatic differentiation rule implemented, this allows one obtain gradients of a loss function by simply putting a ' mark following expect or fidelity, e.g","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"To obtain the gradient of the quantum Fourier transform circuit with respect to its parameters, one can use the following code","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"grad_state, grad_circuit_params = expect'(kron(X, X, I2) + kron(I2, X, X), zero_state(3)=>qft(3))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"where kron(X, X, I2) + kron(I2, X, X) is the target Hamiltonian, zero_state(3) is the initial state, qft(3) is the quantum Fourier transform circuit. The return value is a vector, each corresponding to the gradient of the loss function with respect to a parameter in the circuit. The list of parameters can be obtained by parameters function.","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"parameters(qft(3))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"To obtain the gradient of the fidelity between a state parameterized by a quantum circuit and a target state, one can use the following code","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"((grad_state1, grad_circuit1), grad_state2) = fidelity'(zero_state(3)=>qft(3), ghz_state(3))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"where zero_state(3) is the initial state, qft(3) is the quantum Fourier transform circuit, ghz_state(3) is the target state.","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"The automatic differentiation functionality can also be accessed by interfacing with the machine learning libraries Zygote.","category":"page"},{"location":"quick-start.html#Plot-quantum-circuits","page":"Quick Start","title":"Plot quantum circuits","text":"","category":"section"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"The component package YaoPlots provides plotting for quantum circuits and ZX diagrams. You can use it to visualize your quantum circuits in VSCode, Jupyter notebook or Pluto notebook.","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"using Yao.EasyBuild, Yao.YaoPlots\nusing Compose\n\n# show a qft circuit\nvizcircuit(qft_circuit(5))","category":"page"},{"location":"quick-start.html","page":"Quick Start","title":"Quick Start","text":"More details about the plotting can be found in the manual: Quantum Circuit Visualization.","category":"page"},{"location":"notes.html#How-to-overload-exist-method-for-a-block","page":"How to overload exist method for a block","title":"How to overload exist method for a block","text":"","category":"section"},{"location":"notes.html","page":"How to overload exist method for a block","title":"How to overload exist method for a block","text":"every block has two method: mat & apply!, overload mat to define how to gather this block's matrix form, overload apply! to define how to apply this block to a register.","category":"page"},{"location":"notes.html","page":"How to overload exist method for a block","title":"How to overload exist method for a block","text":"Prototypes:","category":"page"},{"location":"notes.html","page":"How to overload exist method for a block","title":"How to overload exist method for a block","text":"apply!(reg, block)\nmat(block)","category":"page"},{"location":"performancetips.html#Performance-Tips","page":"Performance Tips","title":"Performance Tips","text":"","category":"section"},{"location":"performancetips.html#Use-the-correct-block-types","page":"Performance Tips","title":"Use the correct block types","text":"","category":"section"},{"location":"performancetips.html#put-v.s.-subroutine","page":"Performance Tips","title":"put v.s. subroutine","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"While both blocks maps a subblock to a subset of qudits, their implementations are purposes are quite different. The put block applies the gate in a in-place manner, which requires the static matrix representation of its subblock. It works the best when the subblock is small.","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"The subroutine block is for running a sub-program in a subset of qubits. It first sets target qubits as active qubits using the focus! function, then apply the gates on active qubits. Finally, it unsets the active qubits with the relax! function.","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"julia> using Yao\n\njulia> reg = rand_state(20);\n\njulia> @time apply(reg, put(20, 1:6=>EasyBuild.qft_circuit(6))); # second run\n 0.070245 seconds (1.32 k allocations: 16.525 MiB)\n\njulia> @time apply(reg, subroutine(20, EasyBuild.qft_circuit(6), 1:6)); # second run\n 0.036840 seconds (1.07 k allocations: 16.072 MiB)","category":"page"},{"location":"performancetips.html#repeat-v.s.-put","page":"Performance Tips","title":"repeat v.s. put","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"repeat block is not only an alias of a chain of put, sometimes it can provide speed ups due to the different implementations.","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"julia> reg = rand_state(20);\n\njulia> @time apply!(reg, repeat(20, X));\n 0.002252 seconds (5 allocations: 656 bytes)\n\njulia> @time apply!(reg, chain([put(20, i=>X) for i=1:20]));\n 0.049362 seconds (82.48 k allocations: 4.694 MiB, 47.11% compilation time)","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"Other gates accelerated by repeat include: X, Y, Z, S, T, Sdag, and Tdag.","category":"page"},{"location":"performancetips.html#Diagonal-matrix-in-time_evole","page":"Performance Tips","title":"Diagonal matrix in time_evole","text":"","category":"section"},{"location":"performancetips.html#Register-storage","page":"Performance Tips","title":"Register storage","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"One can use transposed storage and normal storage for computing batched registers. The transposed storage is used by default because it is often faster in practice. One can use transpose_storage to convert the storage.","category":"page"},{"location":"performancetips.html#Multithreading","page":"Performance Tips","title":"Multithreading","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"Multithreading can be switched on by starting Julia in with a global environment variable JULIA_NUM_THREAD","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"$ JULIA_NUM_THREAD=4 julia xxx.jl","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"Check the Julia Multi-Treading manual for details.","category":"page"},{"location":"performancetips.html#GPU-backend","page":"Performance Tips","title":"GPU backend","text":"","category":"section"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"The GPU backend is supported in CuYao.","category":"page"},{"location":"performancetips.html","page":"Performance Tips","title":"Performance Tips","text":"julia> using Yao, CuYao\n\njulia> reg = CuYao.cu(rand_state(20));\n\njulia> circ = Yao.EasyBuild.qft_circuit(20);\n\njulia> apply!(reg, circ)\nArrayReg{2, ComplexF64, CuArray...}\n active qubits: 20/20\n nlevel: 2","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"CurrentModule = YaoArrayRegister\nDocTestSetup = quote\n using Yao\n using BitBasis\n using YaoAPI\n using YaoBlocks\n using YaoArrayRegister\nend","category":"page"},{"location":"man/registers.html#registers","page":"Quantum Registers","title":"Quantum Registers","text":"","category":"section"},{"location":"man/registers.html#Constructing-quantum-states","page":"Quantum Registers","title":"Constructing quantum states","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"A quantum register is a quantum state or a batch of quantum states. Qubits in a Yao register can be active or inactive. Only active qubits are visible to quantum operators, which enables applying quantum operators on a subset of qubits. For example, Suppose we want to run a quantum Fourier transformation circuit of size 4 on qubits (1, 3, 5, 7) with the focus! function, we first set these qubits to active qubits the rest to inactive, then we apply the circuit on the active qubits, and finally we switch back to the original configuration with the relax! function.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"Yao provides two types of quantum registers ArrayReg and BatchedArrayReg. Both use matrices as the storage. For example, for a quantum register with a active qubits, r remaining qubits and batch size b, the storage is as follows.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"(Image: )","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The first dimension of size 2^a is for active qubits, only this subset of qubits are allowed to interact with quantum operators. Since we reshaped the state vector into a matrix, applying a quantum operator can be conceptually represented as a matrix-matrix multiplication.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"Various quantum states can be created with the following functions.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"using Yao\nreg = ArrayReg([0, 1, -1+0.0im, 0]) # a unnormalized Bell state |01⟩ - |10⟩\nstatevec(reg) # a quantum state is represented as a vector\nprint_table(reg)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_zero = zero_state(3) # create a zero state |000⟩\nprint_table(reg_zero)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_rand = rand_state(ComplexF32, 3) # a random state","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_uniform = uniform_state(ComplexF32, 3) # a uniform state\nprint_table(reg_uniform)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_prod = product_state(bit\"110\") # a product state\nbit\"110\"[3] # the bit string is in little-endian format\nprint_table(reg_prod)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_ghz = ghz_state(3) # a GHZ state\nprint_table(reg_ghz)\nvon_neumann_entropy(reg_ghz, (1, 3)) / log(2) # entanglement entropy between qubits (1, 3) and (2,)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_rand3 = rand_state(3, nlevel=3) # a random qutrit state\nreg_prod3 = product_state(dit\"120;3\") # a qudit product state, what follows \";\" symbol denotes the number of levels\nprint_table(reg_prod3)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg_batch = rand_state(3; nbatch=2) # a batch of 2 random qubit states\nprint_table(reg_batch)\nreg_view = viewbatch(reg_batch, 1) # view the first state in the batch\nprint_table(reg_view)","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg = rand_state(3; nlevel=4, nbatch=2)\nnqudits(reg) # the total number of qudits\nnactive(reg) # the number of active qubits\nnremain(reg) # the number of remaining qubits\nnbatch(reg) # the batch size\nnlevel(reg) # the number of levels of each qudit\nbasis(reg) # the basis of the register\nfocus!(reg, 1:2) # set on the first two qubits as active\nnactive(reg) # the number of active qubits\nbasis(reg) # the basis of the register\nrelax!(reg) # set all qubits as active\nnactive(reg) # the number of active qubits\nreorder!(reg, (3,1,2)) # reorder the qubits\n\nreg1 = product_state(bit\"111\");\nreg2 = ghz_state(3);\nfidelity(reg1, reg2) # the fidelity between two states\ntracedist(reg1, reg2) # the trace distance between two states","category":"page"},{"location":"man/registers.html#Arithmetic-operations","page":"Quantum Registers","title":"Arithmetic operations","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The list of arithmetic operations for ArrayReg include ","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"+\n-\n*\n/ (scalar)\nadjoint","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg1 = rand_state(3)\nreg2 = rand_state(3)\nreg3 = reg1 + reg2 # addition\nnormalize!(reg3) # normalize the state\nisnormalized(reg3) # check if the state is normalized\nreg1 - reg2 # subtraction\nreg1 * 2 # scalar multiplication\nreg1 / 2 # scalar division\nreg1' # adjoint\nreg1' * reg1 # inner product","category":"page"},{"location":"man/registers.html#Register-operations","page":"Quantum Registers","title":"Register operations","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg0 = rand_state(3)\nappend_qudits!(reg0, 2) # append 2 qubits\ninsert_qudits!(reg0, 2, 2) # insert 2 qubits at the 2nd position","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"Comparing with using matrix multiplication for quantum simulation, using specialized instructions are much faster and memory efficient. These instructions are specified with the instruct! function.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg = zero_state(2)\ninstruct!(reg, Val(:H), (1,)) # apply a Hadamard gate on the first qubit\nprint_table(reg)","category":"page"},{"location":"man/registers.html#Measurement","page":"Quantum Registers","title":"Measurement","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"We use the measure! function returns the measurement outcome and collapses the state after the measurement. We also have some \"cheating\" version measure that does not collapse states to facilitate classical simulation.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"measure!(reg0, 1) # measure the qubit, the state collapses\nmeasure!(reg0) # measure all qubits\nmeasure(reg0, 3) # measure the qubit at location 3, the state does not collapse (hacky)\nreorder!(reg0, 7:-1:1) # reorder the qubits\nmeasure!(reg0)\ninvorder!(reg0) # reverse the order of qubits\nmeasure!(reg0)\nmeasure!(RemoveMeasured(), reg0, 2:4) # remove the measured qubits\nreg0\n\nreg1 = ghz_state(3)\nselect!(reg1, bit\"111\") # post-select the |111⟩ state\nisnormalized(reg1) # check if the state is normalized","category":"page"},{"location":"man/registers.html#Density-matrices","page":"Quantum Registers","title":"Density matrices","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"reg = rand_state(3)\nrho = density_matrix(reg) # the density matrix of the state\nrand_density_matrix(3) # a random density matrix\ncompletely_mixed_state(3) # a completely mixed state\npartial_tr(rho, 1) # partial trace on the first qubit\npurify(rho) # purify the state\nvon_neumann_entropy(rho) # von Neumann entropy\nmutual_information(rho, 1, 2) # mutual information between qubits 1 and 2","category":"page"},{"location":"man/registers.html#API","page":"Quantum Registers","title":"API","text":"","category":"section"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The constructors and functions for quantum registers are listed below.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"AbstractRegister\nAbstractArrayReg\nArrayReg\nBatchedArrayReg","category":"page"},{"location":"man/registers.html#YaoAPI.AbstractRegister","page":"Quantum Registers","title":"YaoAPI.AbstractRegister","text":"AbstractRegister{D}\n\nAbstract type for quantum registers. Type parameter D is the number of levels in each qudit. For qubits, D = 2.\n\nRequired methods\n\ninstruct!\nnqudits\nnactive\ninsert_qubits!\nappend_qubits!\nfocus!\nrelax!\nreorder!\ninvorder!\n\nOptional methods\n\nnlevel\nnremain\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html#YaoArrayRegister.AbstractArrayReg","page":"Quantum Registers","title":"YaoArrayRegister.AbstractArrayReg","text":"AbstractArrayReg\n\nAbstract type for quantum registers that are represented by an array.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html#YaoArrayRegister.ArrayReg","page":"Quantum Registers","title":"YaoArrayRegister.ArrayReg","text":"ArrayReg{D,T,MT<:AbstractMatrix{T}} <: AbstractArrayRegister{D}\nArrayReg{D}(raw)\nArrayReg(raw::AbstractVecOrMat; nlevel=2)\nArrayReg(r::ArrayReg)\n\nSimulated full amplitude register type, it uses an array to represent corresponding one or a batch of quantum states. T is the numerical type for each amplitude, it is ComplexF64 by default.\n\nwarning: Warning\nArrayReg constructor will not normalize the quantum state. If you need a normalized quantum state remember to use normalize!(register) on the register.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html#YaoArrayRegister.BatchedArrayReg","page":"Quantum Registers","title":"YaoArrayRegister.BatchedArrayReg","text":"BatchedArrayReg{D,T,MT<:AbstractMatrix{T}} <: AbstractArrayReg{D}\nBatchedArrayReg(raw, nbatch; nlevel=2)\nBatchedArrayReg{D}(raw, nbatch)\n\nSimulated batched full amplitude register type, it uses an array to represent corresponding one or a batch of quantum states. T is the numerical type for each amplitude, it is ComplexF64 by default.\n\nwarning: Warning\nBatchedArrayReg constructor will not normalize the quantum state. If you need a normalized quantum state remember to use normalize!(register) on the register.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"arrayreg\nproduct_state\nzero_state\nzero_state_like\nrand_state\nuniform_state\nghz_state\nclone","category":"page"},{"location":"man/registers.html#YaoArrayRegister.arrayreg","page":"Quantum Registers","title":"YaoArrayRegister.arrayreg","text":"arrayreg(state; nbatch::Union{Integer,NoBatch}=NoBatch(), nlevel::Integer=2)\n\nCreate an array register, if nbatch is a integer, it will return a BatchedArrayReg.\n\n\n\n\n\narrayreg([T=ComplexF64], bit_str; nbatch=NoBatch())\n\nConstruct an array register from bit string literal. For bit string literal please read @bit_str.\n\nExamples\n\njulia> arrayreg(bit\"1010\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> arrayreg(ComplexF32, bit\"1010\")\nArrayReg{2, ComplexF32, Array...}\n active qubits: 4/4\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.product_state","page":"Quantum Registers","title":"YaoArrayRegister.product_state","text":"product_state([T=ComplexF64], dit_str; nbatch=NoBatch(), no_transpose_storage=false)\nproduct_state([T=ComplexF64], nbits::Int, val::Int; nbatch=NoBatch(), nlevel=2, no_transpose_storage=false)\nproduct_state([T=ComplexF64], vector; nbatch=NoBatch(), nlevel=2, no_transpose_storage=false)\n\nCreate an ArrayReg of product state. The configuration can be specified with a dit string, which can be defined with @bit_str or @dit_str. Or equivalently, it can be specified explicitly with nbits, val and nlevel. See also zero_state, rand_state, uniform_state.\n\nExamples\n\njulia> reg = product_state(dit\"120;3\"; nbatch=2)\nBatchedArrayReg{3, ComplexF64, Transpose...}\n active qudits: 3/3\n nlevel: 3\n nbatch: 2\n\njulia> measure(reg)\n1×2 Matrix{BitBasis.DitStr64{3, 3}}:\n 120 ₍₃₎ 120 ₍₃₎\n\njulia> product_state(bit\"100\"; nbatch=2);\n\njulia> r1 = product_state(ComplexF32, bit\"001\"; nbatch=2);\n\njulia> r2 = product_state(ComplexF32, [1, 0, 0]; nbatch=2);\n\njulia> r3 = product_state(ComplexF32, 3, 0b001; nbatch=2);\n\njulia> r1 ≈ r2 # because we read bit strings from right to left, vectors from left to right.\ntrue\n\njulia> r1 ≈ r3\ntrue\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.zero_state","page":"Quantum Registers","title":"YaoArrayRegister.zero_state","text":"zero_state([T=ComplexF64], n::Int; nbatch::Int=NoBatch())\n\nCreate an AbstractArrayReg that initialized to state 0rangle^otimes n. See also product_state, rand_state, uniform_state and ghz_state.\n\nExamples\n\njulia> zero_state(4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> zero_state(ComplexF32, 4)\nArrayReg{2, ComplexF32, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> zero_state(ComplexF32, 4; nbatch=3)\nBatchedArrayReg{2, ComplexF32, Transpose...}\n active qubits: 4/4\n nlevel: 2\n nbatch: 3\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.zero_state_like","page":"Quantum Registers","title":"YaoArrayRegister.zero_state_like","text":"zero_state_like(register, n) -> AbstractRegister\n\nCreate a register initialized to zero from an existing one.\n\nExamples\n\njulia> reg = rand_state(3; nbatch=2);\n\njulia> zero_state_like(reg, 2)\nBatchedArrayReg{2, ComplexF64, Array...}\n active qubits: 2/2\n nlevel: 2\n nbatch: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.rand_state","page":"Quantum Registers","title":"YaoArrayRegister.rand_state","text":"rand_state([T=ComplexF64], n::Int; nbatch=NoBatch(), no_transpose_storage=false)\n\nCreate a random AbstractArrayReg with total number of qudits n.\n\nExamples\n\njulia> rand_state(4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> rand_state(ComplexF64, 4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\njulia> rand_state(ComplexF64, 4; nbatch=2)\nBatchedArrayReg{2, ComplexF64, Transpose...}\n active qubits: 4/4\n nlevel: 2\n nbatch: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.uniform_state","page":"Quantum Registers","title":"YaoArrayRegister.uniform_state","text":"uniform_state([T=ComplexF64], n; nbatch=NoBatch(), no_transpose_storage=false)\n\nCreate a uniform state:\n\nfrac1sqrt2^n sum_k=0^2^n-1 krangle\n\nThis state can also be created by applying H (Hadmard gate) on 0000 state.\n\nExample\n\njulia> uniform_state(4; nbatch=2)\nBatchedArrayReg{2, ComplexF64, Transpose...}\n active qubits: 4/4\n nlevel: 2\n nbatch: 2\n\njulia> uniform_state(ComplexF32, 4; nbatch=2)\nBatchedArrayReg{2, ComplexF32, Transpose...}\n active qubits: 4/4\n nlevel: 2\n nbatch: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.ghz_state","page":"Quantum Registers","title":"YaoArrayRegister.ghz_state","text":"ghz_state([T=ComplexF64], n::Int; nbatch::Int=NoBatch())\n\nCreate a GHZ state (or a cat state) that defined as\n\nfrac0rangle^otimes n + 1rangle^otimes nsqrt2\n\nExamples\n\njulia> ghz_state(4)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 4/4\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.clone","page":"Quantum Registers","title":"YaoAPI.clone","text":"clone(register, n)\n\nCreate an ArrayReg by cloning the original register for n times on batch dimension. This function is only for emulation.\n\nExample\n\njulia> clone(arrayreg(bit\"101\"; nbatch=3), 4)\nBatchedArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n nbatch: 12\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for querying the properties of a quantum register.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"nqudits\nnqubits\nnactive\nnremain\nnbatch\nnlevel\nfocus!\nfocus\nrelax!\nexchange_sysenv","category":"page"},{"location":"man/registers.html#YaoAPI.nqudits","page":"Quantum Registers","title":"YaoAPI.nqudits","text":"nqudits(register) -> Int\n\nReturns the total number of qudits in register.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.nqubits","page":"Quantum Registers","title":"YaoAPI.nqubits","text":"nqubits(register) -> Int\n\nReturns the (total) number of qubits. See nactive, nremain for more details.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.nactive","page":"Quantum Registers","title":"YaoAPI.nactive","text":"nactive(register) -> Int\n\nReturns the number of active qudits in register. Here, active qudits means the system qubits that operators can be applied on.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.nremain","page":"Quantum Registers","title":"YaoAPI.nremain","text":"nremain(register) -> Int\n\nReturns the number of inactive qudits in register. It equals to subtracting nqudits and nactive.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.nbatch","page":"Quantum Registers","title":"YaoArrayRegister.nbatch","text":"nbatch(register) -> Union{Int,NoBatch()}\n\nReturns the number of batches.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.nlevel","page":"Quantum Registers","title":"YaoAPI.nlevel","text":"nlevel(x)\n\nNumber of levels in each qudit.\n\nExamples\n\njulia> nlevel(X)\n2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.focus!","page":"Quantum Registers","title":"YaoAPI.focus!","text":"focus!(register, locs) -> register\nfocus!(locs...) -> f(register) -> register\n\nSet the active qubits to focused locations, usually used to execute a subroutine. If register is not provided, returns a lambda that takes a register as input.\n\nExamples\n\njulia> reg = product_state(bit\"01101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> focus!(reg, (1,3,4))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/5\n nlevel: 2\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 111 ₍₂₎\n 111 ₍₂₎\n 111 ₍₂₎\n\njulia> measure(apply(reg, put(3, 2=>X)); nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 101 ₍₂₎\n 101 ₍₂₎\n 101 ₍₂₎\n\nHere, we prepare a product state and only look at the qubits 1, 3 and 4. The measurement results are all ones. With the focued register, we can apply a block of size 3 on it, even though the number of qubits is 5.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.focus","page":"Quantum Registers","title":"YaoAPI.focus","text":"focus(f, register, locs)\n\nCall a callable f under the context of focus. See also focus!.\n\nExamples\n\nTo print the focused register\n\njulia> r = arrayreg(bit\"101100\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 6/6\n nlevel: 2\n\njulia> focus(x->(println(x);x), r, (1, 2));\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/6\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.relax!","page":"Quantum Registers","title":"YaoAPI.relax!","text":"relax!(register[, locs]; to_nactive=nqudits(register)) -> register\nrelax!(locs::Int...; to_nactive=nqudits(register)) -> f(register) -> register\n\nInverse transformation of focus!, where to_nactive is the number of active bits for target register. If the register is not provided, returns a lambda function that takes a register as input.\n\nExamples\n\njulia> reg = product_state(bit\"01101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> focus!(reg, (1,3,4))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/5\n nlevel: 2\n\njulia> relax!(reg, (1,3,4))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.exchange_sysenv","page":"Quantum Registers","title":"YaoArrayRegister.exchange_sysenv","text":"exchange_sysenv(reg::AbstractArrayReg) -> AbstractRegister\n\nExchange system (focused qubits) and environment (remaining qubits).\n\njulia> reg = rand_state(5)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> focus!(reg, (2,4))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/5\n nlevel: 2\n\njulia> exchange_sysenv(reg)\nArrayReg{2, ComplexF64, Adjoint...}\n active qubits: 3/5\n nlevel: 2\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for querying the state of a quantum register.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"state\nbasis\nstatevec\nrelaxedvec\nhypercubic\nrank3\nviewbatch\ntranspose_storage","category":"page"},{"location":"man/registers.html#YaoArrayRegister.state","page":"Quantum Registers","title":"YaoArrayRegister.state","text":"state(register::AbstractArrayReg) -> Matrix\n\nReturns the raw array storage of register. See also statevec.\n\n\n\n\n\nstate(ρ::DensityMatrix) -> Matrix\n\nReturn the raw state of density matrix ρ.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#BitBasis.basis","page":"Quantum Registers","title":"BitBasis.basis","text":"basis(ditstr) -> UnitRange{DitStr{D,N,T}}\nbasis(DitStr{D,N,T}) -> UnitRange{DitStr{D,N,T}}\n\nReturns the UnitRange for basis in Hilbert Space of qudits.\n\n\n\n\n\nbasis(register) -> UnitRange\n\nReturns an UnitRange of the all the bits in the Hilbert space of given register.\n\njulia> collect(basis(rand_state(3)))\n8-element Vector{DitStr{2, 3, Int64}}:\n 000 ₍₂₎\n 001 ₍₂₎\n 010 ₍₂₎\n 011 ₍₂₎\n 100 ₍₂₎\n 101 ₍₂₎\n 110 ₍₂₎\n 111 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.statevec","page":"Quantum Registers","title":"YaoArrayRegister.statevec","text":"statevec(r::ArrayReg) -> array\n\nReturn a state matrix/vector by droping the last dimension of size 1 (i.e. nactive(r) = nqudits(r)). See also state.\n\nwarning: Warning\nstatevec is not type stable. It may cause performance slow down.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.relaxedvec","page":"Quantum Registers","title":"YaoArrayRegister.relaxedvec","text":"relaxedvec(r::AbstractArrayReg) -> AbstractArray\n\nReturn a vector representation of state, with all qudits activated. See also state, statevec.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#BitBasis.hypercubic","page":"Quantum Registers","title":"BitBasis.hypercubic","text":"hypercubic(A::Array) -> Array\n\nget the hypercubic representation for an array.\n\n\n\n\n\nhypercubic(r::ArrayReg) -> AbstractArray\n\nReturn the hypercubic representation (high dimensional tensor) of this register, only active qudits are considered. See also rank3 and state.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.rank3","page":"Quantum Registers","title":"YaoArrayRegister.rank3","text":"rank3(r::ArrayReg)\n\nReturn the rank 3 tensor representation of state, the 3 dimensions are (activated space, remaining space, batch dimension). See also hypercubic and state.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.viewbatch","page":"Quantum Registers","title":"YaoAPI.viewbatch","text":"viewbatch(register, i::Int) -> AbstractRegister\n\nReturns the i-th single register of a batched register. The returned instance is a view of the original register, i.e. inplace operation changes the original register directly.\n\nExamples\n\njulia> reg = zero_state(5; nbatch=2);\n\njulia> apply!(viewbatch(reg, 2), put(5, 2=>X));\n\njulia> measure(reg; nshots=3)\n3×2 Matrix{DitStr{2, 5, Int64}}:\n 00000 ₍₂₎ 00010 ₍₂₎\n 00000 ₍₂₎ 00010 ₍₂₎\n 00000 ₍₂₎ 00010 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.transpose_storage","page":"Quantum Registers","title":"YaoArrayRegister.transpose_storage","text":"transpose_storage(register) -> register\n\nTranspose the register storage. Sometimes transposed storage provides better performance for batched simulation.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for arithmetic operations on quantum registers.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"AdjointArrayReg","category":"page"},{"location":"man/registers.html#YaoArrayRegister.AdjointArrayReg","page":"Quantum Registers","title":"YaoArrayRegister.AdjointArrayReg","text":"AdjointArrayReg{D,T,MT} = AdjointRegister{D,<:AbstractArrayReg{D,T,MT}}\n\nAdjoint array register type, it is used to represent the bra in the Dirac notation.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"We also have some faster inplace versions of arithematic operations","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"regadd!\nregsub!\nregscale!","category":"page"},{"location":"man/registers.html#YaoArrayRegister.regadd!","page":"Quantum Registers","title":"YaoArrayRegister.regadd!","text":"regadd!(target, source)\n\nInplace version of + that accumulates source to target.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.regsub!","page":"Quantum Registers","title":"YaoArrayRegister.regsub!","text":"regsub!(target, source)\n\nInplace version of - that subtract source from target.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.regscale!","page":"Quantum Registers","title":"YaoArrayRegister.regscale!","text":"regscale!(target, x)\n\nInplace version of multiplying a scalar x to target.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"We also define the following functions for state normalization, and distance measurement.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"normalize!\nisnormalized\nfidelity\ntracedist","category":"page"},{"location":"man/registers.html#LinearAlgebra.normalize!","page":"Quantum Registers","title":"LinearAlgebra.normalize!","text":"normalize!(r::AbstractArrayReg)\n\nNormalize the register r by its 2-norm. It changes the register directly.\n\nExamples\n\nThe following code creates a normalized GHZ state.\n\njulia> reg = product_state(bit\"000\") + product_state(bit\"111\");\n\njulia> norm(reg)\n1.4142135623730951\n\njulia> isnormalized(reg)\nfalse\n\njulia> normalize!(reg);\n\njulia> isnormalized(reg)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.isnormalized","page":"Quantum Registers","title":"YaoArrayRegister.isnormalized","text":"isnormalized(r::ArrayReg) -> Bool\n\nReturns true if the register r is normalized.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.fidelity","page":"Quantum Registers","title":"YaoAPI.fidelity","text":"fidelity(register1, register2) -> Real/Vector{<:Real}\nfidelity'(pair_or_reg1, pair_or_reg2) -> (g1, g2)\n\nReturn the fidelity between two states. Calcuate the fidelity between r1 and r2, if r1 or r2 is not pure state (nactive(r) != nqudits(r)), the fidelity is calcuated by purification. See also: http://iopscience.iop.org/article/10.1088/1367-2630/aa6a4b/meta\n\nObtain the gradient with respect to registers and circuit parameters. For pair input ψ=>circuit, the returned gradient is a pair of gψ=>gparams, with gψ the gradient of input state and gparams the gradients of circuit parameters. For register input, the return value is a register.\n\nDefinition\n\nThe fidelity of two quantum state for qudits is defined as:\n\nF(ρ σ) = tr(sqrtsqrtρσsqrtρ)\n\nnote: Note\nThis definition is different from the one in Wiki by a square.\n\nExamples\n\njulia> reg1 = uniform_state(3);\n\njulia> reg2 = zero_state(3);\n\njulia> fidelity(reg1, reg2)\n0.35355339059327373\n\nReferences\n\nJozsa R. Fidelity for mixed quantum states[J]. Journal of modern optics, 1994, 41(12): 2315-2323.\nNielsen M A, Chuang I. Quantum computation and quantum information[J]. 2002.\n\nnote: Note\nThe original definition of fidelity F was from \"transition probability\", defined by Jozsa in 1994, it is the square of what we use here.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.tracedist","page":"Quantum Registers","title":"YaoAPI.tracedist","text":"tracedist(register1, register2)\n\nReturn the trace distance of register1 and register2.\n\nDefinition\n\nTrace distance is defined as following:\n\nfrac12 A - B _rm tr\n\nIt takes values between 0 and 1.\n\nExamples\n\njulia> reg1 = uniform_state(3);\n\njulia> reg2 = zero_state(3);\n\njulia> tracedist(reg1, reg2)\n0.9354143466934852\n\nReferences\n\nhttps://en.wikipedia.org/wiki/Trace_distance\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for adding and reordering qubits in a quantum register.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"insert_qudits!\ninsert_qubits!\nappend_qudits!\nappend_qubits!\nreorder!\ninvorder!","category":"page"},{"location":"man/registers.html#YaoAPI.insert_qudits!","page":"Quantum Registers","title":"YaoAPI.insert_qudits!","text":"insert_qudits!(register, loc::Int, nqudits::Int) -> register\ninsert_qudits!(loc::Int, nqudits::Int) -> λ(register)\n\nInsert qudits to given register in state |0>. i.e. |psi> -> join(|psi>, |0...>, |psi>), increased bits have higher indices.\n\nExamples\n\njulia> reg = product_state(bit\"01101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> insert_qudits!(reg, 2, 2)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 7/7\n nlevel: 2\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 7, Int64}}:\n 0110001 ₍₂₎\n 0110001 ₍₂₎\n 0110001 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.insert_qubits!","page":"Quantum Registers","title":"YaoAPI.insert_qubits!","text":"insert_qubits!(register, loc::Int, nqubits::Int=1) -> register\ninsert_qubits!(loc::Int, nqubits::Int=1) -> λ(register)\n\nInsert n qubits to given register in state |0>. It is an alias of insert_qudits! function.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.append_qudits!","page":"Quantum Registers","title":"YaoAPI.append_qudits!","text":"append_qudits!(register, n::Int) -> register\nappend_qudits!(n::Int) -> λ(register)\n\nAdd n qudits to given register in state |0>. i.e. |psi> -> |000> ⊗ |psi>, increased bits have higher indices.\n\nIf only an integer is provided, then returns a lambda function.\n\nExamples\n\njulia> reg = product_state(bit\"01101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2\n\njulia> append_qudits!(reg, 2)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 7/7\n nlevel: 2\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 7, Int64}}:\n 0001101 ₍₂₎\n 0001101 ₍₂₎\n 0001101 ₍₂₎\n\nNote here, we read the bit string from right to left.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.append_qubits!","page":"Quantum Registers","title":"YaoAPI.append_qubits!","text":"append_qubits!(register, n::Int) -> register\nappend_qubits!(n::Int) -> λ(register)\n\nAdd n qudits to given register in state |0>. It is an alias of append_qudits! function.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.reorder!","page":"Quantum Registers","title":"YaoAPI.reorder!","text":"reorder!(reigster, orders)\n\nReorder the locations of register by input orders. For a 3-qubit register, an order (i, j, k) specifies the following reordering of qubits\n\nmove the first qubit go to i,\nmove the second qubit go to j,\nmove the third qubit go to k.\n\nnote: Note\nThe convention of reorder! is different from the permutedims function, one can use the sortperm function to relate the permutation order and the order in this function.\n\nExamples\n\njulia> reg = product_state(bit\"010101\");\n\njulia> reorder!(reg, (1,4,2,5,3,6));\n\njulia> measure(reg)\n1-element Vector{DitStr{2, 6, Int64}}:\n 000111 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.invorder!","page":"Quantum Registers","title":"YaoAPI.invorder!","text":"invorder!(register)\n\nInverse the locations of the register.\n\nExamples\n\njulia> reg = product_state(bit\"010101\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 6/6\n nlevel: 2\n\njulia> measure(invorder!(reg); nshots=3)\n3-element Vector{DitStr{2, 6, Int64}}:\n 101010 ₍₂₎\n 101010 ₍₂₎\n 101010 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The instruct! function is for applying quantum operators on a quantum register.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"YaoArrayRegister.instruct!","category":"page"},{"location":"man/registers.html#YaoAPI.instruct!","page":"Quantum Registers","title":"YaoAPI.instruct!","text":"instruct!([nlevel=Val(2), ]state, operator, locs[, control_locs, control_configs, theta])\n\nUnified interface for applying an operator to a quantum state. It modifies the state directly.\n\nArguments\n\nnlevel is the number of levels in each qudit,\nstate is a vector or matrix representing the quantum state, where the first dimension is the active qubit dimension, the second is the batch dimension.\noperator is a quantum operator, which can be Val(GATE_SYMBOL) or a matrix.\nlocs::Tuple is a tuple for specifying the locations this gate applied.\ncontrol_locs::Tuple and control_configs are tuples for specifying the control locations and control values.\ntheta::Real is the parameter for the gate, e.g. Val(:Rx) gate takes a real number of its parameter.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for measurement and post-selection.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"measure!\nmeasure\nselect!\nselect\ncollapseto!\nprobs\nmost_probable","category":"page"},{"location":"man/registers.html#YaoAPI.measure!","page":"Quantum Registers","title":"YaoAPI.measure!","text":"measure!([postprocess,] [operator, ]register[, locs]; rng=Random.GLOBAL_RNG)\n\nMeasure current active qudits or qudits at locs. If the operator is not provided, it will measure on the computational basis and collapse to a product state. Otherwise, the quantum state collapse to the subspace corresponds to the resulting eigenvalue of the observable.\n\nArguments\n\npostprocess is the postprocessing method, it can be\nNoPostProcess() (default).\nResetTo(config), reset to result state to config. It can not be used if operator is provided, because measuring an operator in general does not return a product state.\nRemoveMeasured(), remove the measured qudits from the register. It is also incompatible with the operator argument.\noperator::AbstractBlock is the operator to measure.\nregister::AbstractRegister is the quantum state.\nlocs is the qubits to performance the measurement. If locs is not provided, all current active qudits are measured (regarding to active qudits,\n\nsee focus! and relax!).\n\nKeyword arguments\n\nrng is the random number generator.\n\nExamples\n\nThe following example measures a random state on the computational basis and reset it to a certain bitstring value.\n\njulia> reg = rand_state(3);\n\njulia> measure!(ResetTo(bit\"011\"), reg)\n110 ₍₂₎\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 011 ₍₂₎\n 011 ₍₂₎\n 011 ₍₂₎\n\njulia> measure!(RemoveMeasured(), reg, (1,2))\n11 ₍₂₎\n\njulia> reg # removed qubits are not usable anymore\nArrayReg{2, ComplexF64, Array...}\n active qubits: 1/1\n nlevel: 2\n\nMeasuring an operator will project the state to the subspace associated with the returned eigenvalue.\n\njulia> reg = uniform_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> print_table(reg)\n000 ₍₂₎ 0.35355 + 0.0im\n001 ₍₂₎ 0.35355 + 0.0im\n010 ₍₂₎ 0.35355 + 0.0im\n011 ₍₂₎ 0.35355 + 0.0im\n100 ₍₂₎ 0.35355 + 0.0im\n101 ₍₂₎ 0.35355 + 0.0im\n110 ₍₂₎ 0.35355 + 0.0im\n111 ₍₂₎ 0.35355 + 0.0im\n\njulia> measure!(repeat(3, Z, 1:3), reg)\n-1.0 + 0.0im\n\njulia> print_table(reg)\n000 ₍₂₎ 0.0 + 0.0im\n001 ₍₂₎ 0.5 + 0.0im\n010 ₍₂₎ 0.5 + 0.0im\n011 ₍₂₎ 0.0 + 0.0im\n100 ₍₂₎ 0.5 + 0.0im\n101 ₍₂₎ 0.0 + 0.0im\n110 ₍₂₎ 0.0 + 0.0im\n111 ₍₂₎ 0.5 + 0.0im\n\nHere, we measured the parity operator, as a result, the resulting state collapsed to the subspace with either even or odd parity.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.measure","page":"Quantum Registers","title":"YaoAPI.measure","text":"measure([, operator], register[, locs]; nshots=1, rng=Random.GLOBAL_RNG) -> Vector{Int}\n\nMeasure a quantum state and return measurement results of qudits. This measurement function a cheating version of measure! that does not collapse the input state. It also does not need to recompute the quantum state for performing multiple shots measurement.\n\nArguments\n\noperator::AbstractBlock is the operator to measure.\nregister::AbstractRegister is the quantum state.\nlocs is the qubits to performance the measurement. If locs is not provided, all current active qudits are measured (regarding to active qudits,\n\nsee focus! and relax!).\n\nKeyword arguments\n\nnshots::Int is the number of shots.\nrng is the random number generator.\n\nExamples\n\njulia> reg = product_state(bit\"110\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> measure(reg; nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 110 ₍₂₎\n 110 ₍₂₎\n 110 ₍₂₎\n\njulia> measure(reg, (2,3); nshots=3)\n3-element Vector{DitStr{2, 2, Int64}}:\n 11 ₍₂₎\n 11 ₍₂₎\n 11 ₍₂₎\n\nThe following example switches to the X basis for measurement.\n\njulia> reg = apply!(product_state(bit\"100\"), repeat(3, H, 1:3))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> measure(repeat(3, X, 1:3), reg; nshots=3)\n3-element Vector{ComplexF64}:\n -1.0 + 0.0im\n -1.0 + 0.0im\n -1.0 + 0.0im\n\njulia> reg = apply!(product_state(bit\"101\"), repeat(3, H, 1:3))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> measure(repeat(3, X, 1:3), reg; nshots=3)\n3-element Vector{ComplexF64}:\n 1.0 - 0.0im\n 1.0 - 0.0im\n 1.0 - 0.0im\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.select!","page":"Quantum Registers","title":"YaoAPI.select!","text":"select!(dest::AbstractRegister, src::AbstractRegister, bits::Integer...) -> AbstractRegister\nselect!(register::AbstractRegister, bits::Integer...) -> register\nselect!(b::Integer) -> f(register)\n\nselect a subspace of given quantum state based on input eigen state bits. See also select for the non-inplace version. If the register is not provided, it returns a lambda expression that takes a register as the input.\n\nExamples\n\njulia> reg = ghz_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> select!(reg, bit\"111\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 0/0\n nlevel: 2\n\njulia> norm(reg)\n0.7071067811865476\n\nThe selection only works on the activated qubits, for example\n\njulia> reg = focus!(ghz_state(3), (1, 2))\nArrayReg{2, ComplexF64, Array...}\n active qubits: 2/3\n nlevel: 2\n\njulia> select!(reg, bit\"11\")\nArrayReg{2, ComplexF64, Array...}\n active qubits: 0/1\n nlevel: 2\n\njulia> statevec(reg)\n1×2 Matrix{ComplexF64}:\n 0.0+0.0im 0.707107+0.0im\n\ntip: Tip\nDevelopers should overload select!(r::RegisterType, bits::NTuple{N, <:Integer}) and do not assume bits has specific number of bits (e.g Int64), or it will restrict the its maximum available number of qudits.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.select","page":"Quantum Registers","title":"YaoAPI.select","text":"select(register, bits) -> AbstractRegister\n\nThe non-inplace version of select!.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.collapseto!","page":"Quantum Registers","title":"YaoAPI.collapseto!","text":"collapseto!(register, config)\n\nSet the register to bit string literal bit_str (or an equivalent integer). About bit string literal, see more in @bit_str. This interface is only for emulation.\n\nExamples\n\nThe following code collapse a random state to a certain state.\n\njulia> measure(collapseto!(rand_state(3), bit\"001\"); nshots=3)\n3-element Vector{DitStr{2, 3, Int64}}:\n 001 ₍₂₎\n 001 ₍₂₎\n 001 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.probs","page":"Quantum Registers","title":"YaoAPI.probs","text":"probs(register) -> Vector\n\nReturns the probability distribution of computation basis, aka xψ^2.\n\nExamples\n\njulia> reg = product_state(bit\"101\");\n\njulia> reg |> probs\n8-element Vector{Float64}:\n 0.0\n 0.0\n 0.0\n 0.0\n 0.0\n 1.0\n 0.0\n 0.0\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.most_probable","page":"Quantum Registers","title":"YaoArrayRegister.most_probable","text":"most_probable(reg::ArrayReg{D, T} where T, n::Int64) -> Any\n\n\nFind n most probable qubit configurations in a quantum register and return these configurations as a vector of DitStr instances.\n\nExample\n\njulia> most_probable(ghz_state(3), 2)\n2-element Vector{DitStr{2, 3, Int64}}:\n 000 ₍₂₎\n 111 ₍₂₎\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"The following functions are for density matrices.","category":"page"},{"location":"man/registers.html","page":"Quantum Registers","title":"Quantum Registers","text":"DensityMatrix\ndensity_matrix\nrand_density_matrix\ncompletely_mixed_state\npartial_tr\npurify\nvon_neumann_entropy\nmutual_information","category":"page"},{"location":"man/registers.html#YaoAPI.DensityMatrix","page":"Quantum Registers","title":"YaoAPI.DensityMatrix","text":"DensityMatrix{D,T,MT<:AbstractMatrix{T}} <: AbstractRegister{D}\nDensityMatrix{D}(state::AbstractMatrix)\nDensityMatrix(state::AbstractMatrix; nlevel=2)\n\nDensity matrix type, where state is a matrix. Type parameter D is the number of levels, it can also be specified by a keyword argument nlevel.\n\n\n\n\n\n","category":"type"},{"location":"man/registers.html#YaoAPI.density_matrix","page":"Quantum Registers","title":"YaoAPI.density_matrix","text":"density_matrix(register_or_rho[, locations])\n\nReturns the reduced density matrix for qubits at locations (default: all qubits).\n\nExamples\n\nThe following code gets the single site reduce density matrix for the GHZ state.\n\njulia> reg = ghz_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> density_matrix(reg, (2,)).state\n2×2 Matrix{ComplexF64}:\n 0.5+0.0im 0.0+0.0im\n 0.0-0.0im 0.5+0.0im\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.rand_density_matrix","page":"Quantum Registers","title":"YaoArrayRegister.rand_density_matrix","text":"rand_density_matrix([T=ComplexF64], n::Int; nlevel::Int=2, pure::Bool=false)\n\nGenerate a random density matrix by partial tracing half of the pure state.\n\nnote: Note\nThe generated density matrix is not strict hermitian due to rounding error. If you need to check hermicity, do not use ishermitian consider using isapprox(dm.state, dm.state') or explicit mark it as Hermitian.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.completely_mixed_state","page":"Quantum Registers","title":"YaoArrayRegister.completely_mixed_state","text":"completely_mixed_state([T=ComplexF64], n::Int; nlevel::Int=2)\n\nGenerate the completely mixed state with density matrix I(n) ./ nlevel^n.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.partial_tr","page":"Quantum Registers","title":"YaoAPI.partial_tr","text":"partial_tr(ρ, locs) -> DensityMatrix\n\nReturn a density matrix which is the partial traced on locs.\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoAPI.purify","page":"Quantum Registers","title":"YaoAPI.purify","text":"purify(r::DensityMatrix; nbit_env::Int=nactive(r)) -> ArrayReg\n\nGet a purification of target density matrix.\n\nExamples\n\nThe following example shows how to measure a local operator on the register, reduced density matrix and the purified register. Their results should be consistent.\n\njulia> reg = ghz_state(3)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 3/3\n nlevel: 2\n\njulia> r = density_matrix(reg, (2,));\n\njulia> preg = purify(r)\nArrayReg{2, ComplexF64, Array...}\n active qubits: 1/2\n nlevel: 2\n\njulia> isapprox(expect(Z + Y, preg), 0.0; atol=1e-10)\ntrue\n\njulia> isapprox(expect(Z + Y, r), 0.0; atol=1e-10)\ntrue\n\njulia> isapprox(expect(put(3, 2=>(Z + Y)), reg), 0.0; atol=1e-10)\ntrue\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.von_neumann_entropy","page":"Quantum Registers","title":"YaoArrayRegister.von_neumann_entropy","text":"von_neumann_entropy(reg::AbstractArrayReg, part)\nvon_neumann_entropy(ρ::DensityMatrix)\n\nThe entanglement entropy between part and the rest part in quantum state reg. If the input is a density matrix, it returns the entropy of a mixed state.\n\nExample\n\nThe Von Neumann entropy of any segment of GHZ state is log 2.\n\njulia> von_neumann_entropy(ghz_state(3), (1,2))\n0.6931471805599612\n\n\n\n\n\nvon_neumann_entropy(rho) -> Real\n\nReturn the von-Neumann entropy for the input density matrix:\n\n-rm Tr(rholnrho)\n\n\n\n\n\n","category":"function"},{"location":"man/registers.html#YaoArrayRegister.mutual_information","page":"Quantum Registers","title":"YaoArrayRegister.mutual_information","text":"mutual_information(register_or_rho, part1, part2)\n\nReturns the mutual information between subsystems part1 and part2 of the input quantum register or density matrix:\n\nS(rho_A) + S(rho_B) - S(rho_AB)\n\nExample\n\nThe mutual information of a GHZ state of any two disjoint parts is always equal to log 2.\n\njulia> mutual_information(ghz_state(4), (1,), (3,4))\n0.6931471805599132\n\n\n\n\n\n","category":"function"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"EditURL = \"../../../examples/2.qft-phase-estimation/main.jl\"","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"(Image: )","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html#example-qft","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"","category":"section"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Let's use Yao first","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"using Yao","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html#Quantum-Fourier-Transformation","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation","text":"","category":"section"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"The Quantum Fourier Transformation (QFT) circuit is to repeat two kinds of blocks repeatly:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"(Image: qft-circuit)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"The basic building block control phase shift gate is defined as","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"R(k)=beginbmatrix\n1 0\n0 expleft(frac2pi i2^kright)\nendbmatrix","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Let's define block A and block B, block A is actually a control block.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1))))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"A (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Once you construct the blockl you can inspect its matrix using mat function. Let's construct the circuit in dash box A, and see the matrix of R_4 gate.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"R4 = A(4, 1)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"(n -> control(n, 4, 1 => shift(0.39269908169872414)))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"If you have read about preparing GHZ state, you probably know that in Yao, we could just leave the number of qubits, and it will be evaluated when possible.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"R4(5)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"nqubits: 5\ncontrol(4)\n└─ (1,) shift(0.39269908169872414)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"its matrix will be","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"mat(R4(5))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"32×32 Diagonal{ComplexF64, Vector{ComplexF64}}:\n 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im ⋅ ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ \n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.92388+0.382683im","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Then we repeat this control block over and over on different qubits, and put a Hadamard gate to ith qubit to construct i-th B block.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"B(n, k) = chain(n, j==k ? put(k=>H) : A(j, k) for j in k:n)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"B (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"We need to input the total number of qubits n here because we have to iterate through from k-th location to the last.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Now, let's construct the circuit by chaining all the B blocks together","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"qft(n) = chain(B(n, k) for k in 1:n)\nqft(4)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"nqubits: 4\nchain\n├─ chain\n│ ├─ put on (1)\n│ │ └─ H\n│ ├─ control(2)\n│ │ └─ (1,) shift(1.5707963267948966)\n│ ├─ control(3)\n│ │ └─ (1,) shift(0.7853981633974483)\n│ └─ control(4)\n│ └─ (1,) shift(0.39269908169872414)\n├─ chain\n│ ├─ put on (2)\n│ │ └─ H\n│ ├─ control(3)\n│ │ └─ (2,) shift(1.5707963267948966)\n│ └─ control(4)\n│ └─ (2,) shift(0.7853981633974483)\n├─ chain\n│ ├─ put on (3)\n│ │ └─ H\n│ └─ control(4)\n│ └─ (3,) shift(1.5707963267948966)\n└─ chain\n └─ put on (4)\n └─ H\n","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html#Wrap-QFT-to-an-external-block","page":"Quantum Fourier Transformation and Phase Estimation","title":"Wrap QFT to an external block","text":"","category":"section"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"In most cases, functions are enough to wrap quantum circuits, like A and B we defined above, but sometimes, we need to dispatch specialized methods on certain kinds of quantum circuit, or we want to define an external block to export, thus, it's useful to be able to wrap circuit to custom blocks.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"First, we define a new type as subtype of PrimitiveBlock since we are not going to use the subblocks of QFT, if you need to use its subblocks, it'd be better to define it under CompositeBlock.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"struct QFT <: PrimitiveBlock{2}\n n::Int\nend\n\nYaoBlocks.nqudits(q::QFT) = q.n","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Now, let's define its circuit","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"circuit(q::QFT) = qft(q.n)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"circuit (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"And forward mat to its circuit's matrix","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"YaoBlocks.mat(::Type{T}, x::QFT) where T = mat(T, circuit(x))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"You may notice, it is a little ugly to print QFT at the moment, this is because we print the type summary by default, you can define your own printing by overloading print_block","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"YaoBlocks.print_block(io::IO, x::QFT) = print(io, \"QFT($(x.n))\")","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Since it is possible to use FFT to simulate the results of QFT (like cheating), we could define our custom apply! method:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"using FFTW, LinearAlgebra\n\nfunction YaoBlocks.apply!(r::ArrayReg, x::QFT)\n α = sqrt(length(statevec(r)))\n invorder!(r)\n lmul!(α, ifft!(statevec(r)))\n return r\nend","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Now let's check if our apply! method is correct:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"r = rand_state(5)\nr1 = r |> copy |> QFT(5)\nr2 = r |> copy |> circuit(QFT(5))\nr1 ≈ r2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"true","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"We can get iQFT (inverse QFT) directly by calling adjoint","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"QFT(5)'","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":" [†]QFT(5)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"QFT and iQFT are different from FFT and IFFT in three ways,","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"they are different by a factor of sqrt2^n with n the number of qubits.\nthe bit numbering will exchange after applying QFT or iQFT.\ndue to the convention, QFT is more related to IFFT rather than FFT.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html#Phase-Estimation","page":"Quantum Fourier Transformation and Phase Estimation","title":"Phase Estimation","text":"","category":"section"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Since we have QFT and iQFT blocks we can then use them to realize phase estimation circuit, what we want to realize is the following circuit:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"(Image: phase estimation)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"First we call Hadamard gates repeatly on first n qubits.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Hadamards(n) = repeat(H, 1:n)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Hadamards (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Then in dashed box B, we have controlled unitaries:","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ControlU(n, m, U) = chain(n+m, control(k, n+1:n+m=>matblock(U^(2^(k-1)))) for k in 1:n)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ControlU (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"each of them is a U of power 2^(k-1).","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Since we will only apply the qft and Hadamard on first n qubits, we could use Subroutine, which creates a context of a sub-scope of the qubits.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"PE(n, m, U) =\n chain(n+m, # total number of the qubits\n subroutine(Hadamards(n), 1:n), # apply H in local scope\n ControlU(n, m, U),\n subroutine(QFT(n)', 1:n))","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"PE (generic function with 1 method)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"we use the first n qubits as the output space to store phase ϕ, and the other m qubits as the input state which corresponds to an eigenvector of oracle matrix U.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"The subroutine here uses focus! and relax! to manage a local scope of quantum circuit, and only activate the first n qubits while applying the block inside the subroutine context, and the scope will be relax!ed back, after the context. This is equivalent to manually focus! then relax!","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"fullly activated","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"r = rand_state(5)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"first 3 qubits activated","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"focus!(r, 1:3)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 3/5\n nlevel: 2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"relax back to the original","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"relax!(r, 1:3)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 5/5\n nlevel: 2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"In this way, we will be able to apply small operator directly on the subset of the qubits.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Details about the algorithm can be found here: Quantum Phase Estimation Algorithm","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Now let's check the results of our phase estimation.","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"First we need to set up a unitary with known phase, we set the phase to be 0.75, which is 0.75 * 2^3 == 6 == 0b110 .","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"N, M = 3, 5\nP = eigen(rand_unitary(1< PE(N, M, U)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"ArrayReg{2, ComplexF64, Array...}\n active qubits: 8/8\n nlevel: 2","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Since our phase can be represented by 3 qubits precisely, we only need to measure once","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"results = measure(r, 1:N; nshots=1)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"1-element Vector{DitStr{2, 3, Int64}}:\n 011 ₍₂₎","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"Recall that our QFT's bit numbering is reversed, let's reverse it back","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"using BitBasis\nestimated_phase = bfloat(results[]; nbits=N)","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"0.75","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"the phase is exactly 0.75!","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"","category":"page"},{"location":"generated/examples/2.qft-phase-estimation/index.html","page":"Quantum Fourier Transformation and Phase Estimation","title":"Quantum Fourier Transformation and Phase Estimation","text":"This page was generated using Literate.jl.","category":"page"},{"location":"man/bitbasis.html","page":"BitBasis","title":"BitBasis","text":"CurrentModule = BitBasis\nDocTestSetup = quote\n using Yao\n using Yao: YaoBlocks, YaoArrayRegister\n using YaoBlocks\n using YaoArrayRegister\nend","category":"page"},{"location":"man/bitbasis.html#BitBasis","page":"BitBasis","title":"BitBasis","text":"","category":"section"},{"location":"man/bitbasis.html","page":"BitBasis","title":"BitBasis","text":"Types and operations for basis represented by bits in linear algebra.","category":"page"},{"location":"man/bitbasis.html","page":"BitBasis","title":"BitBasis","text":"For more details please ref to BitBasis.jl.","category":"page"},{"location":"man/bitbasis.html","page":"BitBasis","title":"BitBasis","text":"Modules = [BitBasis]\nOrder = [:macro, :function, :type, :module]","category":"page"},{"location":"man/bitbasis.html#BitBasis.@bit_str-Tuple{Any}","page":"BitBasis","title":"BitBasis.@bit_str","text":"@bit_str -> BitStr64\n\nConstruct a bit string. such as bit\"0000\". The bit strings also supports string join. Just use it like normal strings.\n\nExample\n\njulia> bit\"10001\"\n10001 ₍₂₎\n\njulia> bit\"100_111_101\"\n100111101 ₍₂₎\n\njulia> join(bit\"1001\", bit\"11\", bit\"1110\")\n1001111110 ₍₂₎\n\njulia> onehot(bit\"1001\")\n16-element Vector{ComplexF64}:\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 1.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n\n\n\n\n\n\n","category":"macro"},{"location":"man/bitbasis.html#BitBasis.@dit_str-Tuple{Any}","page":"BitBasis","title":"BitBasis.@dit_str","text":"@dit_str -> DitStr64\n\nConstruct a dit string. such as dit\"0201;3\". The dit strings also supports string join. Just use it like normal strings.\n\nExample\n\njulia> dit\"10201;3\"\n10201 ₍₃₎\n\njulia> dit\"100_121_121;3\"\n100121121 ₍₃₎\n\njulia> join(dit\"1021;3\", dit\"11;3\", dit\"1210;3\")\n1021111210 ₍₃₎\n\njulia> onehot(dit\"1021;3\")\n81-element Vector{ComplexF64}:\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n ⋮\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n 0.0 + 0.0im\n\n\n\n\n\n\n","category":"macro"},{"location":"man/bitbasis.html#BitBasis.@lbit_str-Tuple{Any}","page":"BitBasis","title":"BitBasis.@lbit_str","text":"@lbit_str -> LongBitStr\n\nLong bit string version of @bit_str macro.\n\n\n\n\n\n","category":"macro"},{"location":"man/bitbasis.html#BitBasis.@ldit_str-Tuple{Any}","page":"BitBasis","title":"BitBasis.@ldit_str","text":"@ldit_str -> LongDitStr\n\nLong dit string version of @dit_str macro.\n\n\n\n\n\n","category":"macro"},{"location":"man/bitbasis.html#Base.:==-Union{Tuple{N2}, Tuple{N1}, Tuple{D}, Tuple{BitBasis.SubDitStr{D, N1}, DitStr{D, N2}}} where {D, N1, N2}","page":"BitBasis","title":"Base.:==","text":"==(lhs::SubDitStr{D,N,T}, rhs::DitStr{D,N,T}) -> Bool\n==(lhs::DitStr{D,N,T}, rhs::SubDitStr{D,N,T}) -> Bool\n==(lhs::SubDitStr{D,N,T}, rhs::SubDitStr{D,N,T}) -> Bool\n\nCompare the equality between SubDitStr and DitStr. \n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.allone-Union{Tuple{T}, Tuple{T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.allone","text":"allone(index::Integer, mask::Integer) -> Bool\n\nReturn true if all masked position of index is 1.\n\nExample\n\ntrue if all masked positions are 1.\n\njulia> allone(0b1011, 0b1011)\ntrue\n\njulia> allone(0b1011, 0b1001)\ntrue\n\njulia> allone(0b1011, 0b0100)\nfalse\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.anyone-Union{Tuple{T}, Tuple{T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.anyone","text":"anyone(index::Integer, mask::Integer) -> Bool\n\nReturn true if any masked position of index is 1.\n\nExample\n\ntrue if any masked positions is 1.\n\njulia> anyone(0b1011, 0b1001)\ntrue\n\njulia> anyone(0b1011, 0b1100)\ntrue\n\njulia> anyone(0b1011, 0b0100)\nfalse\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.baddrs-Tuple{Integer}","page":"BitBasis","title":"BitBasis.baddrs","text":"baddrs(b::Integer) -> Vector\n\nget the locations of nonzeros bits, i.e. the inverse operation of bmask.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.basis-Tuple{DitStr}","page":"BitBasis","title":"BitBasis.basis","text":"basis(ditstr) -> UnitRange{DitStr{D,N,T}}\nbasis(DitStr{D,N,T}) -> UnitRange{DitStr{D,N,T}}\n\nReturns the UnitRange for basis in Hilbert Space of qudits.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bdistance-Union{Tuple{Ti}, Tuple{Ti, Ti}} where Ti<:Integer","page":"BitBasis","title":"BitBasis.bdistance","text":"bdistance(i::Integer, j::Integer) -> Int\n\nReturn number of different bits.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bfloat-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bfloat","text":"bfloat(b::Integer; nbits::Int=bit_length(b)) -> Float64\n\nfloat view, with current bit numbering. See also bfloat_r.\n\nRef: wiki: bit numbering\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bfloat-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.bfloat","text":"bfloat(b::BitStr) -> Float64\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bfloat_r-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bfloat_r","text":"bfloat_r(b::Integer; nbits::Int=bit_length(b)) -> Float64\n\nfloat view, with reversed bit numbering. See also bfloat.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bfloat_r-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.bfloat_r","text":"bfloat_r(b::BitStr) -> Float64\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bint-Tuple{BitStr}","page":"BitBasis","title":"BitBasis.bint","text":"bint(b::BitStr) -> Integer\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bint-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bint","text":"bint(b; nbits=nothing) -> Int\n\ninteger view, with LSB 0 bit numbering. See also wiki: bit numbering\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bint_r-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bint_r","text":"bint_r(b; nbits::Int) -> Integer\n\ninteger read in inverse order.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bint_r-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.bint_r","text":"bint_r(b::BitStr) -> Integer\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bit_length-Tuple{Integer}","page":"BitBasis","title":"BitBasis.bit_length","text":"bit_length(x::Integer) -> Int\n\nReturn the number of bits required to represent input integer x.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bitarray-Union{Tuple{T}, Tuple{Vector{T}, Int64}} where T<:Number","page":"BitBasis","title":"BitBasis.bitarray","text":"bitarray(v::Vector, [nbits::Int]) -> BitArray\nbitarray(v::Int, nbits::Int) -> BitArray\nbitarray(nbits::Int) -> Function\n\nConstruct BitArray from an integer vector, if nbits not supplied, it is 64. If an integer is supplied, it returns a function mapping a Vector/Int to bitarray.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bmask","page":"BitBasis","title":"BitBasis.bmask","text":"bmask(::Type{T}) where T <: Integer -> zero(T)\nbmask([T::Type], positions::Int...) -> T\nbmask([T::Type], range::UnitRange{Int}) -> T\n\nReturn an integer mask of type T where 1 is the position masked according to positions or range. Directly use T will return an empty mask 0.\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.breflect","page":"BitBasis","title":"BitBasis.breflect","text":"breflect(b::Integer[, masks::Vector{Integer}]; nbits) -> Integer\n\nReturn left-right reflected integer.\n\nExample\n\nReflect the order of bits.\n\njulia> breflect(0b1011; nbits=4) == 0b1101\ntrue\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.breflect-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.breflect","text":"breflect(bit_str[, masks])\n\nReturn left-right reflected bit string.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.bsizeof-Union{Tuple{Type{T}}, Tuple{T}} where T","page":"BitBasis","title":"BitBasis.bsizeof","text":"bsizeof(::Type)\n\nReturns the size of given type in number of binary digits.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.btruncate-Union{Tuple{T}, Tuple{T, Any}} where T<:Integer","page":"BitBasis","title":"BitBasis.btruncate","text":"btruncate(b, n)\n\nTruncate bits b to given length n.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.controldo-Union{Tuple{S}, Tuple{Union{Function, Type}, BitBasis.IterControl{S}}} where S","page":"BitBasis","title":"BitBasis.controldo","text":"controldo(f, itr::IterControl)\n\nExecute f while iterating itr.\n\nnote: Note\nthis is faster but equivalent than using itr as an iterator. See also itercontrol.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.controller-Tuple{Union{UnitRange{T}, NTuple{var\"#s14\", T} where var\"#s14\", Vector{T}, T} where T<:Integer, Union{UnitRange{T}, NTuple{var\"#s14\", T} where var\"#s14\", Vector{T}, T} where T<:Integer}","page":"BitBasis","title":"BitBasis.controller","text":"controller([T=Int, ]cbits, cvals) -> Function\n\nReturn a function that checks whether a basis at cbits takes specific value cvals.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.flip-Union{Tuple{T}, Tuple{T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.flip","text":"flip(index::Integer, mask::Integer) -> Integer\n\nReturn an Integer with bits at masked position flipped.\n\nExample\n\njulia> flip(0b1011, 0b1011) |> BitStr{4}\n0000 ₍₂₎\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.group_shift!-Tuple{Int64, AbstractVector{Int64}}","page":"BitBasis","title":"BitBasis.group_shift!","text":"group_shift!(nbits, positions)\n\nShift bits on positions together.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.hypercubic-Tuple{Array}","page":"BitBasis","title":"BitBasis.hypercubic","text":"hypercubic(A::Array) -> Array\n\nget the hypercubic representation for an array.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.indicator-Union{Tuple{T}, Tuple{Type{T}, Int64}} where T<:Integer","page":"BitBasis","title":"BitBasis.indicator","text":"indicator(::Type{T}, k) -> T\n\nReturn an integer with k-th bit set to 1.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.indices_with-Tuple{Int64, Vector{Int64}, Vector{Int64}}","page":"BitBasis","title":"BitBasis.indices_with","text":"indices_with(n::Int, locs::Vector{Int}, vals::Vector{Int}) -> Vector{Int}\n\nReturn indices with specific positions locs with value vals in a hilbert space of n qubits.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.invorder-Tuple{AbstractVecOrMat}","page":"BitBasis","title":"BitBasis.invorder","text":"invorder(X::AbstractVecOrMat)\n\nInverse the order of given vector/matrix X.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.ismatch-Union{Tuple{T}, Tuple{T, T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.ismatch","text":"ismatch(index::Integer, mask::Integer, target::Integer) -> Bool\n\nReturn true if bits at positions masked by mask equal to 1 are equal to target.\n\nExample\n\njulia> n = 0b11001; mask = 0b10100; target = 0b10000;\n\njulia> ismatch(n, mask, target)\ntrue\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.itercontrol-Tuple{Int64, AbstractVector, Any}","page":"BitBasis","title":"BitBasis.itercontrol","text":"itercontrol([T=Int], nbits, positions, bit_configs)\n\nReturns an iterator which iterate through controlled subspace of bits.\n\nExample\n\nTo iterate through all the bits satisfy 0xx10x1 where x means an arbitrary bit.\n\njulia> for each in itercontrol(7, [1, 3, 4, 7], (1, 0, 1, 0))\n println(string(each, base=2, pad=7))\n end\n0001001\n0001011\n0011001\n0011011\n0101001\n0101011\n0111001\n0111011\n\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.log2dim1-Tuple{Any}","page":"BitBasis","title":"BitBasis.log2dim1","text":"log2dim1(X)\n\nReturns the log2 of the first dimension's size.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.log2i","page":"BitBasis","title":"BitBasis.log2i","text":"log2i(x::Integer) -> Integer\n\nReturn log2(x), this integer version of log2 is fast but only valid for number equal to 2^n.\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.neg-Union{Tuple{BitStr{N}}, Tuple{N}} where N","page":"BitBasis","title":"BitBasis.neg","text":"neg(b::BitStr) -> BitStr\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.neg-Union{Tuple{T}, Tuple{T, Int64}} where T<:Integer","page":"BitBasis","title":"BitBasis.neg","text":"neg(index::Integer, nbits::Int) -> Integer\n\nReturn an integer with all bits flipped (with total number of bit nbits).\n\nExample\n\njulia> neg(0b1111, 4) |> BitStr{4}\n0000 ₍₂₎\n\njulia> neg(0b0111, 4) |> BitStr{4}\n1000 ₍₂₎\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.next_reordered_basis-Union{Tuple{T}, Tuple{N}, Tuple{T, NTuple{N, T}, NTuple{N, T}}} where {N, T}","page":"BitBasis","title":"BitBasis.next_reordered_basis","text":"next_reordered_basis(basis, takers, differ)\n\nReturns the next reordered basis accroding to current basis.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.onehot-Union{Tuple{T1}, Tuple{N}, Tuple{T}, Tuple{D}, Tuple{Type{T}, DitStr{D, N, T1}}} where {D, T, N, T1}","page":"BitBasis","title":"BitBasis.onehot","text":"onehot([T=Float64], dit_str[; nbatch])\n\nCreate an onehot vector in type Vector{T} or a batch of onehot vector in type Matrix{T}, where index x + 1 is one. One can specify the value of the nonzero entry by inputing a pair.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.packbits-Tuple{AbstractVector}","page":"BitBasis","title":"BitBasis.packbits","text":"packbits(arr::AbstractArray) -> AbstractArray\n\npack bits to integers, usually take a BitArray as input.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.readat-Union{Tuple{T}, Tuple{N}, Tuple{D}, Tuple{DitStr{D, N, T}, Vararg{Integer}}} where {D, N, T}","page":"BitBasis","title":"BitBasis.readat","text":"readat(x, loc...) -> Integer\n\nRead the dit config at given location.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.readbit-Union{Tuple{T}, Tuple{T, Int64}} where T<:Integer","page":"BitBasis","title":"BitBasis.readbit","text":"readbit(x, loc...)\n\nRead the bit config at given location.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.reorder","page":"BitBasis","title":"BitBasis.reorder","text":"reorder(X::AbstractArray, orders)\n\nReorder X according to orders.\n\ntip: Tip\nAlthough orders can be any iterable, Tuple is preferred inorder to gain as much performance as possible. But the conversion won't take much anyway.\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.setbit-Union{Tuple{T}, Tuple{T, T}} where T<:Integer","page":"BitBasis","title":"BitBasis.setbit","text":"setbit(index::Integer, mask::Integer) -> Integer\n\nset the bit at masked position to 1.\n\nExample\n\njulia> setbit(0b1011, 0b1100) |> BitStr{4}\n1111 ₍₂₎\n\njulia> setbit(0b1011, 0b0100) |> BitStr{4}\n1111 ₍₂₎\n\njulia> setbit(0b1011, 0b0000) |> BitStr{4}\n1011 ₍₂₎\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.swapbits-Union{Tuple{T}, Tuple{T, Int64, Int64}} where T<:Integer","page":"BitBasis","title":"BitBasis.swapbits","text":"swapbits(n::Integer, mask_ij::Integer) -> Integer\nswapbits(n::Integer, i::Int, j::Int) -> Integer\n\nReturn an integer with bits at i and j flipped.\n\nExample\n\njulia> swapbits(0b1011, 0b1100) == 0b0111\ntrue\n\ntip: Tip\nlocations i and j specified by mask could be faster when bmask is not straight forward but known by constant.\n\nwarning: Warning\nmask_ij should only contain two 1, swapbits will not check it, use at your own risk.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.unsafe_reorder","page":"BitBasis","title":"BitBasis.unsafe_reorder","text":"unsafe_reorder(X::AbstractArray, orders)\n\nReorder X according to orders.\n\nwarning: Warning\nunsafe_reorder won't check whether the length of orders and the size of first dimension of X match, use at your own risk.\n\n\n\n\n\n","category":"function"},{"location":"man/bitbasis.html#BitBasis.unsafe_sub-Union{Tuple{T}, Tuple{N}, Tuple{UnitRange{T}, NTuple{N, T}}} where {N, T}","page":"BitBasis","title":"BitBasis.unsafe_sub","text":"unsafe_sub(a::UnitRange, b::NTuple{N}) -> NTuple{N}\n\nReturns result in type Tuple of a .- b. This will not check the length of a and b, use at your own risk.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.unsafe_sub-Union{Tuple{T}, Tuple{UnitRange{T}, Vector{T}}} where T","page":"BitBasis","title":"BitBasis.unsafe_sub","text":"unsafe_sub(a::UnitRange{T}, b::Vector{T}) where T\n\nReturns a .- b, fallback version when b is a Vector.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.BitStr","page":"BitBasis","title":"BitBasis.BitStr","text":"BitStr{N,T} <: Integer\n\nThe struct for bit string with fixed length N and storage type T. It is an alias of DitStr{2,N,T}.\n\nBitStr{N,T}(integer)\nBitStr64{N}(integer)\nBitStr64(vector)\nLongBitStr{N}(integer)\nLongBitStr(vector)\n\nReturns a BitStr. When the input is an integer, the bits are read from right to left. When the input is a vector, the bits are read from left to right.\n\nExamples\n\nBitStr supports some basic arithmetic operations. It acts like an integer, but supports some frequently used methods for binary basis.\n\njulia> bit\"0101\" * 2\n1010 ₍₂₎\n\njulia> join([bit\"101\" for i in 1:10])\n\"101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎101 ₍₂₎\"\n\njulia> repeat(bit\"101\", 2)\n101101 ₍₂₎\n\njulia> bit\"1101\"[2]\n0\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.DitStr","page":"BitBasis","title":"BitBasis.DitStr","text":"DitStr{D,N,T<:Integer} <: Integer\n\nThe struct for dit string with fixed length N and storage type T, where dit is a extension of dit from binary system to a d-ary system.\n\nDitStr{D,N,T}(integer)\nDitStr{D,N}(integer)\nDitStr{D}(vector)\n\nReturns a DitStr. When the input is an integer, the dits are read from right to left. When the input is a vector, the dits are read from left to right.\n\nExamples\n\njulia> DitStr{3}([1,2,1,1,0])\n01121 ₍₃₎\n\njulia> DitStr{3, 5}(71)\n02122 ₍₃₎\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.DitStr-Union{Tuple{BitBasis.SubDitStr{D, N, T}}, Tuple{T}, Tuple{N}, Tuple{D}} where {D, N, T}","page":"BitBasis","title":"BitBasis.DitStr","text":"DitStr(dit::SubDitStr{D,N,T}) -> DitStr{D,N,T}\n\nRaise type SubDitStr to DitStr.\n\njulia> x = DitStr{3, 5}(71)\n02122 ₍₃₎\n\njulia> sx = SubDitStr(x, 2, 4)\nSubDitStr{3, 5, Int64}(02122 ₍₃₎, 1, 3)\n\njulia> DitStr(sx)\n212 ₍₃₎\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.IterControl","page":"BitBasis","title":"BitBasis.IterControl","text":"IterControl{S}\nIterControl(n::Int, base::Int, masks, factors) -> IterControl\n\nIterator to iterate through controlled subspace. See also itercontrol. S is the number of chunks, n is the size of Hilbert space, base is the base of counter, masks and factors are helpers for enumerating over the target Hilbert Space.\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.LongLongUInt","page":"BitBasis","title":"BitBasis.LongLongUInt","text":"LongLongUInt{C} <: Integer\n\nA LongLongUInt{C} is an integer with C UInt numbers to store the value.\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.ReorderedBasis","page":"BitBasis","title":"BitBasis.ReorderedBasis","text":"ReorderedBasis{N, T}\n\nLazy reorderd basis.\n\n\n\n\n\n","category":"type"},{"location":"man/bitbasis.html#BitBasis.ReorderedBasis-Union{Tuple{Tuple{T, Vararg{T, N}}}, Tuple{T}, Tuple{N}} where {N, T<:Integer}","page":"BitBasis","title":"BitBasis.ReorderedBasis","text":"ReorderedBasis(orders::NTuple{N, <:Integer})\n\nReturns a lazy set of reordered basis.\n\n\n\n\n\n","category":"method"},{"location":"man/bitbasis.html#BitBasis.SubDitStr","page":"BitBasis","title":"BitBasis.SubDitStr","text":"SubDitStr{D,N,T<:Integer} <: Integer\n\nThe struct as a SubString-like object for DitStr(SubString is an official implementation of sliced strings, see String for reference). This slicing returns a view into the parent DitStr instead of making a copy (similar to the @views macro for strings).\n\nSubDitStr can be used to describe the qubit configuration within the subspace of the entire Hilbert space.It provides similar getindex, length functions as DitStr. \n\nSubDitStr(dit::DitStr{D,N,T}, i::Int, j::Int)\nSubDitStr(dit::DitStr{D,N,T}, r::AbstractUnitRange{<:Integer})\n\nOr by @views macro for DitStr (this macro makes your life easier by supporting begin and end syntax):\n\n@views dit[i:j]\n\nReturns a SubDitStr.\n\nExamples\n\njulia> x = DitStr{3, 5}(71)\n02122 ₍₃₎\n\njulia> sx = SubDitStr(x, 2, 4) \nSubDitStr{3, 5, Int64}(02122 ₍₃₎, 1, 3)\n\njulia> @views x[2:end] \nSubDitStr{3, 5, Int64}(02122 ₍₃₎, 1, 4)\n\njulia> sx == dit\"212;3\"\ntrue\n\n\n\n\n\n","category":"type"},{"location":"index.html","page":"Home","title":"Home","text":"CurrentModule = Yao","category":"page"},{"location":"index.html#Yao","page":"Home","title":"Yao","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"A General Purpose Quantum Computation Simulation Framework","category":"page"},{"location":"index.html","page":"Home","title":"Home","text":"Welcome to Yao, a Flexible, Extensible, Efficient Framework for Quantum Algorithm Design. Yao (幺) is the Chinese character for normalized but not orthogonal.","category":"page"},{"location":"index.html","page":"Home","title":"Home","text":"We aim to provide a powerful tool for researchers, students to study and explore quantum computing in near term future, before quantum computer being used in large-scale.","category":"page"},{"location":"index.html#Quick-Starts","page":"Home","title":"Quick Starts","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"You can learn how to use Yao with some quick examples in this section. There are three badges on the top of each tutorial that allows you to open it in mybinder, preview it in nbviewer or download the tutorial as .zip file, which includes the notebook and the scripts and other related materials.","category":"page"},{"location":"index.html#Contribution","page":"Home","title":"Contribution","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"If you are interesting in polishing or contributing our tutorial, you can just open a PR in our tutorial repo.","category":"page"},{"location":"index.html#Syntax","page":"Home","title":"Syntax","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"The tutorials are written with Literate.","category":"page"},{"location":"index.html#Pluto-Notebooks","page":"Home","title":"Pluto Notebooks","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"There is also a set of Pluto notebooks available in the notebooks folder","category":"page"},{"location":"index.html#Manual","page":"Home","title":"Manual","text":"","category":"section"},{"location":"index.html","page":"Home","title":"Home","text":"Pages = [\n \"man/array_registers.md\",\n \"man/blocks.md\",\n \"man/registers.md\",\n \"man/extending_blocks.md\",\n]\nDepth = 1","category":"page"},{"location":"man/simplification.html#Simplification","page":"Simplification","title":"Simplification","text":"","category":"section"},{"location":"man/simplification.html","page":"Simplification","title":"Simplification","text":"The simplification for YaoBlocks is currently implemented in a limited and straightforward fashion, there is only one interface simplify to call.","category":"page"},{"location":"man/simplification.html#APIs","page":"Simplification","title":"APIs","text":"","category":"section"},{"location":"man/simplification.html","page":"Simplification","title":"Simplification","text":"Modules = [YaoBlocks.Optimise]\nOrder = [:function, :macro]","category":"page"},{"location":"man/simplification.html#YaoBlocks.Optimise.is_pauli-Tuple","page":"Simplification","title":"YaoBlocks.Optimise.is_pauli","text":"is_pauli(x)\n\nCheck if x is an element of pauli group.\n\n\n\n\n\n","category":"method"},{"location":"man/simplification.html#YaoBlocks.Optimise.replace_block-Tuple{Any, AbstractBlock}","page":"Simplification","title":"YaoBlocks.Optimise.replace_block","text":"replace_block(actor, tree::AbstractBlock) -> AbstractBlock\nreplace_block(pair::Pair{Type{ST}, TT}, tree::AbstractBlock) -> AbstractBlock\n\nreplace blocks in a circuit, where actor is a function that given input block, returns the block to replace, or nothing for skip replacing and visit sibling. If pair is provided, then replace original block with type ST with new block (pair.second).\n\n\n\n\n\n","category":"method"},{"location":"man/simplification.html#YaoBlocks.Optimise.simplify-Tuple{AbstractBlock}","page":"Simplification","title":"YaoBlocks.Optimise.simplify","text":"simplify(block[; rules=__default_simplification_rules__])\n\nSimplify a block tree accroding to given rules, default to use YaoBlocks.Optimise.__default_simplification_rules__.\n\n\n\n\n\n","category":"method"},{"location":"man/simplification.html#YaoBlocks.Optimise.to_basictypes","page":"Simplification","title":"YaoBlocks.Optimise.to_basictypes","text":"to_basictypes(block::AbstractBlock)\n\nconvert gates to basic types\n\n* ChainBlock\n* PutBlock\n* PrimitiveBlock\n\n\n\n\n\n","category":"function"}] }