diff --git a/Project.toml b/Project.toml index eb3179e2..85719e4b 100644 --- a/Project.toml +++ b/Project.toml @@ -23,14 +23,12 @@ ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" ChainRulesTestUtils = "cdddcdb0-9152-4a09-a978-84456f9df70a" FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000" Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" -Quac = "b9105292-1415-45cf-bff1-d6ccf71e6143" [extensions] TenetChainRulesCoreExt = "ChainRulesCore" TenetChainRulesTestUtilsExt = ["ChainRulesCore", "ChainRulesTestUtils"] TenetFiniteDifferencesExt = "FiniteDifferences" TenetMakieExt = "Makie" -TenetQuacExt = "Quac" [compat] ChainRulesCore = "1.0" @@ -42,6 +40,5 @@ Graphs = "1.7" Makie = "0.18, 0.19" Muscle = "0.1" OMEinsum = "0.7" -Quac = "0.2" ValSplit = "0.1" julia = "1.9" diff --git a/README.md b/README.md index c46bac1d..f23d752f 100644 --- a/README.md +++ b/README.md @@ -22,15 +22,6 @@ A video of its presentation at JuliaCon 2023 can be seen here: - [x] Tensor Network slicing/cuttings - [x] Automatic Differentiation of TN contraction - [ ] Distributed contraction -- [ ] Quantum Tensor Networks - - [x] Matrix Product States (MPS) - - [x] Matrix Product Operators (MPO) - - [ ] Tree Tensor Networks (TTN) - - [x] Projected Entangled Pair States (PEPS) - - [ ] Multiscale Entanglement Renormalization Ansatz (MERA) -- [ ] Numerical Tensor Network algorithms - - [ ] Tensor Renormalization Group (TRG) - - [ ] Density Matrix Renormalization Group (DMRG) - [x] Local Tensor Network transformations - [x] Hyperindex converter - [x] Rank simplification @@ -39,4 +30,3 @@ A video of its presentation at JuliaCon 2023 can be seen here: - [x] Column reduction - [x] Split simplification - [x] 2D & 3D visualization of large networks, powered by [`Makie`](https://github.com/MakieOrg/Makie.jl) -- [x] Translation from quantum circuits, powered by [`Quac`](https://github.com/bsc-quantic/Quac.jl) diff --git a/docs/Project.toml b/docs/Project.toml index e4a848fd..02b785d2 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -5,7 +5,6 @@ DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244" EinExprs = "b1794770-133b-4de1-afb4-526377e9f4c5" Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" NetworkLayout = "46757867-2c16-5918-afeb-47bfcb05e46a" -QuacIO = "0dfb065c-ad45-4a42-9a50-cb82c165eb0b" Tenet = "85d41934-b9cd-44e1-8730-56d86f15f3ec" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" diff --git a/docs/make.jl b/docs/make.jl index b8dff0c7..89c2d0b1 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -20,21 +20,10 @@ makedocs( pages = Any[ "Home"=>"index.md", "Tensors"=>"tensors.md", - "Tensor Networks"=>[ - "Introduction" => "tensor-network.md", - "Contraction" => "contraction.md", - "Transformations" => "transformations.md", - "Visualization" => "visualization.md", - ], - "Quantum Tensor Networks"=>[ - "Introduction" => "quantum/index.md", - "Matrix Product States (MPS)" => "quantum/mps.md", - "Projected Entangled Pair States (PEPS)" => "quantum/peps.md", - ], - "Examples"=>[ - "Google's Quantum Advantage experiment" => "examples/google-rqc.md", - "Automatic Differentiation on Tensor Network contraction" => "examples/ad-tn.md", - ], + "Tensor Networks"=>"tensor-network.md", + "Contraction"=>"contraction.md", + "Transformations"=>"transformations.md", + "Visualization"=>"visualization.md", "Alternatives"=>"alternatives.md", "References"=>"references.md", ], diff --git a/docs/src/examples/ad-tn.md b/docs/src/examples/ad-tn.md deleted file mode 100644 index 638dd735..00000000 --- a/docs/src/examples/ad-tn.md +++ /dev/null @@ -1,69 +0,0 @@ -# Automatic Differentiation on Tensor Network contraction - -```@setup autodiff -using CairoMakie -``` - -Tensor Networks have recently gained popularity for Machine Learning tasks. -In this example, we show how to perform Automatic Differentiation on Tensor Network contraction to overlap the overlap between two [Matrix Product States (MPS)](@ref) with a smaller dimension. - -```@example autodiff -using Tenet -using Zygote -using Random: seed! # hide - -rng = seed!(4) # hide - -ψ = rand(MPS{Open}, n = 4, p = 2, χ = 2) -ϕ = rand(MPS{Open}, n = 4, p = 2, χ = 4) -ψ = rand(rng, MPS{Open}, n = 4, p = 2, χ = 2) # hide -ϕ = rand(rng, MPS{Open}, n = 4, p = 2, χ = 4) # hide - -tn = merge(ψ, ϕ') - -plot(tn) # hide -``` - -This problem is known as _MPS compression_. -While there are better methods for this matter, this example excels for its simplicity and it can easily be modified for ML tasks. -The loss function minimizes when the overlap between the two states ``\psi`` and ``\phi`` maximizes, constrained to normalized states. - -```math -\begin{aligned} -\min_\psi \quad & \left(\braket{\phi | \psi} - 1\right)^2 \\ -\textrm{s.t.} \quad & \lVert \psi \rVert^2 = \braket{\psi \mid \psi} = 1 \\ - & \lVert \phi \rVert^2 = \braket{\phi \mid \phi} = 1 -\end{aligned} -``` - -!!! warning "Implicit parameters" - Currently, calling `Zygote.gradient`/`Zygote.jacobian` on functions with explicit parameters doesn't interact well with `Tenet` data-structures (i.e. `Tensor` and `TensorNetwork`) on the interface. - - While the problem persists, use implicit parameters with `Zygote.Params` on the arrays (i.e. call `Params([parent(tensor)])` or `Params([arrays(tensor_network)])`). - -```@example autodiff -η = 0.01 -@time losses = map(1:200) do it - # compute gradient - loss, ∇ = withgradient(Params(arrays(ψ))) do - ((contract(tn) |> first) - 1)^2 - end - - # direct gradient descent - for array in arrays(ψ) - array .-= η * ∇[array] - end - - # normalize state - normalize!(ψ) - - return loss -end - -f = Figure() # hide -ax = Axis(f[1, 1], yscale = log10, xscale = identity, xlabel="Iterations") # hide -lines!(losses, label="Loss") # hide -lines!(map(x -> 1 - sqrt(x), losses), label="Overlap") # hide -f[1,2] = Legend(f, ax, framevisible=false) # hide -f # hide -``` diff --git a/docs/src/examples/google-rqc.md b/docs/src/examples/google-rqc.md deleted file mode 100644 index 8f945228..00000000 --- a/docs/src/examples/google-rqc.md +++ /dev/null @@ -1,93 +0,0 @@ -# Google's Quantum Advantage experiment - -```@setup circuit -using CairoMakie -CairoMakie.activate!(type = "svg") -using NetworkLayout -``` - -!!! info "Dependencies 📦" - This example uses `QuacIO` and `EinExprs` in combination with `Tenet`. - Both packages can be found in [Quantic's registry](https://github.com/bsc-quantic/Registry) and can be installed in Pkg mode. - - ```julia - add QuacIO EinExprs - ``` - - It also requires the circuit in `sycamore_m53_d10.qasm` file that can be found in [here](./sycamore_53_10_0.qasm). - This is a shorter version of the real circuit used for the experiment. - -In 2019, Google rushed to claim _quantum advantage_[^supremacy] for the first time ever [arute2019quantum](@cite)[villalonga2020establishing](@cite). -The article was highly criticized and one year later, it was disproved [gray2021hyper](@cite) by developing a better heuristic search for contraction path which provided a $\times 10^4$ speedup. - -[^supremacy]: The first used term was _quantum supremacy_ although the community transitioned to _quantum advantage_ due to political reasons. However, Google now uses the term _beyond classical_. It is then not uncommon to find different terms to refer to the same thing: the moment in which quantum computers surpass classical computers on solving some problem. - -Since then, several teams and companies have come and go, proposing and disproving several experiments. But in this example, we focus on the original Google experiment. - -In short, the experiment consisted on sampling Random Quantum Circuits (RQC). -The state of the systems after these circuits follow a distribution similar, but **not equal** to the uniform distribution. -Due to noise and decoherence, the fidelity of quantum chips decrease with the circuit depth. -The complexity of contracting tensor networks grows with the circuit depth, but due to the fidelity of the physical realization being small, a very rough approximation can be used. -In the case of Google, they used _tensor slicing_ for projecting some expensive to contract indices. -Since the contribution of each quantum path is guessed to be similar, each slice should contribute a similar part, and by taking the same percentage of slices as the fidelity of the quantum experiment, we obtain a result with a similar fidelity. -If you want to read more on the topic, check out [boixo2018characterizing](@cite),[markov2018quantum](@cite). - -Thanks to `Tenet`'s much cared design, the experiment can be replicated conceptually in less than 20loc. - -```@example circuit -using QuacIO -using Tenet - -_sites = [5, 6, 14, 15, 16, 17, 24, 25, 26, 27, 28, 32, 33, 34, 35, 36, 37, 38, 39, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 72, 73, 74, 75, 76, 83, 84, 85, 94]; - -# load circuit and convert to `TensorNetwork` -circuit = QuacIO.parse(joinpath(@__DIR__, "sycamore_53_10_0.qasm"), format = QuacIO.Qflex(), sites = _sites); -tn = QuantumTensorNetwork(circuit) -tn = view(tn, [i => 1 for i in inds(tn, set=:open)]...) -plot(tn) # hide -``` - -In order to aid the contraction path optimization, we shrink the search space by using local transformations. - -```@example circuit -# simplify Tensor Network by preemptively contracting trivial cases -tn = transform(tn, Tenet.RankSimplification) -plot(tn, layout=Stress()) # hide -``` - -Contraction path optimization is the focus of the [`EinExprs`](https://github.com/bsc-quantic/EinExprs.jl) package. For this example, we will use the `Greedy` algorithm which doesn't yield the optimal path but it's fast and reproducible. - -```@example circuit -using EinExprs -path = einexpr(tn, optimizer = Greedy) -plot(path, layout=Stress()) # hide -``` - -Then, the indices to be sliced have to be selected. `EinExprs` provides us with the `findslices` algorithm (based in the `SliceFinder` algorithm of [cotengra](@cite)) to suggest candidate indices for slicing. - -```julia -cuttings = [[i => dim for dim in 1:size(tn,i)] for i in findslices(FlopsScorer(), path, slices=100)] -``` - -Finally, the contraction of slices is parallelized using distributed workers and each contribution is summed to `result`. - -```julia -using Distributed -using Iterators: product - -addprocs(10) - -@everywhere using Tenet, EinExprs -@everywhere tn = $tn -@everywhere path = $path - -result = @distributed (+) for proj_inds in product(cuttings...) - slice = view(tn, proj_inds...) - - for indices in contractorder(path) - contract!(slice, indices) - end - - tensors(slice) |> only -end -``` diff --git a/docs/src/examples/sycamore_53_10_0.qasm b/docs/src/examples/sycamore_53_10_0.qasm deleted file mode 100644 index 1d701b02..00000000 --- a/docs/src/examples/sycamore_53_10_0.qasm +++ /dev/null @@ -1,1659 +0,0 @@ -53 -0 hz_1_2 5 -0 x_1_2 6 -0 x_1_2 14 -0 hz_1_2 15 -0 y_1_2 16 -0 hz_1_2 17 -0 hz_1_2 24 -0 hz_1_2 25 -0 hz_1_2 26 -0 x_1_2 27 -0 y_1_2 28 -0 hz_1_2 32 -0 hz_1_2 33 -0 hz_1_2 34 -0 hz_1_2 35 -0 y_1_2 36 -0 x_1_2 37 -0 x_1_2 38 -0 hz_1_2 39 -0 x_1_2 41 -0 x_1_2 42 -0 hz_1_2 43 -0 y_1_2 44 -0 x_1_2 45 -0 x_1_2 46 -0 y_1_2 47 -0 hz_1_2 48 -0 x_1_2 49 -0 hz_1_2 50 -0 hz_1_2 51 -0 x_1_2 52 -0 x_1_2 53 -0 x_1_2 54 -0 y_1_2 55 -0 hz_1_2 56 -0 y_1_2 57 -0 hz_1_2 58 -0 hz_1_2 61 -0 hz_1_2 62 -0 y_1_2 63 -0 hz_1_2 64 -0 x_1_2 65 -0 x_1_2 66 -0 x_1_2 67 -0 hz_1_2 72 -0 y_1_2 73 -0 x_1_2 74 -0 hz_1_2 75 -0 y_1_2 76 -0 y_1_2 83 -0 y_1_2 84 -0 hz_1_2 85 -0 x_1_2 94 -1 rz(0.7743385483953005) 6 -1 rz(-0.7085204779284944) 16 -1 rz(-0.8687711187158653) 15 -1 rz(0.3853766657859231) 25 -1 rz(-0.3522159558487364) 17 -1 rz(0.569527381436443) 27 -1 rz(0.06748036788071975) 24 -1 rz(-0.03542260032736748) 34 -1 rz(0.921123478965347) 26 -1 rz(-0.940605149780575) 36 -1 rz(0.40878079457469985) 28 -1 rz(-0.3573777822597026) 38 -1 rz(0.4286328898578044) 33 -1 rz(-0.567173927172081) 43 -1 rz(0.6962362636582926) 35 -1 rz(-0.6243336356713873) 45 -1 rz(0.5070267688233168) 37 -1 rz(-0.49025706927611445) 47 -1 rz(-0.82479487914479) 39 -1 rz(0.831505604695568) 49 -1 rz(0.7654710267272109) 42 -1 rz(-0.7622667609489339) 52 -1 rz(-0.7530995459405583) 44 -1 rz(0.7063901684965722) 54 -1 rz(-0.7750964509509387) 46 -1 rz(0.9619956872914577) 56 -1 rz(-0.8310454946335954) 48 -1 rz(0.8149432193242095) 58 -1 rz(0.568448771120722) 51 -1 rz(-0.5458328527656618) 61 -1 rz(0.46444025457872556) 53 -1 rz(-0.8641681946768033) 63 -1 rz(0.33639050361710615) 55 -1 rz(-0.4121311900075394) 65 -1 rz(0.881176970884841) 57 -1 rz(-0.8199816956867351) 67 -1 rz(-0.5174631371535426) 62 -1 rz(0.5093922035705379) 72 -1 rz(-0.2684453761112637) 64 -1 rz(0.26751780455859997) 74 -1 rz(0.7883616255904944) 66 -1 rz(0.9304903862480522) 76 -1 rz(0.5471409474788239) 73 -1 rz(-0.5891117186780521) 83 -1 rz(0.7384907660505857) 75 -1 rz(-0.7451407522809496) 85 -1 rz(-0.1830293948567971) 84 -1 rz(-0.1757017537984857) 94 -2 fsim(0.48248590238931144, 0.17720711726780922) 6 16 -2 fsim(0.4831173807612162, 0.1575031878359891) 15 25 -2 fsim(0.5104652445279683, 0.1518018478533972) 17 27 -2 fsim(0.483109325847836, 0.16101107882693258) 24 34 -2 fsim(0.48552394043342284, 0.14819609246068247) 26 36 -2 fsim(0.5137841338574078, 0.15735440433706077) 28 38 -2 fsim(0.49264217592278786, 0.14098000393237992) 33 43 -2 fsim(0.48501709381128927, 0.14949793435121178) 35 45 -2 fsim(0.48656355637175525, 0.18260338861410977) 37 47 -2 fsim(0.49284428894552623, 0.15792655003519906) 39 49 -2 fsim(0.521298630708583, 0.21928323341492764) 42 52 -2 fsim(0.486998183067378, 0.15361268278864498) 44 54 -2 fsim(0.486390931075892, 0.1626489398497966) 46 56 -2 fsim(0.4813094673968524, 0.15327107428645925) 48 58 -2 fsim(0.47975471412767756, 0.16199668846067358) 51 61 -2 fsim(0.492110274286689, 0.1687807392184565) 53 63 -2 fsim(0.4827686976879951, 0.14378566187650293) 55 65 -2 fsim(0.46465889570960195, 0.13416717007279197) 57 67 -2 fsim(0.48881240027593537, 0.14984846721738163) 62 72 -2 fsim(0.4831873565264152, 0.16620074089526124) 64 74 -2 fsim(0.4764882949770173, 0.13770458644228914) 66 76 -2 fsim(0.48112498558227507, 0.15642764309600338) 73 83 -2 fsim(0.47456208123909566, 0.15553396824213445) 75 85 -2 fsim(0.5144705816268026, 0.1596097876378056) 84 94 -3 rz(-0.7618064157555159) 6 -3 rz(0.827624486222322) 16 -3 rz(0.677790595837605) 15 -3 rz(0.8388149512324528) 25 -3 rz(0.34915411632258214) 17 -3 rz(-0.13184269073487556) 27 -3 rz(0.4610625765182105) 24 -3 rz(-0.4290048089648583) 34 -3 rz(0.6641998401797986) 26 -3 rz(-0.6836815109950266) 36 -3 rz(0.026240452181357746) 28 -3 rz(0.025162560133639312) 38 -3 rz(0.9071761579568303) 33 -3 rz(0.9542828047288932) 43 -3 rz(-0.46145806100291004) 35 -3 rz(0.5333606889898155) 45 -3 rz(0.5128100748460089) 37 -3 rz(-0.4960403752988061) 47 -3 rz(0.5829645187562967) 39 -3 rz(-0.5762537932055181) 49 -3 rz(0.022811401598836913) 42 -3 rz(-0.019607135820559906) 52 -3 rz(0.8523020333228131) 44 -3 rz(-0.8990114107667992) 54 -3 rz(0.9352866185158868) 46 -3 rz(-0.7483873821753678) 56 -3 rz(-0.9220101925888569) 48 -3 rz(0.9059079172794712) 58 -3 rz(0.7039221690166656) 51 -3 rz(-0.6813062506616053) 61 -3 rz(0.6965073865506469) 53 -3 rz(0.9037646733512754) 63 -3 rz(-0.45310524873049973) 55 -3 rz(0.3773645623400665) 65 -3 rz(0.42017342300456634) 57 -3 rz(-0.3589781478064599) 67 -3 rz(0.9534707755965702) 62 -3 rz(-0.9615417091795746) 72 -3 rz(0.5368636250628501) 64 -3 rz(-0.5377911966155139) 74 -3 rz(0.5123942238917779) 66 -3 rz(-0.7935422120532315) 76 -3 rz(-0.7898684772427236) 73 -3 rz(0.7478977060434954) 83 -3 rz(-0.8571455144841159) 75 -3 rz(0.8504955282537521) 85 -3 rz(0.9094649565590708) 84 -3 rz(0.7318038947856463) 94 -4 y_1_2 5 -4 y_1_2 6 -4 y_1_2 14 -4 x_1_2 15 -4 x_1_2 16 -4 x_1_2 17 -4 x_1_2 24 -4 x_1_2 25 -4 y_1_2 26 -4 hz_1_2 27 -4 x_1_2 28 -4 x_1_2 32 -4 y_1_2 33 -4 x_1_2 34 -4 y_1_2 35 -4 hz_1_2 36 -4 hz_1_2 37 -4 y_1_2 38 -4 y_1_2 39 -4 hz_1_2 41 -4 y_1_2 42 -4 y_1_2 43 -4 hz_1_2 44 -4 y_1_2 45 -4 y_1_2 46 -4 hz_1_2 47 -4 x_1_2 48 -4 hz_1_2 49 -4 y_1_2 50 -4 y_1_2 51 -4 y_1_2 52 -4 y_1_2 53 -4 hz_1_2 54 -4 hz_1_2 55 -4 y_1_2 56 -4 x_1_2 57 -4 x_1_2 58 -4 x_1_2 61 -4 y_1_2 62 -4 x_1_2 63 -4 y_1_2 64 -4 hz_1_2 65 -4 hz_1_2 66 -4 y_1_2 67 -4 y_1_2 72 -4 x_1_2 73 -4 hz_1_2 74 -4 y_1_2 75 -4 x_1_2 76 -4 x_1_2 83 -4 x_1_2 84 -4 y_1_2 85 -4 hz_1_2 94 -5 rz(0.07221640979880403) 5 -5 rz(0.17734365608174887) 15 -5 rz(-0.7166427083722222) 14 -5 rz(0.717673588252228) 24 -5 rz(-0.1312926423470736) 16 -5 rz(0.13158529074665537) 26 -5 rz(0.7500367576549269) 25 -5 rz(-0.31797150857789674) 35 -5 rz(-0.8756735306896725) 27 -5 rz(-0.9327732133062662) 37 -5 rz(0.7071565092929694) 32 -5 rz(-0.6264998637477406) 42 -5 rz(0.82790347048799) 34 -5 rz(-0.8594778743809006) 44 -5 rz(0.8064559428449068) 36 -5 rz(-0.7629602352736249) 46 -5 rz(-0.23630732076940514) 38 -5 rz(0.25438180016733336) 48 -5 rz(0.6476084230939583) 41 -5 rz(-0.6528339440806201) 51 -5 rz(-0.20879565669998532) 43 -5 rz(-0.26053049452558324) 53 -5 rz(-0.7777343640360711) 45 -5 rz(0.8805385932920736) 55 -5 rz(-0.5137630264839785) 47 -5 rz(0.48179097076948874) 57 -5 rz(0.7693840211762448) 52 -5 rz(-0.7680082232923118) 62 -5 rz(0.14188452450562264) 54 -5 rz(-0.1339396318115881) 64 -5 rz(-0.95616894502165) 56 -5 rz(-0.9015807139989003) 66 -5 rz(-0.3168365530459615) 63 -5 rz(0.2898226701533191) 73 -5 rz(-0.32361247881294825) 65 -5 rz(0.27931184143712456) 75 -5 rz(0.884543382731205) 74 -5 rz(-0.8540367322639986) 84 -6 fsim(0.4836037489865321, 0.15720448517258814) 5 15 -6 fsim(0.4813027746287272, 0.16589400016587655) 14 24 -6 fsim(0.5141011050173628, 0.23139995996898027) 16 26 -6 fsim(0.4860333525890109, 0.1603093406600409) 25 35 -6 fsim(0.48318175023922383, 0.1564279262034107) 27 37 -6 fsim(0.4893783671604143, 0.1436061569230382) 32 42 -6 fsim(0.4885622789540625, 0.14820473190374475) 34 44 -6 fsim(0.48365869422848307, 0.16133729898079696) 36 46 -6 fsim(0.5035633150535174, 0.17812225242391694) 38 48 -6 fsim(0.47971143268846445, 0.14388623656266197) 41 51 -6 fsim(0.48615849941720374, 0.1566149748128868) 43 53 -6 fsim(0.4819082002062166, 0.14615816911657503) 45 55 -6 fsim(0.4909994945412715, 0.16098322131650447) 47 57 -6 fsim(0.4912337946314961, 0.18012457108936253) 52 62 -6 fsim(0.46508517467774446, 0.17301578991022867) 54 64 -6 fsim(0.4625029911035914, 0.13951781372243774) 56 66 -6 fsim(0.5169231411118692, 0.15867863143208272) 63 73 -6 fsim(0.4737902812504438, 0.15803377395648677) 65 75 -6 fsim(0.47857129167400153, 0.15930690639357745) 74 84 -7 rz(0.10267615219883607) 5 -7 rz(0.14688391368171685) 15 -7 rz(0.5303948572093229) 14 -7 rz(-0.529363977329317) 24 -7 rz(-0.6623304931849363) 16 -7 rz(0.6626231415845181) 26 -7 rz(0.06783382350879162) 25 -7 rz(0.36423142556823856) 35 -7 rz(-0.9730909692986618) 27 -7 rz(-0.8353557746972768) 37 -7 rz(-0.5361169534193021) 32 -7 rz(0.6167735989645307) 42 -7 rz(-0.6122117071342573) 34 -7 rz(0.5806373032413467) 44 -7 rz(0.968052322606287) 36 -7 rz(-0.9245566150350051) 46 -7 rz(-0.6534917441628949) 38 -7 rz(0.6715662235608231) 48 -7 rz(-0.7407238202696524) 41 -7 rz(0.7354982992829906) 51 -7 rz(-0.06340668623729523) 43 -7 rz(-0.40591946498827336) 53 -7 rz(-0.4557556128718794) 45 -7 rz(0.558559842127882) 55 -7 rz(0.923796560084577) 47 -7 rz(-0.9557686157990668) 57 -7 rz(0.6313087990584325) 52 -7 rz(-0.6299330011745) 62 -7 rz(-0.20274234705300925) 54 -7 rz(0.21068723974704434) 64 -7 rz(0.5124187849542257) 56 -7 rz(-0.3701684439747759) 66 -7 rz(-0.3038733131602001) 63 -7 rz(0.2768594302675577) 73 -7 rz(0.26284256852387516) 65 -7 rz(-0.3071432058996983) 75 -7 rz(0.7502523839911145) 74 -7 rz(-0.719745733523908) 84 -8 x_1_2 5 -8 x_1_2 6 -8 x_1_2 14 -8 hz_1_2 15 -8 hz_1_2 16 -8 y_1_2 17 -8 hz_1_2 24 -8 hz_1_2 25 -8 x_1_2 26 -8 y_1_2 27 -8 y_1_2 28 -8 y_1_2 32 -8 x_1_2 33 -8 y_1_2 34 -8 x_1_2 35 -8 y_1_2 36 -8 y_1_2 37 -8 x_1_2 38 -8 x_1_2 39 -8 y_1_2 41 -8 hz_1_2 42 -8 x_1_2 43 -8 x_1_2 44 -8 x_1_2 45 -8 hz_1_2 46 -8 y_1_2 47 -8 y_1_2 48 -8 y_1_2 49 -8 hz_1_2 50 -8 hz_1_2 51 -8 x_1_2 52 -8 x_1_2 53 -8 x_1_2 54 -8 x_1_2 55 -8 x_1_2 56 -8 hz_1_2 57 -8 hz_1_2 58 -8 y_1_2 61 -8 hz_1_2 62 -8 y_1_2 63 -8 hz_1_2 64 -8 x_1_2 65 -8 x_1_2 66 -8 hz_1_2 67 -8 x_1_2 72 -8 hz_1_2 73 -8 y_1_2 74 -8 x_1_2 75 -8 hz_1_2 76 -8 hz_1_2 83 -8 hz_1_2 84 -8 x_1_2 85 -8 y_1_2 94 -9 rz(0.868874517623681) 5 -9 rz(-0.5062300204223075) 6 -9 rz(0.6874509025876478) 14 -9 rz(-0.6826684237245009) 15 -9 rz(0.3757979651191995) 16 -9 rz(-0.3369000264078134) 17 -9 rz(0.5165579149683887) 25 -9 rz(-0.9838406309684837) 26 -9 rz(0.6517543596020707) 27 -9 rz(-0.8938908007211287) 28 -9 rz(0.011576333256837757) 32 -9 rz(0.1994965304792813) 33 -9 rz(-0.5357402786793479) 34 -9 rz(0.5797224477448737) 35 -9 rz(0.6015756389470484) 36 -9 rz(-0.573317645438219) 37 -9 rz(0.3791786031325414) 38 -9 rz(-0.676931394322152) 39 -9 rz(0.6257613274555152) 41 -9 rz(-0.6210571332355261) 42 -9 rz(-0.45193657844083596) 43 -9 rz(0.16633011275543763) 44 -9 rz(-0.8632357323678501) 45 -9 rz(0.5580904452638696) 46 -9 rz(0.7226189706701976) 47 -9 rz(-0.7708292466716248) 48 -9 rz(-0.628899885711077) 50 -9 rz(0.8564821803203452) 51 -9 rz(-0.48600051750832335) 52 -9 rz(0.40704671139578114) 53 -9 rz(0.7509923227943213) 54 -9 rz(-0.7705635810307807) 55 -9 rz(0.5247429096711106) 56 -9 rz(-0.31560248875795377) 57 -9 rz(0.4445283033807374) 61 -9 rz(-0.43843587057450184) 62 -9 rz(0.23079678484166474) 63 -9 rz(-0.24296757608244463) 64 -9 rz(-0.6933510795197081) 65 -9 rz(0.7747059716945244) 66 -9 rz(0.6297402023667946) 72 -9 rz(-0.650250406527777) 73 -9 rz(0.8327738427573091) 74 -9 rz(-0.8966188475674683) 75 -9 rz(0.12025352080627527) 83 -9 rz(-0.029370019547682955) 84 -10 fsim(0.49365264175466117, 0.15525133396347482) 5 6 -10 fsim(0.47303698530749166, 0.15851903504005288) 14 15 -10 fsim(0.4860239014600936, 0.16383319416244227) 16 17 -10 fsim(0.47760865431703853, 0.1722820082764079) 25 26 -10 fsim(0.509171230744336, 0.16804022614589761) 27 28 -10 fsim(0.488759902041367, 0.1333685928255776) 32 33 -10 fsim(0.4920570546033223, 0.16987541076683108) 34 35 -10 fsim(0.4982034875822141, 0.16859518356435038) 36 37 -10 fsim(0.5169469113973622, 0.15443156883098344) 38 39 -10 fsim(0.5100156470228439, 0.15919887714218442) 41 42 -10 fsim(0.5013161698221332, 0.16668826789830035) 43 44 -10 fsim(0.48505020747377536, 0.15126442409592716) 45 46 -10 fsim(0.4910557144645823, 0.16553543587639166) 47 48 -10 fsim(0.4531292444443958, 0.1672349617084543) 50 51 -10 fsim(0.4811161821494542, 0.14574797118653934) 52 53 -10 fsim(0.4892984073437459, 0.18061915843291854) 54 55 -10 fsim(0.4807798603179813, 0.1432020872458372) 56 57 -10 fsim(0.47699857306165455, 0.2028158162407915) 61 62 -10 fsim(0.47981318946926454, 0.15237439630820673) 63 64 -10 fsim(0.4737599636880325, 0.14788136570201332) 65 66 -10 fsim(0.4902284723641499, 0.1632425516276174) 72 73 -10 fsim(0.5048672988301155, 0.15248440735797275) 74 75 -10 fsim(0.49753578048082747, 0.15466472657491784) 83 84 -11 rz(-0.6542790087648793) 5 -11 rz(-0.9830764940337477) 6 -11 rz(-0.7079366355498636) 14 -11 rz(0.7127191144130105) 15 -11 rz(-0.5003181025167607) 16 -11 rz(0.5392160412281468) 17 -11 rz(-0.4944938908636658) 25 -11 rz(0.027211174863570817) 26 -11 rz(0.5893795615335414) 27 -11 rz(-0.831516002652599) 28 -11 rz(-0.21350946680641048) 32 -11 rz(0.42458233054252953) 33 -11 rz(-0.14729238052848453) 34 -11 rz(0.19127454959401033) 35 -11 rz(0.00982266418345571) 36 -11 rz(0.018435329325373753) 37 -11 rz(-0.2092460914861244) 38 -11 rz(-0.08850669970348643) 39 -11 rz(-0.04816660891478307) 41 -11 rz(0.05287080313477205) 42 -11 rz(-0.5144804279802232) 43 -11 rz(0.2288739622948249) 44 -11 rz(0.6539308607246773) 45 -11 rz(-0.9590761478286578) 46 -11 rz(-0.6105530873621177) 47 -11 rz(0.5623428113606904) 48 -11 rz(0.4541035216184288) 50 -11 rz(-0.22652122700916058) 51 -11 rz(-0.09920368129230818) 52 -11 rz(0.020249875179765953) 53 -11 rz(-0.7703835607337791) 54 -11 rz(0.7508123024973197) 55 -11 rz(-0.9299380908209051) 56 -11 rz(-0.8609214882659385) 57 -11 rz(-0.6603148238966917) 61 -11 rz(0.6664072567029273) 62 -11 rz(0.011997302735339959) 63 -11 rz(-0.02416809397611926) 64 -11 rz(0.7541471791694208) 65 -11 rz(-0.6727922869946045) 66 -11 rz(0.21828350563706272) 72 -11 rz(-0.2387937097980442) 73 -11 rz(0.8775865857149596) 74 -11 rz(-0.9414315905251189) 75 -11 rz(0.5077173122630191) 83 -11 rz(-0.4168338110044266) 84 -12 hz_1_2 5 -12 hz_1_2 6 -12 y_1_2 14 -12 x_1_2 15 -12 x_1_2 16 -12 x_1_2 17 -12 y_1_2 24 -12 x_1_2 25 -12 y_1_2 26 -12 x_1_2 27 -12 hz_1_2 28 -12 hz_1_2 32 -12 hz_1_2 33 -12 hz_1_2 34 -12 hz_1_2 35 -12 hz_1_2 36 -12 hz_1_2 37 -12 y_1_2 38 -12 y_1_2 39 -12 hz_1_2 41 -12 y_1_2 42 -12 hz_1_2 43 -12 hz_1_2 44 -12 y_1_2 45 -12 y_1_2 46 -12 x_1_2 47 -12 x_1_2 48 -12 x_1_2 49 -12 y_1_2 50 -12 x_1_2 51 -12 hz_1_2 52 -12 hz_1_2 53 -12 hz_1_2 54 -12 y_1_2 55 -12 hz_1_2 56 -12 x_1_2 57 -12 x_1_2 58 -12 x_1_2 61 -12 x_1_2 62 -12 hz_1_2 63 -12 x_1_2 64 -12 hz_1_2 65 -12 hz_1_2 66 -12 y_1_2 67 -12 hz_1_2 72 -12 y_1_2 73 -12 x_1_2 74 -12 hz_1_2 75 -12 y_1_2 76 -12 x_1_2 83 -12 y_1_2 84 -12 hz_1_2 85 -12 x_1_2 94 -13 rz(0.493850693839934) 15 -13 rz(-0.46824735745938767) 16 -13 rz(0.2984751103100736) 24 -13 rz(-0.7975917880942631) 25 -13 rz(-0.2590669520927105) 26 -13 rz(0.46553678230138035) 27 -13 rz(0.4922863320894708) 33 -13 rz(-0.4386037696673656) 34 -13 rz(-0.9729214362671511) 35 -13 rz(0.9612016987900408) 36 -13 rz(0.4556017204511883) 37 -13 rz(-0.4602146990123172) 38 -13 rz(-0.17115863024938213) 42 -13 rz(-0.07406694571515549) 43 -13 rz(-0.04747985536414887) 44 -13 rz(-0.0015617338005978266) 45 -13 rz(0.2389354663504067) 46 -13 rz(-0.2865947391710613) 47 -13 rz(-0.5880773071541381) 48 -13 rz(0.6362285069775276) 49 -13 rz(0.3964494752371541) 51 -13 rz(-0.38670528408761545) 52 -13 rz(0.011734933093958058) 53 -13 rz(0.0011415796799869179) 54 -13 rz(-0.5924971027747271) 55 -13 rz(0.6771826672314938) 56 -13 rz(-0.42942159755003484) 57 -13 rz(0.5342946187446849) 58 -13 rz(-0.8039587731906531) 62 -13 rz(0.6712120667598861) 63 -13 rz(-0.878510082642783) 64 -13 rz(0.8658791452001359) 65 -13 rz(-0.13314967964918875) 66 -13 rz(0.3134985834412089) 67 -13 rz(-0.13421982786758235) 73 -13 rz(0.14142059663243078) 74 -13 rz(-0.24729161215179005) 75 -13 rz(-0.1789596367298805) 76 -13 rz(0.7475635765288697) 84 -13 rz(-0.8844707307377268) 85 -14 fsim(0.4721504021115573, 0.15695816747993444) 15 16 -14 fsim(0.4825634211282305, 0.15867828327762148) 24 25 -14 fsim(0.48824316009376834, 0.15951491059929712) 26 27 -14 fsim(0.47115582838766157, 0.15190773431751792) 33 34 -14 fsim(0.48231141888350276, 0.1585063414575064) 35 36 -14 fsim(0.4865342593572244, 0.16427486274391248) 37 38 -14 fsim(0.5050345537310194, 0.15144542443009287) 42 43 -14 fsim(0.48807396570956973, 0.14318657147960762) 44 45 -14 fsim(0.48249755474463474, 0.14845262365278886) 46 47 -14 fsim(0.4980006261021947, 0.15119064727561662) 48 49 -14 fsim(0.4984695188566927, 0.18004531009583208) 51 52 -14 fsim(0.4842091684198735, 0.16094100162415842) 53 54 -14 fsim(0.48011792378547014, 0.1580141230640478) 55 56 -14 fsim(0.48023421368651875, 0.14013840287026855) 57 58 -14 fsim(0.49842022326892416, 0.15044767636993245) 62 63 -14 fsim(0.484447874980701, 0.16984474255103443) 64 65 -14 fsim(0.49342767762518064, 0.14018741526981413) 66 67 -14 fsim(0.47190475607081295, 0.21827595026961338) 73 74 -14 fsim(0.47561747564029094, 0.14608866678530144) 75 76 -14 fsim(0.49298021632342415, 0.14221762546243955) 84 85 -15 rz(-0.599747845729294) 15 -15 rz(0.6253511821098403) 16 -15 rz(0.9185238680705767) 24 -15 rz(0.5823594541452338) 25 -15 rz(0.017602831844571624) 26 -15 rz(0.18886699836409832) 27 -15 rz(-0.4113331864284153) 33 -15 rz(0.46501574885052055) 34 -15 rz(-0.7427018606296518) 35 -15 rz(0.7309821231525422) 36 -15 rz(-0.4572604632711416) 37 -15 rz(0.45264748471001387) 38 -15 rz(0.8287439256872393) 42 -15 rz(0.9260304983482223) 43 -15 rz(-0.5539049867836513) 44 -15 rz(0.5048633976189045) 45 -15 rz(0.17394491383358626) 46 -15 rz(-0.22160418665424148) 47 -15 rz(0.24017847920109392) 48 -15 rz(-0.19202727937770428) 49 -15 rz(-0.37039764324017677) 51 -15 rz(0.38014183438971544) 52 -15 rz(-0.34101503555577156) 53 -15 rz(0.35389154832971653) 54 -15 rz(0.6559023537995501) 55 -15 rz(-0.5712167893427836) 56 -15 rz(0.4498659567527707) 57 -15 rz(-0.34499293555812066) 58 -15 rz(0.4151204811787974) 62 -15 rz(-0.5478671876095643) 63 -15 rz(-0.6044391967350843) 64 -15 rz(0.5918082592924367) 65 -15 rz(-0.3382065832034761) 66 -15 rz(0.5185554869954963) 67 -15 rz(0.3976402333451519) 73 -15 rz(-0.3904394645803035) 74 -15 rz(0.44626364529659257) 75 -15 rz(-0.8725148941782631) 76 -15 rz(-0.7580489709662166) 84 -15 rz(0.6211418167573595) 85 -16 y_1_2 5 -16 x_1_2 6 -16 x_1_2 14 -16 y_1_2 15 -16 hz_1_2 16 -16 y_1_2 17 -16 x_1_2 24 -16 hz_1_2 25 -16 x_1_2 26 -16 hz_1_2 27 -16 y_1_2 28 -16 y_1_2 32 -16 x_1_2 33 -16 x_1_2 34 -16 y_1_2 35 -16 x_1_2 36 -16 x_1_2 37 -16 x_1_2 38 -16 x_1_2 39 -16 x_1_2 41 -16 hz_1_2 42 -16 x_1_2 43 -16 x_1_2 44 -16 hz_1_2 45 -16 hz_1_2 46 -16 y_1_2 47 -16 hz_1_2 48 -16 y_1_2 49 -16 hz_1_2 50 -16 y_1_2 51 -16 y_1_2 52 -16 y_1_2 53 -16 x_1_2 54 -16 x_1_2 55 -16 y_1_2 56 -16 hz_1_2 57 -16 hz_1_2 58 -16 y_1_2 61 -16 y_1_2 62 -16 x_1_2 63 -16 hz_1_2 64 -16 y_1_2 65 -16 x_1_2 66 -16 hz_1_2 67 -16 y_1_2 72 -16 hz_1_2 73 -16 y_1_2 74 -16 y_1_2 75 -16 hz_1_2 76 -16 hz_1_2 83 -16 x_1_2 84 -16 x_1_2 85 -16 hz_1_2 94 -17 rz(0.7988745176237023) 5 -17 rz(-0.43623002042232994) 6 -17 rz(0.6854509025876576) 14 -17 rz(-0.6806684237245106) 15 -17 rz(0.895797965119231) 16 -17 rz(-0.8569000264078449) 17 -17 rz(-0.5874420850315563) 25 -17 rz(0.1201593690314567) 26 -17 rz(-0.1662456403979169) 27 -17 rz(-0.07589080072114174) 28 -17 rz(-0.7304236667431359) 32 -17 rz(0.941496530479255) 33 -17 rz(0.20225972132064465) 34 -17 rz(-0.15827755225511886) 35 -17 rz(-0.4344243610529689) 36 -17 rz(0.46268235456179807) 37 -17 rz(-0.8068213968674496) 38 -17 rz(0.509068605677839) 39 -17 rz(-0.48423867254446107) 41 -17 rz(0.48894286676445003) 42 -17 rz(-0.15393657844081263) 43 -17 rz(-0.13166988724458512) 44 -17 rz(0.9167642676321308) 45 -17 rz(0.7780904452638893) 46 -17 rz(0.9446189706702058) 47 -17 rz(-0.9928292466716331) 48 -17 rz(0.5611001142888932) 50 -17 rz(-0.3335178196796271) 51 -17 rz(-0.9320005175083301) 52 -17 rz(0.8530467113957879) 53 -17 rz(-0.43500767720566996) 54 -17 rz(0.41543641896921035) 55 -17 rz(0.7467429096710533) 56 -17 rz(-0.5376024887578965) 57 -17 rz(0.2245283033807833) 61 -17 rz(-0.21843587057454775) 62 -17 rz(0.5287967848416878) 63 -17 rz(-0.5409675760824668) 64 -17 rz(0.6406489204802666) 65 -17 rz(-0.5592940283054504) 66 -17 rz(0.2577402023668132) 72 -17 rz(-0.278250406527795) 73 -17 rz(0.9067738427572684) 74 -17 rz(-0.9706188475674273) 75 -17 rz(-0.619746479193709) 83 -17 rz(0.710629980452301) 84 -18 fsim(0.49365264175466117, 0.15525133396347482) 5 6 -18 fsim(0.47303698530749166, 0.15851903504005288) 14 15 -18 fsim(0.4860239014600936, 0.16383319416244227) 16 17 -18 fsim(0.47760865431703853, 0.1722820082764079) 25 26 -18 fsim(0.509171230744336, 0.16804022614589761) 27 28 -18 fsim(0.488759902041367, 0.1333685928255776) 32 33 -18 fsim(0.4920570546033223, 0.16987541076683108) 34 35 -18 fsim(0.4982034875822141, 0.16859518356435038) 36 37 -18 fsim(0.5169469113973622, 0.15443156883098344) 38 39 -18 fsim(0.5100156470228439, 0.15919887714218442) 41 42 -18 fsim(0.5013161698221332, 0.16668826789830035) 43 44 -18 fsim(0.48505020747377536, 0.15126442409592716) 45 46 -18 fsim(0.4910557144645823, 0.16553543587639166) 47 48 -18 fsim(0.4531292444443958, 0.1672349617084543) 50 51 -18 fsim(0.4811161821494542, 0.14574797118653934) 52 53 -18 fsim(0.4892984073437459, 0.18061915843291854) 54 55 -18 fsim(0.4807798603179813, 0.1432020872458372) 56 57 -18 fsim(0.47699857306165455, 0.2028158162407915) 61 62 -18 fsim(0.47981318946926454, 0.15237439630820673) 63 64 -18 fsim(0.4737599636880325, 0.14788136570201332) 65 66 -18 fsim(0.4902284723641499, 0.1632425516276174) 72 73 -18 fsim(0.5048672988301155, 0.15248440735797275) 74 75 -18 fsim(0.49753578048082747, 0.15466472657491784) 83 84 -19 rz(-0.5842790087648996) 5 -19 rz(0.9469235059662741) 6 -19 rz(-0.7059366355498733) 14 -19 rz(0.7107191144130203) 15 -19 rz(0.9796818974832071) 16 -19 rz(-0.9407839587718211) 17 -19 rz(0.6095061091362723) 25 -19 rz(0.9232111748636281) 26 -19 rz(-0.5926204384664704) 27 -19 rz(0.35048399734741176) 28 -19 rz(0.5284905331935638) 32 -19 rz(-0.3174176694574447) 33 -19 rz(-0.8852923805284783) 34 -19 rz(0.929274549594004) 35 -19 rz(-0.9541773358165268) 36 -19 rz(0.9824353293253562) 37 -19 rz(0.9767539085138666) 38 -19 rz(0.7254933002965229) 39 -19 rz(-0.9381666089148069) 41 -19 rz(0.9428708031347959) 42 -19 rz(-0.8124804279802466) 43 -19 rz(0.5268739622948487) 44 -19 rz(0.8739308607246958) 45 -19 rz(0.8209238521713237) 46 -19 rz(-0.8325530873621259) 47 -19 rz(0.7843428113606987) 48 -19 rz(-0.7358964783815413) 50 -19 rz(0.9634787729908084) 51 -19 rz(0.34679631870769856) 52 -19 rz(-0.42575012482024077) 53 -19 rz(0.41561643926621195) 54 -19 rz(-0.43518769750267156) 55 -19 rz(0.8480619091791521) 56 -19 rz(-0.6389214882659956) 57 -19 rz(-0.4403148238967388) 61 -19 rz(0.4464072567029743) 62 -19 rz(-0.28600269726468336) 63 -19 rz(0.27383190602390434) 64 -19 rz(-0.579852820830554) 65 -19 rz(0.6612077130053702) 66 -19 rz(0.590283505637045) 72 -19 rz(-0.6107937097980273) 73 -19 rz(0.8035865857150007) 74 -19 rz(-0.8674315905251597) 75 -19 rz(-0.7522826877369967) 83 -19 rz(0.8431661889955893) 84 -20 x_1_2 5 -20 y_1_2 6 -20 hz_1_2 14 -20 hz_1_2 15 -20 y_1_2 16 -20 x_1_2 17 -20 y_1_2 24 -20 x_1_2 25 -20 y_1_2 26 -20 y_1_2 27 -20 hz_1_2 28 -20 hz_1_2 32 -20 hz_1_2 33 -20 hz_1_2 34 -20 x_1_2 35 -20 y_1_2 36 -20 y_1_2 37 -20 hz_1_2 38 -20 y_1_2 39 -20 y_1_2 41 -20 y_1_2 42 -20 y_1_2 43 -20 y_1_2 44 -20 y_1_2 45 -20 x_1_2 46 -20 hz_1_2 47 -20 y_1_2 48 -20 x_1_2 49 -20 y_1_2 50 -20 hz_1_2 51 -20 x_1_2 52 -20 hz_1_2 53 -20 y_1_2 54 -20 y_1_2 55 -20 hz_1_2 56 -20 x_1_2 57 -20 y_1_2 58 -20 hz_1_2 61 -20 hz_1_2 62 -20 hz_1_2 63 -20 x_1_2 64 -20 hz_1_2 65 -20 hz_1_2 66 -20 x_1_2 67 -20 hz_1_2 72 -20 x_1_2 73 -20 x_1_2 74 -20 x_1_2 75 -20 x_1_2 76 -20 x_1_2 83 -20 y_1_2 84 -20 y_1_2 85 -20 y_1_2 94 -21 rz(0.6438506938399094) 15 -21 rz(-0.618247357459362) 16 -21 rz(0.07047511031002901) 24 -21 rz(-0.5695917880942174) 25 -21 rz(-0.4070669520927599) 26 -21 rz(0.6135367823014299) 27 -21 rz(0.5682863320894853) 33 -21 rz(-0.5146037696673801) 34 -21 rz(0.28907856373285357) 35 -21 rz(-0.30079830120996326) 36 -21 rz(0.6756017204512074) 37 -21 rz(-0.6802146990123358) 38 -21 rz(-0.6911586302494148) 42 -21 rz(0.44593305428487634) 43 -21 rz(0.39452014463587903) 44 -21 rz(-0.44356173380062575) 45 -21 rz(-0.4290645336496083) 46 -21 rz(0.38140526082895393) 47 -21 rz(-0.5160773071541702) 48 -21 rz(0.564228506977561) 49 -21 rz(0.6204494752371521) 51 -21 rz(-0.6107052840876123) 52 -21 rz(-0.9502650669060344) 53 -21 rz(0.9631415796799797) 54 -21 rz(0.8895028972252971) 55 -21 rz(-0.8048173327685305) 56 -21 rz(0.6805784024500074) 57 -21 rz(-0.5757053812553574) 58 -21 rz(-0.8799587731906682) 62 -21 rz(0.7472120667599012) 63 -21 rz(-0.5825100826428156) 64 -21 rz(0.5698791452001684) 65 -21 rz(0.9028503203508277) 66 -21 rz(-0.7225014165588084) 67 -21 rz(0.3857801721324489) 73 -21 rz(-0.3785794033676002) 74 -21 rz(-0.10329161215178768) 75 -21 rz(-0.3229596367298828) 76 -21 rz(0.3035635765288527) 84 -21 rz(-0.4404707307377103) 85 -22 fsim(0.4721504021115573, 0.15695816747993444) 15 16 -22 fsim(0.4825634211282305, 0.15867828327762148) 24 25 -22 fsim(0.48824316009376834, 0.15951491059929712) 26 27 -22 fsim(0.47115582838766157, 0.15190773431751792) 33 34 -22 fsim(0.48231141888350276, 0.1585063414575064) 35 36 -22 fsim(0.4865342593572244, 0.16427486274391248) 37 38 -22 fsim(0.5050345537310194, 0.15144542443009287) 42 43 -22 fsim(0.48807396570956973, 0.14318657147960762) 44 45 -22 fsim(0.48249755474463474, 0.14845262365278886) 46 47 -22 fsim(0.4980006261021947, 0.15119064727561662) 48 49 -22 fsim(0.4984695188566927, 0.18004531009583208) 51 52 -22 fsim(0.4842091684198735, 0.16094100162415842) 53 54 -22 fsim(0.48011792378547014, 0.1580141230640478) 55 56 -22 fsim(0.48023421368651875, 0.14013840287026855) 57 58 -22 fsim(0.49842022326892416, 0.15044767636993245) 62 63 -22 fsim(0.484447874980701, 0.16984474255103443) 64 65 -22 fsim(0.49342767762518064, 0.14018741526981413) 66 67 -22 fsim(0.47190475607081295, 0.21827595026961338) 73 74 -22 fsim(0.47561747564029094, 0.14608866678530144) 75 76 -22 fsim(0.49298021632342415, 0.14221762546243955) 84 85 -23 rz(-0.7497478457292671) 15 -23 rz(0.7753511821098146) 16 -23 rz(-0.8534761319293775) 24 -23 rz(0.35435945414518916) 25 -23 rz(0.16560283184462107) 26 -23 rz(0.04086699836404887) 27 -23 rz(-0.4873331864284298) 33 -23 rz(0.541015748850535) 34 -23 rz(-0.0047018606296570335) 35 -23 rz(-0.007017876847452668) 36 -23 rz(-0.6772604632711591) 37 -23 rz(0.6726474847100307) 38 -23 rz(-0.6512560743127291) 42 -23 rz(0.40603049834819016) 43 -23 rz(-0.9959049867836792) 44 -23 rz(0.9468633976189325) 45 -23 rz(0.8419449138336009) 46 -23 rz(-0.8896041866542553) 47 -23 rz(0.16817847920112608) 48 -23 rz(-0.12002727937773534) 49 -23 rz(-0.5943976432401735) 51 -23 rz(0.6041418343897134) 52 -23 rz(0.6209849644442211) 53 -23 rz(-0.6081084516702759) 54 -23 rz(-0.8260976462004742) 55 -23 rz(0.9107832106572408) 56 -23 rz(-0.6601340432472717) 57 -23 rz(0.7650070644419217) 58 -23 rz(0.49112048117881246) 62 -23 rz(-0.6238671876095794) 63 -23 rz(-0.9004391967350515) 64 -23 rz(0.8878082592924043) 65 -23 rz(0.6257934167965067) 66 -23 rz(-0.4454445130044874) 67 -23 rz(-0.12235976665487905) 73 -23 rz(0.12956053541972776) 74 -23 rz(0.30226364529658795) 75 -23 rz(-0.7285148941782584) 76 -23 rz(-0.31404897096620005) 84 -23 rz(0.17714181675734245) 85 -24 hz_1_2 5 -24 x_1_2 6 -24 y_1_2 14 -24 y_1_2 15 -24 x_1_2 16 -24 hz_1_2 17 -24 x_1_2 24 -24 hz_1_2 25 -24 x_1_2 26 -24 hz_1_2 27 -24 y_1_2 28 -24 y_1_2 32 -24 x_1_2 33 -24 x_1_2 34 -24 hz_1_2 35 -24 x_1_2 36 -24 hz_1_2 37 -24 x_1_2 38 -24 hz_1_2 39 -24 x_1_2 41 -24 x_1_2 42 -24 x_1_2 43 -24 hz_1_2 44 -24 x_1_2 45 -24 y_1_2 46 -24 x_1_2 47 -24 hz_1_2 48 -24 hz_1_2 49 -24 x_1_2 50 -24 x_1_2 51 -24 hz_1_2 52 -24 x_1_2 53 -24 x_1_2 54 -24 hz_1_2 55 -24 x_1_2 56 -24 y_1_2 57 -24 x_1_2 58 -24 x_1_2 61 -24 y_1_2 62 -24 y_1_2 63 -24 y_1_2 64 -24 x_1_2 65 -24 x_1_2 66 -24 y_1_2 67 -24 x_1_2 72 -24 hz_1_2 73 -24 hz_1_2 74 -24 hz_1_2 75 -24 y_1_2 76 -24 hz_1_2 83 -24 hz_1_2 84 -24 hz_1_2 85 -24 x_1_2 94 -25 rz(-0.5516614516047799) 6 -25 rz(0.6174795220715865) 16 -25 rz(-0.4327711187160072) 15 -25 rz(-0.05062333421393557) 25 -25 rz(0.3177840441511373) 17 -25 rz(-0.10047261856343086) 27 -25 rz(0.5094803678807461) 24 -25 rz(-0.477422600327394) 34 -25 rz(-0.6408765210346724) 26 -25 rz(0.6213948502194439) 36 -25 rz(-0.7032192054252008) 28 -25 rz(0.754622217740198) 38 -25 rz(-0.9073671101422918) 33 -25 rz(0.7688260728280146) 43 -25 rz(-0.8617637363416806) 35 -25 rz(0.9336663643285862) 45 -25 rz(-0.3929732311767222) 37 -25 rz(0.4097429307239244) 47 -25 rz(0.0552051208550207) 39 -25 rz(-0.04849439530424264) 49 -25 rz(0.9954710267271799) 42 -25 rz(-0.9922667609489023) 52 -25 rz(-0.08109954594056305) 44 -25 rz(0.03439016849657811) 54 -25 rz(0.11890354904913102) 46 -25 rz(0.06799568729138893) 56 -25 rz(-0.6030454946335517) 48 -25 rz(0.5869432193241655) 58 -25 rz(-0.9975512288793414) 51 -25 rz(-0.9798328527655973) 61 -25 rz(0.676440254578787) 53 -25 rz(0.9238318053231387) 63 -25 rz(0.7743905036170879) 55 -25 rz(-0.8501311900075205) 65 -25 rz(-0.6828230291151024) 57 -25 rz(0.7440183043132079) 67 -25 rz(-0.06546313715369771) 62 -25 rz(0.05739220357069274) 72 -25 rz(-0.03844537611129621) 64 -25 rz(0.037517804558631546) 74 -25 rz(0.782361625590525) 66 -25 rz(0.9364903862480225) 76 -25 rz(0.7611409474788069) 73 -25 rz(-0.8031117186780351) 83 -25 rz(-0.38150923394940456) 75 -25 rz(0.37485924771904144) 85 -25 rz(0.03297060514310833) 84 -25 rz(-0.3917017537983911) 94 -26 fsim(0.48248590238931144, 0.17720711726780922) 6 16 -26 fsim(0.4831173807612162, 0.1575031878359891) 15 25 -26 fsim(0.5104652445279683, 0.1518018478533972) 17 27 -26 fsim(0.483109325847836, 0.16101107882693258) 24 34 -26 fsim(0.48552394043342284, 0.14819609246068247) 26 36 -26 fsim(0.5137841338574078, 0.15735440433706077) 28 38 -26 fsim(0.49264217592278786, 0.14098000393237992) 33 43 -26 fsim(0.48501709381128927, 0.14949793435121178) 35 45 -26 fsim(0.48656355637175525, 0.18260338861410977) 37 47 -26 fsim(0.49284428894552623, 0.15792655003519906) 39 49 -26 fsim(0.521298630708583, 0.21928323341492764) 42 52 -26 fsim(0.486998183067378, 0.15361268278864498) 44 54 -26 fsim(0.486390931075892, 0.1626489398497966) 46 56 -26 fsim(0.4813094673968524, 0.15327107428645925) 48 58 -26 fsim(0.47975471412767756, 0.16199668846067358) 51 61 -26 fsim(0.492110274286689, 0.1687807392184565) 53 63 -26 fsim(0.4827686976879951, 0.14378566187650293) 55 65 -26 fsim(0.46465889570960195, 0.13416717007279197) 57 67 -26 fsim(0.48881240027593537, 0.14984846721738163) 62 72 -26 fsim(0.4831873565264152, 0.16620074089526124) 64 74 -26 fsim(0.4764882949770173, 0.13770458644228914) 66 76 -26 fsim(0.48112498558227507, 0.15642764309600338) 73 83 -26 fsim(0.47456208123909566, 0.15553396824213445) 75 85 -26 fsim(0.5144705816268026, 0.1596097876378056) 84 94 -27 rz(0.5641935842445645) 6 -27 rz(-0.4983755137777578) 16 -27 rz(0.24179059583774581) 15 -27 rz(-0.7251850487676863) 25 -27 rz(-0.32084588367729194) 17 -27 rz(0.5381573092649984) 27 -27 rz(0.019062576518183987) 24 -27 rz(0.01299519103516814) 34 -27 rz(0.22619984017981742) 26 -27 rz(-0.2456815109950459) 36 -27 rz(-0.8617595478187416) 28 -27 rz(0.9131625601337389) 38 -27 rz(0.24317615795692585) 33 -27 rz(-0.38171719527120296) 43 -27 rz(-0.9034580610029361) 35 -27 rz(0.9753606889898416) 45 -27 rz(-0.5871899251539519) 37 -27 rz(0.603959624701154) 47 -27 rz(-0.29703548124351364) 39 -27 rz(0.3037462067942906) 49 -27 rz(-0.20718859840113155) 42 -27 rz(0.2103928641794091) 52 -27 rz(0.18030203332281788) 44 -27 rz(-0.2270114107668028) 54 -27 rz(0.04128661851581855) 46 -27 rz(0.1456126178247014) 56 -27 rz(0.8499898074110996) 48 -27 rz(-0.8660920827204859) 58 -27 rz(0.26992216901673105) 51 -27 rz(-0.24730625066166856) 61 -27 rz(0.4845073865505883) 53 -27 rz(-0.8842353266486614) 63 -27 rz(-0.8911052487304801) 55 -27 rz(0.8153645623400477) 65 -27 rz(-0.0158265769954911) 57 -27 rz(0.07702185219359665) 67 -27 rz(0.5014707755967253) 62 -27 rz(-0.5095417091797303) 72 -27 rz(0.3068636250628814) 64 -27 rz(-0.30779119661554605) 74 -27 rz(0.5183942238917469) 66 -27 rz(-0.7995422120531994) 76 -27 rz(0.9961315227572937) 73 -27 rz(0.9618977060434781) 83 -27 rz(0.26285448551587504) 75 -27 rz(-0.26950447174623815) 85 -27 rz(0.6934649565591651) 84 -27 rz(0.947803894785552) 94 -28 x_1_2 5 -28 hz_1_2 6 -28 x_1_2 14 -28 hz_1_2 15 -28 y_1_2 16 -28 x_1_2 17 -28 y_1_2 24 -28 y_1_2 25 -28 hz_1_2 26 -28 y_1_2 27 -28 hz_1_2 28 -28 hz_1_2 32 -28 hz_1_2 33 -28 hz_1_2 34 -28 y_1_2 35 -28 hz_1_2 36 -28 y_1_2 37 -28 y_1_2 38 -28 x_1_2 39 -28 y_1_2 41 -28 y_1_2 42 -28 hz_1_2 43 -28 x_1_2 44 -28 y_1_2 45 -28 x_1_2 46 -28 y_1_2 47 -28 y_1_2 48 -28 x_1_2 49 -28 hz_1_2 50 -28 y_1_2 51 -28 y_1_2 52 -28 y_1_2 53 -28 hz_1_2 54 -28 x_1_2 55 -28 hz_1_2 56 -28 x_1_2 57 -28 hz_1_2 58 -28 hz_1_2 61 -28 hz_1_2 62 -28 x_1_2 63 -28 x_1_2 64 -28 hz_1_2 65 -28 y_1_2 66 -28 x_1_2 67 -28 y_1_2 72 -28 y_1_2 73 -28 y_1_2 74 -28 y_1_2 75 -28 x_1_2 76 -28 x_1_2 83 -28 x_1_2 84 -28 x_1_2 85 -28 y_1_2 94 -29 rz(0.08621640979886422) 5 -29 rz(0.16334365608168644) 15 -29 rz(0.3973572916277998) 14 -29 rz(-0.396326411747794) 24 -29 rz(0.5427073576530422) 16 -29 rz(-0.5424147092534605) 26 -29 rz(0.09003675765506945) 25 -29 rz(0.34202849142196157) 35 -29 rz(0.8983264693104055) 27 -29 rz(-0.7067732133063435) 37 -29 rz(0.705156509293045) 32 -29 rz(-0.6244998637478164) 42 -29 rz(0.15790347048791883) 34 -29 rz(-0.18947787438082972) 44 -29 rz(0.8024559428448615) 36 -29 rz(-0.7589602352735803) 46 -29 rz(0.8696926792305255) 38 -29 rz(-0.8516181998325968) 48 -29 rz(0.8756084230940031) 41 -29 rz(-0.8808339440806644) 51 -29 rz(0.24320434330005752) 43 -29 rz(-0.7125304945256264) 53 -29 rz(-0.9897343640361297) 45 -29 rz(-0.9074614067078688) 55 -29 rz(-0.9497630264840345) 47 -29 rz(0.9177909707695425) 57 -29 rz(-0.12861597882367556) 52 -29 rz(0.1299917767076041) 62 -29 rz(0.13388452450572944) 54 -29 rz(-0.12593963181169407) 64 -29 rz(-0.9621689450218167) 56 -29 rz(-0.8955807139987333) 66 -29 rz(-0.7528365530460183) 63 -29 rz(0.7258226701533779) 73 -29 rz(-0.7596124788130051) 65 -29 rz(0.7153118414371823) 75 -29 rz(-0.6814566172688604) 74 -29 rz(0.7119632677360634) 84 -30 fsim(0.4836037489865321, 0.15720448517258814) 5 15 -30 fsim(0.4813027746287272, 0.16589400016587655) 14 24 -30 fsim(0.5141011050173628, 0.23139995996898027) 16 26 -30 fsim(0.4860333525890109, 0.1603093406600409) 25 35 -30 fsim(0.48318175023922383, 0.1564279262034107) 27 37 -30 fsim(0.4893783671604143, 0.1436061569230382) 32 42 -30 fsim(0.4885622789540625, 0.14820473190374475) 34 44 -30 fsim(0.48365869422848307, 0.16133729898079696) 36 46 -30 fsim(0.5035633150535174, 0.17812225242391694) 38 48 -30 fsim(0.47971143268846445, 0.14388623656266197) 41 51 -30 fsim(0.48615849941720374, 0.1566149748128868) 43 53 -30 fsim(0.4819082002062166, 0.14615816911657503) 45 55 -30 fsim(0.4909994945412715, 0.16098322131650447) 47 57 -30 fsim(0.4912337946314961, 0.18012457108936253) 52 62 -30 fsim(0.46508517467774446, 0.17301578991022867) 54 64 -30 fsim(0.4625029911035914, 0.13951781372243774) 56 66 -30 fsim(0.5169231411118692, 0.15867863143208272) 63 73 -30 fsim(0.4737902812504438, 0.15803377395648677) 65 75 -30 fsim(0.47857129167400153, 0.15930690639357745) 74 84 -31 rz(0.08867615219877248) 5 -31 rz(0.16088391368177818) 15 -31 rz(-0.5836051427906996) 14 -31 rz(0.5846360226707056) 24 -31 rz(0.6636695068149479) 16 -31 rz(-0.6633768584153672) 26 -31 rz(0.7278338235086499) 25 -31 rz(-0.2957685744316189) 35 -31 rz(-0.7470909692987385) 27 -31 rz(0.9386442253028005) 37 -31 rz(-0.534116953419378) 32 -31 rz(0.6147735989646066) 42 -31 rz(0.057788292865813835) 34 -31 rz(-0.08936269675872473) 44 -31 rz(0.9720523226063322) 36 -31 rz(-0.9285566150350509) 46 -31 rz(0.24050825583717475) 38 -31 rz(-0.22243377643924597) 48 -31 rz(-0.968723820269696) 41 -31 rz(0.9634982992830347) 51 -31 rz(-0.5154066862373383) 43 -31 rz(0.04608053501176949) 53 -31 rz(-0.24375561287182076) 45 -31 rz(0.3465598421278222) 55 -31 rz(-0.6402034399153681) 47 -31 rz(0.608231384200875) 57 -31 rz(-0.4706912009416499) 52 -31 rz(0.4720669988255795) 62 -31 rz(-0.1947423470531135) 54 -31 rz(0.2026872397471489) 64 -31 rz(0.518418784954393) 56 -31 rz(-0.37616844397494287) 66 -31 rz(0.13212668683985648) 63 -31 rz(-0.15914056973249802) 73 -31 rz(0.698842568523934) 65 -31 rz(-0.7431432058997568) 75 -31 rz(0.3162523839911777) 74 -31 rz(-0.28574573352397464) 84 -32 hz_1_2 5 -32 x_1_2 6 -32 hz_1_2 14 -32 y_1_2 15 -32 x_1_2 16 -32 hz_1_2 17 -32 hz_1_2 24 -32 hz_1_2 25 -32 x_1_2 26 -32 x_1_2 27 -32 x_1_2 28 -32 y_1_2 32 -32 x_1_2 33 -32 x_1_2 34 -32 x_1_2 35 -32 y_1_2 36 -32 x_1_2 37 -32 hz_1_2 38 -32 y_1_2 39 -32 x_1_2 41 -32 x_1_2 42 -32 y_1_2 43 -32 hz_1_2 44 -32 hz_1_2 45 -32 hz_1_2 46 -32 x_1_2 47 -32 x_1_2 48 -32 hz_1_2 49 -32 x_1_2 50 -32 hz_1_2 51 -32 x_1_2 52 -32 hz_1_2 53 -32 x_1_2 54 -32 hz_1_2 55 -32 y_1_2 56 -32 y_1_2 57 -32 x_1_2 58 -32 x_1_2 61 -32 y_1_2 62 -32 hz_1_2 63 -32 y_1_2 64 -32 y_1_2 65 -32 x_1_2 66 -32 y_1_2 67 -32 hz_1_2 72 -32 x_1_2 73 -32 hz_1_2 74 -32 x_1_2 75 -32 hz_1_2 76 -32 hz_1_2 83 -32 y_1_2 84 -32 hz_1_2 85 -32 hz_1_2 94 -33 rz(-0.9936614516048078) 6 -33 rz(-0.9405204779283867) 16 -33 rz(0.37922888128394683) 15 -33 rz(-0.862623334213893) 25 -33 rz(-0.792215955848905) 17 -33 rz(-0.9904726185633891) 27 -33 rz(-0.6765196321192446) 24 -33 rz(0.7085773996725973) 34 -33 rz(-0.4948765210346792) 26 -33 rz(0.4753948502194507) 36 -33 rz(-0.40721920542516743) 28 -33 rz(0.45862221774016465) 38 -33 rz(-0.019367110142323812) 33 -33 rz(-0.11917392717195331) 43 -33 rz(-0.04776373634167188) 35 -33 rz(0.11966636432857744) 45 -33 rz(-0.6929732311767329) 37 -33 rz(0.7097429307239397) 47 -33 rz(-0.9847948791450413) 39 -33 rz(0.9915056046958216) 49 -33 rz(0.40547102672717017) 42 -33 rz(-0.40226676094889036) 52 -33 rz(0.14290045405943544) 44 -33 rz(-0.1896098315034204) 54 -33 rz(0.41690354904915433) 46 -33 rz(-0.23000431270863436) 56 -33 rz(-0.5270454946335372) 48 -33 rz(0.510943219324151) 58 -33 rz(0.48044877112063566) 51 -33 rz(-0.45783285276557767) 61 -33 rz(0.08044025457880374) 53 -33 rz(-0.48016819467688143) 63 -33 rz(0.9203905036170812) 55 -33 rz(-0.9961311900075136) 65 -33 rz(0.12917697088491722) 57 -33 rz(-0.06798169568681166) 67 -33 rz(-0.5814631371537482) 62 -33 rz(0.5733922035707443) 72 -33 rz(-0.6284453761113048) 64 -33 rz(0.6275178045586413) 74 -33 rz(0.7803616255905353) 66 -33 rz(0.9384903862480122) 76 -33 rz(-0.5008590525212017) 73 -33 rz(0.45888828132197124) 83 -33 rz(0.5784907660505968) 75 -33 rz(-0.5851407522809633) 85 -33 rz(0.10497060514307784) 84 -33 rz(-0.46370175379836065) 94 -34 fsim(0.48248590238931144, 0.17720711726780922) 6 16 -34 fsim(0.4831173807612162, 0.1575031878359891) 15 25 -34 fsim(0.5104652445279683, 0.1518018478533972) 17 27 -34 fsim(0.483109325847836, 0.16101107882693258) 24 34 -34 fsim(0.48552394043342284, 0.14819609246068247) 26 36 -34 fsim(0.5137841338574078, 0.15735440433706077) 28 38 -34 fsim(0.49264217592278786, 0.14098000393237992) 33 43 -34 fsim(0.48501709381128927, 0.14949793435121178) 35 45 -34 fsim(0.48656355637175525, 0.18260338861410977) 37 47 -34 fsim(0.49284428894552623, 0.15792655003519906) 39 49 -34 fsim(0.521298630708583, 0.21928323341492764) 42 52 -34 fsim(0.486998183067378, 0.15361268278864498) 44 54 -34 fsim(0.486390931075892, 0.1626489398497966) 46 56 -34 fsim(0.4813094673968524, 0.15327107428645925) 48 58 -34 fsim(0.47975471412767756, 0.16199668846067358) 51 61 -34 fsim(0.492110274286689, 0.1687807392184565) 53 63 -34 fsim(0.4827686976879951, 0.14378566187650293) 55 65 -34 fsim(0.46465889570960195, 0.13416717007279197) 57 67 -34 fsim(0.48881240027593537, 0.14984846721738163) 62 72 -34 fsim(0.4831873565264152, 0.16620074089526124) 64 74 -34 fsim(0.4764882949770173, 0.13770458644228914) 66 76 -34 fsim(0.48112498558227507, 0.15642764309600338) 73 83 -34 fsim(0.47456208123909566, 0.15553396824213445) 75 85 -34 fsim(0.5144705816268026, 0.1596097876378056) 84 94 -35 rz(-0.9938064157554087) 6 -35 rz(-0.9403755137777857) 16 -35 rz(-0.5702094041622093) 15 -35 rz(0.08681495123226317) 25 -35 rz(0.789154116322751) 17 -35 rz(-0.571842690735044) 27 -35 rz(-0.7949374234818247) 24 -35 rz(0.8269951910351775) 34 -35 rz(0.08019984017982425) 26 -35 rz(-0.09968151099505272) 36 -35 rz(0.8422404521812253) 28 -35 rz(-0.7908374398662281) 38 -35 rz(-0.6448238420430421) 33 -35 rz(0.506282804728765) 43 -35 rz(0.28254193899705515) 35 -35 rz(-0.21063931101014957) 45 -35 rz(-0.28718992515393654) 37 -35 rz(0.30395962470114324) 47 -35 rz(0.7429645187565517) 39 -35 rz(-0.7362537932057713) 49 -35 rz(0.3828114015988804) 42 -35 rz(-0.3796071358206017) 52 -35 rz(-0.043697966677180636) 44 -35 rz(-0.0030114107668043153) 54 -35 rz(-0.25671338148420475) 46 -35 rz(0.4436126178247247) 56 -35 rz(0.7739898074110851) 48 -35 rz(-0.7900920827204714) 58 -35 rz(0.7919221690167495) 51 -35 rz(-0.7693062506616914) 61 -35 rz(-0.919492613449433) 53 -35 rz(0.5197646733513552) 63 -35 rz(0.9628947512695266) 55 -35 rz(0.9613645623400409) 65 -35 rz(-0.8278265769955084) 57 -35 rz(0.889021852193614) 67 -35 rz(-0.9825292244032231) 62 -35 rz(0.9744582908202193) 72 -35 rz(0.8968636250628911) 64 -35 rz(-0.8977911966155546) 74 -35 rz(0.5203942238917367) 66 -35 rz(-0.801542212053188) 76 -35 rz(0.2581315227573) 73 -35 rz(-0.30010229395653043) 83 -35 rz(-0.6971455144841298) 75 -35 rz(0.6904955282537633) 85 -35 rz(0.6214649565591956) 84 -35 rz(-0.9801961052144784) 94 -36 x_1_2 5 -36 y_1_2 6 -36 x_1_2 14 -36 x_1_2 15 -36 y_1_2 16 -36 y_1_2 17 -36 x_1_2 24 -36 x_1_2 25 -36 y_1_2 26 -36 hz_1_2 27 -36 y_1_2 28 -36 hz_1_2 32 -36 y_1_2 33 -36 y_1_2 34 -36 y_1_2 35 -36 x_1_2 36 -36 hz_1_2 37 -36 x_1_2 38 -36 hz_1_2 39 -36 hz_1_2 41 -36 hz_1_2 42 -36 x_1_2 43 -36 y_1_2 44 -36 y_1_2 45 -36 x_1_2 46 -36 y_1_2 47 -36 y_1_2 48 -36 x_1_2 49 -36 y_1_2 50 -36 y_1_2 51 -36 hz_1_2 52 -36 x_1_2 53 -36 hz_1_2 54 -36 y_1_2 55 -36 hz_1_2 56 -36 x_1_2 57 -36 y_1_2 58 -36 hz_1_2 61 -36 hz_1_2 62 -36 x_1_2 63 -36 hz_1_2 64 -36 x_1_2 65 -36 hz_1_2 66 -36 hz_1_2 67 -36 x_1_2 72 -36 hz_1_2 73 -36 x_1_2 74 -36 y_1_2 75 -36 y_1_2 76 -36 y_1_2 83 -36 hz_1_2 84 -36 y_1_2 85 -36 y_1_2 94 -37 rz(-0.5757835902011161) 5 -37 rz(0.8253436560816667) 15 -37 rz(-0.5646427083721929) 14 -37 rz(0.5656735882521988) 24 -37 rz(0.10070735765308102) 16 -37 rz(-0.10041470925350265) 26 -37 rz(-0.1299632423448818) 25 -37 rz(0.5620284914219106) 35 -37 rz(0.15632646931043123) 27 -37 rz(0.03522678669363078) 37 -37 rz(-0.6288434907069298) 32 -37 rz(0.7095001362521582) 42 -37 rz(-0.732096529512105) 34 -37 rz(0.7005221256191941) 44 -37 rz(0.13445594284484547) 36 -37 rz(-0.09096023527356352) 46 -37 rz(0.5716926792305023) 38 -37 rz(-0.5536181998325734) 48 -37 rz(0.9516084230940176) 41 -37 rz(-0.9568339440806789) 51 -37 rz(-0.27279565669992845) 43 -37 rz(-0.1965304945256404) 53 -37 rz(-0.3937343640361464) 45 -37 rz(0.4965385932921524) 55 -37 rz(0.2382369735159425) 47 -37 rz(-0.2702090292304356) 57 -37 rz(0.905384021176354) 52 -37 rz(-0.9040082232924209) 62 -37 rz(0.7978845245057673) 54 -37 rz(-0.7899396318117285) 64 -37 rz(-0.964168945021872) 56 -37 rz(-0.893580713998678) 66 -37 rz(0.435163446953961) 63 -37 rz(-0.46217732984660476) 73 -37 rz(0.4283875211869742) 65 -37 rz(-0.4726881585628004) 75 -37 rz(0.7965433827311167) 74 -37 rz(-0.7660367322639136) 84 -38 fsim(0.4836037489865321, 0.15720448517258814) 5 15 -38 fsim(0.4813027746287272, 0.16589400016587655) 14 24 -38 fsim(0.5141011050173628, 0.23139995996898027) 16 26 -38 fsim(0.4860333525890109, 0.1603093406600409) 25 35 -38 fsim(0.48318175023922383, 0.1564279262034107) 27 37 -38 fsim(0.4893783671604143, 0.1436061569230382) 32 42 -38 fsim(0.4885622789540625, 0.14820473190374475) 34 44 -38 fsim(0.48365869422848307, 0.16133729898079696) 36 46 -38 fsim(0.5035633150535174, 0.17812225242391694) 38 48 -38 fsim(0.47971143268846445, 0.14388623656266197) 41 51 -38 fsim(0.48615849941720374, 0.1566149748128868) 43 53 -38 fsim(0.4819082002062166, 0.14615816911657503) 45 55 -38 fsim(0.4909994945412715, 0.16098322131650447) 47 57 -38 fsim(0.4912337946314961, 0.18012457108936253) 52 62 -38 fsim(0.46508517467774446, 0.17301578991022867) 54 64 -38 fsim(0.4625029911035914, 0.13951781372243774) 56 66 -38 fsim(0.5169231411118692, 0.15867863143208272) 63 73 -38 fsim(0.4737902812504438, 0.15803377395648677) 65 75 -38 fsim(0.47857129167400153, 0.15930690639357745) 74 84 -39 rz(0.7506761521987528) 5 -39 rz(-0.5011160863182021) 15 -39 rz(0.37839485720929306) 14 -39 rz(-0.3773639773292872) 24 -39 rz(-0.8943304931850955) 16 -39 rz(0.894623141584675) 26 -39 rz(0.9478338235086012) 25 -39 rz(-0.5157685744315735) 35 -39 rz(-0.005090969298765407) 27 -39 rz(0.19664422530282744) 37 -39 rz(0.7998830465805966) 32 -39 rz(-0.7192264010353682) 42 -39 rz(0.9477882928658377) 34 -39 rz(-0.9793626967587485) 44 -39 rz(-0.359947677393651) 36 -39 rz(0.403443384964933) 46 -39 rz(0.5385082558371981) 38 -39 rz(-0.5204337764392692) 48 -39 rz(0.9552761797302897) 41 -39 rz(-0.9605017007169508) 51 -39 rz(0.0005933137626453817) 43 -39 rz(-0.46991946498821424) 53 -39 rz(-0.8397556128717996) 45 -39 rz(0.9425598421278055) 55 -39 rz(0.17179656008465377) 47 -39 rz(-0.20376861579914693) 57 -39 rz(0.495308799058324) 52 -39 rz(-0.49393300117439093) 62 -39 rz(-0.858742347053148) 54 -39 rz(0.8666872397471868) 64 -39 rz(0.5204187849544483) 56 -39 rz(-0.37816844397499816) 66 -39 rz(0.9441266868398739) 63 -39 rz(-0.9711405697325176) 73 -39 rz(-0.4891574314760486) 65 -39 rz(0.44485679410022244) 75 -39 rz(0.8382523839912006) 74 -39 rz(-0.8077457335239976) 84 -40 hz_1_2 5 -40 x_1_2 6 -40 hz_1_2 14 -40 hz_1_2 15 -40 x_1_2 16 -40 x_1_2 17 -40 hz_1_2 24 -40 hz_1_2 25 -40 x_1_2 26 -40 y_1_2 27 -40 x_1_2 28 -40 x_1_2 32 -40 hz_1_2 33 -40 x_1_2 34 -40 x_1_2 35 -40 hz_1_2 36 -40 x_1_2 37 -40 hz_1_2 38 -40 x_1_2 39 -40 x_1_2 41 -40 x_1_2 42 -40 hz_1_2 43 -40 x_1_2 44 -40 x_1_2 45 -40 hz_1_2 46 -40 hz_1_2 47 -40 x_1_2 48 -40 hz_1_2 49 -40 x_1_2 50 -40 x_1_2 51 -40 y_1_2 52 -40 y_1_2 53 -40 y_1_2 54 -40 x_1_2 55 -40 x_1_2 56 -40 y_1_2 57 -40 x_1_2 58 -40 y_1_2 61 -40 y_1_2 62 -40 hz_1_2 63 -40 y_1_2 64 -40 y_1_2 65 -40 x_1_2 66 -40 y_1_2 67 -40 hz_1_2 72 -40 y_1_2 73 -40 hz_1_2 74 -40 x_1_2 75 -40 hz_1_2 76 -40 x_1_2 83 -40 x_1_2 84 -40 hz_1_2 85 -40 x_1_2 94 diff --git a/docs/src/index.md b/docs/src/index.md index a34d9ee4..3d7960ed 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -28,21 +28,4 @@ A video of its presentation at JuliaCon 2023 can be seen here: - Optimized Tensor Network contraction, powered by [`EinExprs`](https://github.com/bsc-quantic/EinExprs.jl) - Tensor Network slicing/cuttings - Automatic Differentiation of TN contraction, powered by [`EinExprs`](https://github.com/bsc-quantic/EinExprs.jl) and [`ChainRules`](https://github.com/JuliaDiff/ChainRulesCore.jl) -- Quantum Tensor Networks - - Matrix Product States (MPS) - - Matrix Product Operators (MPO) - - Projected Entangled Pair States (PEPS) - 3D visualization of large networks, powered by [`Makie`](https://github.com/MakieOrg/Makie.jl) -- Translation from quantum circuits, powered by [`Quac`](https://github.com/bsc-quantic/Quac.jl) - -### Roadmap - -The following feature are not yet implemented but are work in progress or are thought to be implemented in the near-mid future: - -- Distributed contraction -- Quantum Tensor Networks - - Tree Tensor Networks (TTN) - - Multiscale Entanglement Renormalization Ansatz (MERA) -- Numerical Tensor Network algorithms - - Tensor Renormalization Group (TRG) - - Density Matrix Renormalization Group (DMRG) diff --git a/docs/src/quantum/index.md b/docs/src/quantum/index.md deleted file mode 100644 index e8924934..00000000 --- a/docs/src/quantum/index.md +++ /dev/null @@ -1,34 +0,0 @@ -# Introduction - -In `Tenet`, we define a [`QuantumTensorNetwork`](@ref) as a [`TensorNetwork`](@ref) with a notion of sites and directionality. - -```@docs -QuantumTensorNetwork -plug -sites -``` - -## Adjoint - -```@docs -adjoint -``` - -## Norm - -```@docs -LinearAlgebra.norm(::Tenet.AbstractQuantumTensorNetwork, ::Real) -LinearAlgebra.normalize!(::Tenet.AbstractQuantumTensorNetwork, ::Real) -``` - -## Trace - -```@docs -LinearAlgebra.tr(::Tenet.AbstractQuantumTensorNetwork) -``` - -## Fidelity - -```@docs -fidelity -``` diff --git a/docs/src/quantum/mps.md b/docs/src/quantum/mps.md deleted file mode 100644 index 37d32cfd..00000000 --- a/docs/src/quantum/mps.md +++ /dev/null @@ -1,58 +0,0 @@ -# Matrix Product States (MPS) - -Matrix Product States (MPS) are a Quantum Tensor Network ansatz whose tensors are laid out in a 1D chain. -Due to this, these networks are also known as _Tensor Trains_ in other mathematical fields. -Depending on the boundary conditions, the chains can be open or closed (i.e. periodic boundary conditions). - -```@setup viz -using Makie -Makie.inline!(true) -set_theme!(resolution=(800,200)) - -using CairoMakie - -using Tenet -using NetworkLayout -``` - -```@example viz -fig = Figure() # hide - -tn_open = rand(MatrixProduct{State,Open}, n=10, χ=4) # hide -tn_periodic = rand(MatrixProduct{State,Periodic}, n=10, χ=4) # hide - -plot!(fig[1,1], tn_open, layout=Spring(iterations=1000, C=0.5, seed=100)) # hide -plot!(fig[1,2], tn_periodic, layout=Spring(iterations=1000, C=0.5, seed=100)) # hide - -Label(fig[1,1, Bottom()], "Open") # hide -Label(fig[1,2, Bottom()], "Periodic") # hide - -fig # hide -``` - -## Matrix Product Operators (MPO) - -Matrix Product Operators (MPO) are the operator version of [Matrix Product State (MPS)](#matrix-product-states-mps). -The major difference between them is that MPOs have 2 indices per site (1 input and 1 output) while MPSs only have 1 index per site (i.e. an output). - -```@example viz -fig = Figure() # hide - -tn_open = rand(MatrixProduct{Operator,Open}, n=10, χ=4) # hide -tn_periodic = rand(MatrixProduct{Operator,Periodic}, n=10, χ=4) # hide - -plot!(fig[1,1], tn_open, layout=Spring(iterations=1000, C=0.5, seed=100)) # hide -plot!(fig[1,2], tn_periodic, layout=Spring(iterations=1000, C=0.5, seed=100)) # hide - -Label(fig[1,1, Bottom()], "Open") # hide -Label(fig[1,2, Bottom()], "Periodic") # hide - -fig # hide -``` - -In `Tenet`, the generic `MatrixProduct` ansatz implements this topology. Type variables are used to address their functionality (`State` or `Operator`) and their boundary conditions (`Open` or `Periodic`). - -```@docs -MatrixProduct -MatrixProduct(::Any) -``` diff --git a/docs/src/quantum/peps.md b/docs/src/quantum/peps.md deleted file mode 100644 index 11a792ef..00000000 --- a/docs/src/quantum/peps.md +++ /dev/null @@ -1,52 +0,0 @@ -# Projected Entangled Pair States (PEPS) - -Projected Entangled Pair States (PEPS) are a Quantum Tensor Network ansatz whose tensors are laid out in a 2D lattice. Depending on the boundary conditions, the chains can be open or closed (i.e. periodic boundary conditions). - -```@setup viz -using Makie -Makie.inline!(true) -set_theme!(resolution=(800,400)) - -using CairoMakie -CairoMakie.activate!(type = "svg") - -using Tenet -using NetworkLayout -``` - -```@example viz -fig = Figure() # hide - -tn_open = rand(PEPS{Open}, rows=10, cols=10, χ=4) # hide -tn_periodic = rand(PEPS{Periodic}, rows=10, cols=10, χ=4) # hide - -plot!(fig[1,1], tn_open, layout=Stress(seed=1)) # hide -plot!(fig[1,2], tn_periodic, layout=Stress(seed=10,dim=2,iterations=100000)) # hide - -Label(fig[1,1, Bottom()], "Open") # hide -Label(fig[1,2, Bottom()], "Periodic") # hide - -fig # hide -``` - -## Projected Entangled Pair Operators (PEPO) - -```@example viz -fig = Figure() # hide - -tn_open = rand(PEPO{Open}, rows=10, cols=10, χ=4) # hide -tn_periodic = rand(PEPO{Periodic}, rows=10, cols=10, χ=4) # hide - -plot!(fig[1,1], tn_open, layout=Stress(seed=1)) # hide -plot!(fig[1,2], tn_periodic, layout=Stress(seed=10,dim=2,iterations=100000)) # hide - -Label(fig[1,1, Bottom()], "Open") # hide -Label(fig[1,2, Bottom()], "Periodic") # hide - -fig # hide -``` - -```@docs -ProjectedEntangledPair -ProjectedEntangledPair(::Any) -``` diff --git a/docs/src/transformations.md b/docs/src/transformations.md index ac482326..85b3eede 100644 --- a/docs/src/transformations.md +++ b/docs/src/transformations.md @@ -283,35 +283,3 @@ plot!(fig[1, 2], reduced, layout=Spring(iterations=10000, C=13, seed=151); node_ fig #hide ``` - -## Example: RQC simplification - -Local transformations can dramatically reduce the complexity of tensor networks. Take as an example the Random Quantum Circuit circuit on the Sycamore chip from Google's quantum advantage experiment [arute2019quantum](@cite). - -```@example plot -using QuacIO -set_theme!(resolution=(800,400)) # hide - -sites = [5, 6, 14, 15, 16, 17, 24, 25, 26, 27, 28, 32, 33, 34, 35, 36, 37, 38, 39, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 72, 73, 74, 75, 76, 83, 84, 85, 94] -circuit = QuacIO.parse(joinpath(@__DIR__, "sycamore_53_10_0.qasm"), format=QuacIO.Qflex(), sites=sites) -tn = QuantumTensorNetwork(circuit) - -# Apply transformations to the tensor network -transformed_tn = transform(tn, [Tenet.AntiDiagonalGauging, Tenet.DiagonalReduction, Tenet.ColumnReduction, Tenet.RankSimplification]) - -fig = Figure() # hide -ax1 = Axis(fig[1, 1]) # hide -p1 = plot!(ax1, tn; edge_width=0.75, node_size=8., node_attr=(strokecolor=:black, strokewidth=0.5)) # hide -ax2 = Axis(fig[1, 2]) # hide -p2 = plot!(ax2, transformed_tn; edge_width=0.75, node_size=8., node_attr=(strokecolor=:black, strokewidth=0.5)) # hide -ax1.titlesize, ax2.titlesize = 20, 20 # hide -hidedecorations!(ax1) # hide -hidespines!(ax1) # hide -hidedecorations!(ax2) # hide -hidespines!(ax2) # hide - -Label(fig[1, 1, Bottom()], "Original") # hide -Label(fig[1, 2, Bottom()], "Transformed") # hide - -fig # hide -``` diff --git a/ext/TenetQuacExt.jl b/ext/TenetQuacExt.jl deleted file mode 100644 index 3879fdbf..00000000 --- a/ext/TenetQuacExt.jl +++ /dev/null @@ -1,40 +0,0 @@ -module TenetQuacExt - -using Tenet -using Quac: Circuit, lanes, arraytype, Swap - -function Tenet.QuantumTensorNetwork(circuit::Circuit) - n = lanes(circuit) - wire = [[Tenet.letter(i)] for i in 1:n] - tn = TensorNetwork() - - i = n + 1 - - for gate in circuit - G = arraytype(gate) - array = G(gate) - - if gate isa Swap - (a, b) = lanes(gate) - wire[a], wire[b] = wire[b], wire[a] - continue - end - - inds = map(lanes(gate)) do l - from, to = last(wire[l]), Tenet.letter(i) - i += 1 - push!(wire[l], to) - (from, to) - end |> x -> zip(x...) |> Iterators.flatten |> collect - - tensor = Tensor(array, inds) - push!(tn, tensor) - end - - input = first.(wire) - output = last.(wire) - - return QuantumTensorNetwork(tn, input, output) -end - -end diff --git a/src/Quantum/MP.jl b/src/Quantum/MP.jl deleted file mode 100644 index 18ba008a..00000000 --- a/src/Quantum/MP.jl +++ /dev/null @@ -1,192 +0,0 @@ -using UUIDs: uuid4 -using Base.Iterators: flatten -using Random -using Muscle: gramschmidt! -using EinExprs: inds -using Classes - -""" - MatrixProduct{P<:Plug,B<:Boundary} <: Ansatz - -A generic ansatz representing Matrix Product State (MPS) and Matrix Product Operator (MPO) topology, aka Tensor Train. -Type variable `P` represents the `Plug` type (`State` or `Operator`) and `B` represents the `Boundary` type (`Open` or `Periodic`). -""" -struct MatrixProduct{P<:Plug,B<:Boundary} <: Ansatz end - -function MatrixProduct{P}(arrays; boundary::Type{<:Boundary} = Open, kwargs...) where {P<:Plug} - MatrixProduct{P,boundary}(arrays; kwargs...) -end - -const MPS = MatrixProduct{State} -const MPO = MatrixProduct{Operator} - -plug(::Type{<:MatrixProduct{P}}) where {P} = P() -boundary(::Type{<:MatrixProduct{P,B}}) where {P,B} = B() - -sitealias(::Type{MatrixProduct{P,Open}}, order, n, i) where {P<:Plug} = - if i == 1 - filter(!=(:l), order) - elseif i == n - filter(!=(:r), order) - else - order - end -sitealias(::Type{MatrixProduct{P,Periodic}}, order, n, i) where {P<:Plug} = tuple(order...) - -defaultorder(::Type{<:MatrixProduct{Property}}) = (:l, :r) -defaultorder(::Type{<:MatrixProduct{State}}) = (:l, :r, :o) -defaultorder(::Type{<:MatrixProduct{Operator}}) = (:l, :r, :i, :o) - -""" - MatrixProduct{P,B}(arrays::AbstractArray[]; order = defaultorder(MatrixProduct{P})) - -Construct a [`TensorNetwork`](@ref) with [`MatrixProduct`](@ref) ansatz, from the arrays of the tensors. - -# Keyword Arguments - - - `order` Order of tensor indices on `arrays`. Defaults to `(:l, :r, :o)` if `P` is a `State`, `(:l, :r, :i, :o)` if `Operator`. -""" -function MatrixProduct{P,B}(arrays; order = defaultorder(MatrixProduct{P})) where {P<:Plug,B<:Boundary} - issetequal(order, defaultorder(MatrixProduct{P})) || throw( - ArgumentError( - "`order` must be a permutation of $(join(String.(defaultorder(MatrixProduct{P})), ',', " and "))", - ), - ) - - n = length(arrays) - vinds = Dict(x => Symbol(uuid4()) for x in ringpeek(1:n)) - oinds = map(_ -> Symbol(uuid4()), 1:n) - iinds = map(_ -> Symbol(uuid4()), 1:n) - - input, output = if P <: Property - Symbol[], Symbol[] - elseif P <: State - Symbol[], oinds - elseif P <: Operator - iinds, oinds - else - throw(ArgumentError("Plug $P is not valid")) - end - - tensors::Vector{Tensor} = map(enumerate(arrays)) do (i, array) - dirs = sitealias(MatrixProduct{P,B}, order, n, i) - - inds = map(dirs) do dir - if dir === :l - vinds[(mod1(i - 1, n), i)] - elseif dir === :r - vinds[(i, mod1(i + 1, n))] - elseif dir === :o - oinds[i] - elseif dir === :i - iinds[i] - end - end - - Tensor(array, inds) - end - - return QuantumTensorNetwork(TensorNetwork(tensors), input, output) -end - -# NOTE does not use optimal contraction path, but "parallel-optimal" which costs x2 more -# function contractpath(a::TensorNetwork{<:MatrixProductState}, b::TensorNetwork{<:MatrixProductState}) -# !issetequal(sites(a), sites(b)) && throw(ArgumentError("both tensor networks are expected to have same sites")) - -# b = replace(b, [nameof(outsiteind(b, s)) => nameof(outsiteind(a, s)) for s in sites(a)]...) -# path = nameof.(flatten([physicalinds(a), flatten(zip(virtualinds(a), virtualinds(b)))]) |> collect) -# inputs = flatten([tensors(a), tensors(b)]) .|> inds -# output = Symbol[] -# size_dict = merge(size(a), size(b)) - -# ContractionPath(path, inputs, output, size_dict) -# end - -# TODO let choose the orthogonality center -function Base.rand(rng::Random.AbstractRNG, sampler::QTNSampler{MatrixProduct{State,Open}}) - n = sampler.n - χ = sampler.χ - p = get(sampler, :p, 2) - T = get(sampler, :eltype, Float64) - - arrays::Vector{AbstractArray{T}} = map(1:n) do i - χl, χr = let after_mid = i > n ÷ 2, i = (n + 1 - abs(2i - n - 1)) ÷ 2 - χl = min(χ, p^(i - 1)) - χr = min(χ, p^i) - - # swap bond dims after mid and handle midpoint for odd-length MPS - (isodd(n) && i == n ÷ 2 + 1) ? (χl, χl) : (after_mid ? (χr, χl) : (χl, χr)) - end - - # fix for first site - i == 1 && ((χl, χr) = (χr, 1)) - - # orthogonalize by Gram-Schmidt algorithm - A = gramschmidt!(rand(rng, T, χl, χr * p)) - - reshape(A, χl, χr, p) - end - - # reshape boundary sites - arrays[1] = reshape(arrays[1], p, p) - arrays[n] = reshape(arrays[n], p, p) - - # normalize state - arrays[1] ./= sqrt(p) - - MatrixProduct{State,Open}(arrays) -end - -# TODO let choose the orthogonality center -# TODO different input/output physical dims -function Base.rand(rng::Random.AbstractRNG, sampler::QTNSampler{MatrixProduct{Operator,Open}}) - n = sampler.n - χ = sampler.χ - p = get(sampler, :p, 2) - T = get(sampler, :eltype, Float64) - - ip = op = p - - arrays::Vector{AbstractArray{T}} = map(1:n) do i - χl, χr = let after_mid = i > n ÷ 2, i = (n + 1 - abs(2i - n - 1)) ÷ 2 - χl = min(χ, ip^(i - 1) * op^(i - 1)) - χr = min(χ, ip^i * op^i) - - # swap bond dims after mid and handle midpoint for odd-length MPS - (isodd(n) && i == n ÷ 2 + 1) ? (χl, χl) : (after_mid ? (χr, χl) : (χl, χr)) - end - - shape = if i == 1 - (χr, ip, op) - elseif i == n - (χl, ip, op) - else - (χl, χr, ip, op) - end - - # orthogonalize by Gram-Schmidt algorithm - A = gramschmidt!(rand(rng, T, shape[1], prod(shape[2:end]))) - - reshape(A, shape) - end - - # normalize - ζ = min(χ, ip * op) - arrays[1] ./= sqrt(ζ) - - MatrixProduct{Operator,Open}(arrays) -end - -# TODO stable renormalization -# TODO different input/output physical dims for Operator -function Base.rand(rng::Random.AbstractRNG, sampler::QTNSampler{MatrixProduct{P,Periodic}}) where {P<:Plug} - n = sampler.n - χ = sampler.χ - p = get(sampler, :p, 2) - T = get(sampler, :eltype, Float64) - - A = MatrixProduct{P,Periodic}([rand(rng, T, [P === State ? (χ, χ, p) : (χ, χ, p, p)]...) for _ in 1:n]) - normalize!(A) - - return A -end diff --git a/src/Quantum/PEP.jl b/src/Quantum/PEP.jl deleted file mode 100644 index 06e36d74..00000000 --- a/src/Quantum/PEP.jl +++ /dev/null @@ -1,173 +0,0 @@ -using UUIDs: uuid4 -using Classes - -""" - ProjectedEntangledPair{P<:Plug,B<:Boundary} <: Ansatz - -A generic ansatz representing Projected Entangled Pair States (PEPS) and Projected Entangled Pair Operators (PEPO). -Type variable `P` represents the `Plug` type (`State` or `Operator`) and `B` represents the `Boundary` type (`Open` or `Periodic`). -""" -struct ProjectedEntangledPair{P<:Plug,B<:Boundary} <: Ansatz end - -function ProjectedEntangledPair{P}(arrays; boundary::Type{<:Boundary} = Open, kwargs...) where {P<:Plug} - ProjectedEntangledPair{P,boundary}(arrays; kwargs...) -end - -const PEPS = ProjectedEntangledPair{State} -const PEPO = ProjectedEntangledPair{Operator} - -plug(::Type{<:ProjectedEntangledPair{P}}) where {P} = P() -boundary(::Type{<:ProjectedEntangledPair{P,B}}) where {P,B} = B() - -function sitealias(::Type{<:ProjectedEntangledPair{P,Open}}, order, size, pos) where {P<:Plug} - m, n = size - i, j = pos - - order = [order...] - - filter(order) do dir - !(i == 1 && dir === :u || i == m && dir === :d || j == 1 && dir === :l || j == n && dir === :r) - end -end -sitealias(::Type{<:ProjectedEntangledPair{P,Periodic}}, order, _, _) where {P<:Plug} = tuple(order...) - -defaultorder(::Type{<:ProjectedEntangledPair{State}}) = (:l, :r, :u, :d, :o) -defaultorder(::Type{<:ProjectedEntangledPair{Operator}}) = (:l, :r, :u, :d, :i, :o) - -""" - ProjectedEntangledPair{P,B}(arrays::Matrix{AbstractArray}; χ::Union{Nothing,Int} = nothing, order = defaultorder(ProjectedEntangledPair{P})) - -Construct a [`TensorNetwork`](@ref) with [`ProjectedEntangledPair`](@ref) ansatz, from the arrays of the tensors. - -# Keyword Arguments - - - `order` Order of the tensor indices on `arrays`. Defaults to `(:l, :r, :u, :d, :o)` if `P` is a `State`, `(:l, :r, :u, :d, :i, :o)` if `Operator`. -""" -function ProjectedEntangledPair{P,B}( - arrays; - χ = nothing, - order = defaultorder(ProjectedEntangledPair{P}), - metadata..., -) where {P<:Plug,B<:Boundary} - issetequal(order, defaultorder(ProjectedEntangledPair{P})) || throw( - ArgumentError( - "`order` must be a permutation of $(join(String.(defaultorder(ProjectedEntangledPair{P})), ',', " and "))", - ), - ) - - m, n = size(arrays) - hinds = Dict((i, j) => Symbol(uuid4()) for i in 1:m, j in ringpeek(1:n)) - vinds = Dict((i, j) => Symbol(uuid4()) for i in ringpeek(1:m), j in 1:n) - oinds = Dict((i, j) => Symbol(uuid4()) for i in 1:m, j in 1:n) - iinds = Dict((i, j) => Symbol(uuid4()) for i in 1:m, j in 1:n) - - input, output = if P <: Property - Symbol[], Symbol[] - elseif P <: State - Symbol[], vec([oinds[i, j] for i in 1:m, j in 1:n]) - elseif P <: Operator - vec([iinds[i, j] for i in 1:m, j in 1:n]), vec([oinds[i, j] for i in 1:m, j in 1:n]) - else - throw(ArgumentError("Plug $P is not valid")) - end - - tensors::Vector{Tensor} = - map(zip(Iterators.map(Tuple, eachindex(IndexCartesian(), arrays)), arrays)) do ((i, j), array) - dirs = sitealias(ProjectedEntangledPair{P,B}, order, (m, n), (i, j)) - - inds = map(dirs) do dir - if dir === :l - hinds[(i, (mod1(j - 1, n), j))] - elseif dir === :r - hinds[(i, (j, mod1(j + 1, n)))] - elseif dir === :u - vinds[((mod1(i - 1, m), i), j)] - elseif dir === :d - vinds[((i, mod1(i + 1, m)), j)] - elseif dir === :i - iinds[(i, j)] - elseif dir === :o - oinds[(i, j)] - end - end - - Tensor(array, inds) - end |> vec - - return QuantumTensorNetwork(TensorNetwork(tensors), input, output) -end - -# TODO normalize -# TODO let choose the orthogonality center -# TODO different input/output physical dims -function Base.rand(rng::Random.AbstractRNG, sampler::QTNSampler{ProjectedEntangledPair{P,Open}}) where {P<:Plug} - rows = sampler.rows - cols = sampler.cols - χ = sampler.χ - p = get(sampler, :p, 2) - T = get(sampler, :eltype, Float64) - - arrays::Matrix{AbstractArray{T,N} where {N}} = reshape( - map(Iterators.product(1:rows, 1:cols)) do (i, j) - shape = filter( - !=(1), - [ - i === 1 ? 1 : χ, - i === rows ? 1 : χ, - j === 1 ? 1 : χ, - j === cols ? 1 : χ, - p, - if P <: State - 1 - elseif P <: Operator - p - else - throw(ErrorException("$P is not a valid Plug type")) - end, - ], - ) - - rand(rng, T, shape...) - end, - rows, - cols, - ) - - # normalize state - arrays[1, 1] ./= P <: State ? sqrt(p) : p - - ProjectedEntangledPair{P,Open}(arrays) -end - -# TODO normalize -# TODO let choose the orthogonality center -# TODO different input/output physical dims -function Base.rand(rng::Random.AbstractRNG, sampler::QTNSampler{ProjectedEntangledPair{P,Periodic}}) where {P<:Plug} - rows = sampler.rows - cols = sampler.cols - χ = sampler.χ - p = get(sampler, :p, 2) - T = get(sampler, :eltype, Float64) - - arrays::Matrix{AbstractArray{T,N} where {N}} = reshape( - map(Iterators.product(1:rows, 1:cols)) do (i, j) - shape = tuple([χ, χ, χ, χ]..., ([if P <: State - (p,) - elseif P <: Operator - (p, p) - else - throw(ErrorException("$P is not a valid Plug type")) - end]...)...) - - # A = gramschmidt!(rand(rng, T, shape[1], prod(shape[1:end]))) - A = rand(rng, T, shape...) - end, - rows, - cols, - ) - - # normalize state - arrays[1, 1] ./= P <: State ? sqrt(p) : p - - ProjectedEntangledPair{P,Periodic}(arrays) -end diff --git a/src/Quantum/Quantum.jl b/src/Quantum/Quantum.jl deleted file mode 100644 index 180aa854..00000000 --- a/src/Quantum/Quantum.jl +++ /dev/null @@ -1,258 +0,0 @@ -using LinearAlgebra -using UUIDs: uuid4 -using ValSplit -using Classes - -""" - QuantumTensorNetwork - -Tensor Network that has a notion of sites and directionality (input/output). -""" -@class QuantumTensorNetwork <: TensorNetwork begin - input::Vector{Symbol} - output::Vector{Symbol} -end - -inds(tn::absclass(QuantumTensorNetwork), ::Val{:in}) = tuple(tn.input...) -inds(tn::absclass(QuantumTensorNetwork), ::Val{:in}, site) = tn.input[site] -inds(tn::absclass(QuantumTensorNetwork), ::Val{:out}) = tuple(tn.output...) -inds(tn::absclass(QuantumTensorNetwork), ::Val{:out}, site) = tn.output[site] -inds(tn::absclass(QuantumTensorNetwork), ::Val{:physical}) = ∪(tn.input, tn.output) -inds(tn::absclass(QuantumTensorNetwork), ::Val{:virtual}) = setdiff(inds(tn, Val(:all)), inds(tn, Val(:physical))) - -""" - sites(tn::AbstractQuantumTensorNetwork, dir) - -Return the sites in which the [`TensorNetwork`](@ref) acts. -""" -sites(tn::absclass(QuantumTensorNetwork)) = sites(tn, :in) ∪ sites(tn, :out) -function sites(tn::absclass(QuantumTensorNetwork), dir) - if dir === :in - firstindex(tn.input):lastindex(tn.input) - elseif dir === :out - firstindex(tn.output):lastindex(tn.output) - else - throw(MethodError("unknown dir=$dir")) - end -end - -function Base.replace!(tn::absclass(QuantumTensorNetwork), old_new::Pair{Symbol,Symbol}) - Base.@invoke replace!(tn::absclass(TensorNetwork), old_new::Pair{Symbol,Symbol}) - - replace!(tn.input, old_new) - replace!(tn.output, old_new) - - return tn -end - -""" - adjoint(tn::AbstractQuantumTensorNetwork) - -Return the adjoint [`TensorNetwork`](@ref). - -# Implementation details - -The tensors are not transposed, just `conj!` is applied to them. -""" -function Base.adjoint(tn::absclass(QuantumTensorNetwork)) - tn = deepcopy(tn) - - # swap input/output - temp = copy(tn.input) - resize!(tn.input, length(tn.output)) - copy!(tn.input, tn.output) - resize!(tn.output, length(temp)) - copy!(tn.output, temp) - - foreach(conj!, tensors(tn)) - - return tn -end - -function Base.merge!(self::absclass(QuantumTensorNetwork), other::absclass(QuantumTensorNetwork)) - sites(self, :out) == sites(other, :in) || - throw(DimensionMismatch("both `QuantumTensorNetwork`s must contain the same set of sites")) - - # copy to avoid mutation if reindex is needed - # TODO deepcopy because `indices` are not correctly copied and it mutates - other = deepcopy(other) - - # reindex other if needed - if inds(self, set = :out) != inds(other, set = :in) - replace!(other, map(splat(=>), zip(inds(other, set = :in), inds(self, set = :out)))) - end - - # reindex inner indices of `other` to avoid accidental hyperindices - conflict = inds(self, set = :virtual) ∩ inds(other, set = :virtual) - if !isempty(conflict) - replace!(other, map(i -> i => Symbol(uuid4()), conflict)) - end - - @invoke merge!(self::absclass(TensorNetwork), other::absclass(TensorNetwork)) - - # update i/o - copy!(self.output, other.output) - - self -end - -function contract(a::absclass(QuantumTensorNetwork), b::absclass(QuantumTensorNetwork); kwargs...) - contract(merge(a, b); kwargs...) -end - -# Plug trait -abstract type Plug end -struct Property <: Plug end -struct State <: Plug end -struct Dual <: Plug end -struct Operator <: Plug end - -""" - plug(::QuantumTensorNetwork) - -Return the `Plug` type of the [`TensorNetwork`](@ref). The following `Plug`s are defined in `Tenet`: - - - `Property` No inputs nor outputs. - - `State` Only outputs. - - `Dual` Only inputs. - - `Operator` Inputs and outputs. -""" -function plug(tn) - if isempty(tn.input) && isempty(tn.output) - Property() - elseif isempty(tn.input) - State() - elseif isempty(tn.output) - Dual() - else - Operator() - end -end - -# TODO look for more stable ways -""" - norm(ψ::AbstractQuantumTensorNetwork, p::Real=2) - -Compute the ``p``-norm of a [`QuantumTensorNetwork`](@ref). - -See also: [`normalize!`](@ref). -""" -function LinearAlgebra.norm(ψ::absclass(QuantumTensorNetwork), p::Real = 2; kwargs...) - p == 2 || throw(ArgumentError("p=$p is not implemented yet")) - - tn = merge(ψ, ψ') - if plug(tn) isa Operator - tn = tr(tn) - end - - return contract(tn; kwargs...) |> only |> sqrt |> abs -end - -""" - normalize!(ψ::AbstractQuantumTensorNetwork, p::Real = 2; insert::Union{Nothing,Int} = nothing) - -In-place normalize the [`TensorNetwork`](@ref). - -# Keyword Arguments - - - `insert` Choose the way the normalization is performed: - - + If `insert=nothing` (default), then all tensors are divided by ``\\sqrt[n]{\\lVert \\psi \\rVert_p}`` where `n` is the number of tensors. - + If `insert isa Integer`, then the tensor connected to the site pointed by `insert` is divided by the norm. - - Both approaches are mathematically equivalent. Choose between them depending on the numerical properties. - -See also: [`norm`](@ref). -""" -function LinearAlgebra.normalize!( - ψ::absclass(QuantumTensorNetwork), - p::Real = 2; - insert::Union{Nothing,Int} = nothing, - kwargs..., -) - norm = LinearAlgebra.norm(ψ, p; kwargs...) - - if isnothing(insert) - # method 1: divide all tensors by (√v)^(1/n) - n = length(tensors(ψ)) - norm ^= 1 / n - for tensor in tensors(ψ) - tensor ./= norm - end - else - # method 2: divide only one tensor - tensor = ψ.tensors[insert] # tensors(ψ, insert) # TODO fix this to match site? - tensor ./= norm - end -end - -""" - LinearAlgebra.tr(U::AbstractQuantumTensorNetwork) - -Trace `U`: sum of diagonal elements if `U` is viewed as a matrix. - -Depending on the result of `plug(U)`, different actions can be taken: - - - If `Property()`, the result of `contract(U)` will be a "scalar", for which the trace acts like the identity. - - If `State()`, the result of `contract(U)` will be a "vector", for which the trace is undefined and will fail. - - If `Operator()`, the input and output indices of `U` are connected. -""" -LinearAlgebra.tr(U::absclass(QuantumTensorNetwork)) = tr!(U) -tr!(U::absclass(QuantumTensorNetwork)) = tr!(plug(U), U) -tr!(::Property, scalar::absclass(QuantumTensorNetwork)) = scalar -function tr!(::Operator, U::absclass(QuantumTensorNetwork)) - sites(U, :in) == sites(U, :out) || throw(ArgumentError("input and output sites do not match")) - copyto!(U.output, U.input) - U -end - -""" - fidelity(ψ,ϕ) - -Compute the fidelity between states ``\\ket{\\psi}`` and ``\\ket{\\phi}``. -""" -fidelity(a, b; kwargs...) = abs(only(contract(a, b'; kwargs...)))^2 - -""" - marginal(ψ, site) - -Return the marginal quantum state of site. -""" -function marginal(ψ, site) - plug(ψ) == State() || throw("unimplemented") - - siteindex = inds(ψ, :out, site) - tensor = only(select(tn, siteindex)) - sum(tensor, inds = setdiff(inds(tensor), [siteindex])) -end - -# Boundary trait -abstract type Boundary end -struct Open <: Boundary end -struct Periodic <: Boundary end - -""" - boundary(::QuantumTensorNetwork) - -Return the `Boundary` type of the [`TensorNetwork`](@ref). The following `Boundary`s are defined in `Tenet`: - - - `Open` - - `Periodic` -""" -function boundary end - -abstract type Ansatz end - -struct QTNSampler{A<:Ansatz} <: Random.Sampler{QuantumTensorNetwork} - config::Dict{Symbol,Any} - - QTNSampler{A}(; kwargs...) where {A} = new{A}(kwargs) -end - -Base.eltype(::QTNSampler{A}) where {A} = A - -Base.getproperty(obj::QTNSampler, name::Symbol) = name === :config ? getfield(obj, :config) : obj.config[name] -Base.get(obj::QTNSampler, name, default) = get(obj.config, name, default) - -Base.rand(A::Type{<:Ansatz}; kwargs...) = rand(Random.default_rng(), A; kwargs...) -Base.rand(rng::AbstractRNG, A::Type{<:Ansatz}; kwargs...) = rand(rng, QTNSampler{A}(; kwargs...)) diff --git a/src/Tenet.jl b/src/Tenet.jl index bbe52d09..48943968 100644 --- a/src/Tenet.jl +++ b/src/Tenet.jl @@ -16,20 +16,6 @@ export contract, contract! include("Transformations.jl") export transform, transform! -include("Quantum/Quantum.jl") -export QuantumTensorNetwork, sites, fidelity -export Plug, plug, Property, State, Dual, Operator -export Boundary, boundary, Open, Periodic - -include("Quantum/MP.jl") -export MatrixProduct, MPS, MPO - -include("Quantum/PEP.jl") -export ProjectedEntangledPair, PEPS, PEPO - -# reexports from LinearAlgebra -export norm, normalize! - # reexports from EinExprs export einexpr, inds diff --git a/test/MatrixProductOperator_test.jl b/test/MatrixProductOperator_test.jl deleted file mode 100644 index 97cc6de2..00000000 --- a/test/MatrixProductOperator_test.jl +++ /dev/null @@ -1,126 +0,0 @@ -@testset "MatrixProduct{Operator}" begin - @testset "plug" begin - @test plug(MatrixProduct{Operator}) === Operator() - @test all(T -> plug(MatrixProduct{Operator,T}) === Operator(), [Open, Periodic]) - end - - @testset "boundary" begin - @test all(B -> boundary(MatrixProduct{Operator,B}) == B(), [Open, Periodic]) - end - - @testset "Constructor" begin - # empty constructor - @test_throws Exception MatrixProduct{Operator}([]) - - @test begin - arrays = [rand(2, 2, 2)] - MatrixProduct{Operator}(arrays) isa QuantumTensorNetwork - end - - @test begin - arrays = [rand(2, 2, 2), rand(2, 2, 2)] - MatrixProduct{Operator}(arrays) isa QuantumTensorNetwork - end - - @testset "`Open` boundary" begin - # product operator - @test begin - arrays = [rand(1, 2, 2), rand(1, 1, 2, 2), rand(1, 2, 2)] - MatrixProduct{Operator,Open}(arrays) isa QuantumTensorNetwork - end - - # alternative constructor - @test begin - arrays = [rand(1, 2, 2), rand(1, 1, 2, 2), rand(1, 2, 2)] - MatrixProduct{Operator}(arrays; boundary = Open) isa QuantumTensorNetwork - end - - # entangling operator - @test begin - i = 3 - o = 5 - arrays = [rand(2, i, o), rand(2, 4, i, o), rand(4, i, o)] - MatrixProduct{Operator,Open}(arrays) isa QuantumTensorNetwork - end - - # entangling operator - change order - @test begin - i = 3 - o = 5 - arrays = [rand(i, 2, o), rand(2, i, 4, o), rand(4, i, o)] - MatrixProduct{Operator,Open}(arrays, order = (:l, :i, :r, :o)) isa QuantumTensorNetwork - end - - # fail on Open with Periodic format - @test_throws MethodError begin - arrays = [rand(1, 1, 2, 2), rand(1, 1, 2, 2), rand(1, 1, 2, 2)] - MatrixProduct{Operator,Open}(arrays) isa QuantumTensorNetwork - end - end - - @testset "`Periodic` boundary" begin - # product operator - @test begin - arrays = [rand(1, 1, 2, 2), rand(1, 1, 2, 2), rand(1, 1, 2, 2)] - MatrixProduct{Operator,Periodic}(arrays) isa QuantumTensorNetwork - end - - # alternative constructor - @test begin - arrays = [rand(1, 1, 2, 2), rand(1, 1, 2, 2), rand(1, 1, 2, 2)] - MatrixProduct{Operator}(arrays; boundary = Periodic) isa QuantumTensorNetwork - end - - # entangling operator - @test begin - i = 3 - o = 5 - arrays = [rand(2, 4, i, o), rand(4, 8, i, o), rand(8, 2, i, o)] - MatrixProduct{Operator,Periodic}(arrays) isa QuantumTensorNetwork - end - - # entangling operator - change order - @test begin - i = 3 - o = 5 - arrays = [rand(2, i, 4, o), rand(4, i, 8, o), rand(8, i, 2, o)] - MatrixProduct{Operator,Periodic}(arrays, order = (:l, :i, :r, :o)) isa QuantumTensorNetwork - end - - # fail on Periodic with Open format - @test_throws MethodError begin - arrays = [rand(1, 2, 2), rand(1, 1, 2, 2), rand(1, 2, 2)] - MatrixProduct{Operator,Periodic}(arrays) isa QuantumTensorNetwork - end - end - end - - @testset "merge" begin - @test begin - arrays = [rand(2, 2), rand(2, 2)] - mps = MatrixProduct{State,Open}(arrays) - arrays_o = [rand(2, 2, 2), rand(2, 2, 2)] - mpo = MatrixProduct{Operator}(arrays_o) - merge(mps, mpo) isa QuantumTensorNetwork - end - - @test begin - arrays = [rand(2, 2), rand(2, 2)] - mps = MatrixProduct{State,Open}(arrays) - arrays_o = [rand(2, 2, 2), rand(2, 2, 2)] - mpo = MatrixProduct{Operator}(arrays_o) - merge(mpo, mps') isa QuantumTensorNetwork - end - - @test begin - arrays = [rand(2, 2, 2), rand(2, 2, 2)] - mpo = MatrixProduct{Operator}(arrays) - merge(mpo, mpo') isa QuantumTensorNetwork - end - end - - @testset "norm" begin - mpo = rand(MatrixProduct{Operator,Open}, n = 8, p = 2, χ = 8) - @test norm(mpo) ≈ 1 - end -end diff --git a/test/MatrixProductState_test.jl b/test/MatrixProductState_test.jl deleted file mode 100644 index c3459a66..00000000 --- a/test/MatrixProductState_test.jl +++ /dev/null @@ -1,122 +0,0 @@ -@testset "MatrixProduct{State}" begin - @testset "plug" begin - @test plug(MatrixProduct{State}) == State() - @test all(T -> plug(MatrixProduct{State,T}) == State(), [Open, Periodic]) - end - - @testset "boundary" begin - @test all(B -> boundary(MatrixProduct{State,B}) == B(), [Open, Periodic]) - end - - @testset "Constructor" begin - # empty constructor - @test_throws Exception MatrixProduct{State}([]) - - @test begin - arrays = [rand(1, 2)] - MatrixProduct{State}(arrays) isa QuantumTensorNetwork - end - - @test begin - arrays = [rand(1, 2), rand(1, 2)] - MatrixProduct{State}(arrays) isa QuantumTensorNetwork - end - - @testset "`Open` boundary" begin - # product state - @test begin - arrays = [rand(1, 2), rand(1, 1, 2), rand(1, 2)] - MatrixProduct{State,Open}(arrays) isa QuantumTensorNetwork - end - - # entangled state - @test begin - arrays = [rand(2, 2), rand(2, 4, 2), rand(4, 1, 2), rand(1, 2)] - MatrixProduct{State,Open}(arrays) isa QuantumTensorNetwork - end - - @testset "custom order" begin - arrays = [rand(3, 1), rand(3, 1, 3), rand(1, 3)] - ψ = MatrixProduct{State,Open}(arrays, order = (:r, :o, :l)) - - @test ψ isa QuantumTensorNetwork - end - - # alternative constructor - @test begin - arrays = [rand(1, 2), rand(1, 1, 2), rand(1, 2)] - MatrixProduct{State}(arrays; boundary = Open) isa QuantumTensorNetwork - end - - # fail on Open with Periodic format - @test_throws Exception begin - arrays = [rand(1, 1, 2), rand(1, 1, 2), rand(1, 1, 2)] - MatrixProduct{State,Open}(arrays) isa QuantumTensorNetwork - end - - @testset "rand" begin - # 4 => χ < maximum possible χ for the given parameters - # 32 => χ > maximum possible χ for the given parameters - @testset "χ = $χ" for χ in [4, 32] - ψ = rand(MatrixProduct{State,Open}, n = 7, p = 2, χ = χ) - - @test ψ isa QuantumTensorNetwork - @test length(tensors(ψ)) == 7 - @test maximum(vind -> size(ψ, vind), inds(ψ, :inner)) <= 32 - end - end - end - - @testset "`Periodic` boundary" begin - # product state - @test begin - arrays = [rand(1, 1, 2), rand(1, 1, 2), rand(1, 1, 2)] - MatrixProduct{State,Periodic}(arrays) isa QuantumTensorNetwork - end - - # entangled state - @test begin - arrays = [rand(3, 4, 2), rand(4, 8, 2), rand(8, 3, 2)] - MatrixProduct{State,Periodic}(arrays) isa QuantumTensorNetwork - end - - @testset "custom order" begin - arrays = [rand(3, 1, 3), rand(3, 1, 3), rand(3, 1, 3)] - ψ = MatrixProduct{State,Periodic}(arrays, order = (:r, :o, :l)) - - @test ψ isa QuantumTensorNetwork - end - - # alternative constructor - @test begin - arrays = [rand(1, 1, 2), rand(1, 1, 2), rand(1, 1, 2)] - MatrixProduct{State}(arrays; boundary = Periodic) isa QuantumTensorNetwork - end - - # fail on Periodic with Open format - @test_throws Exception begin - arrays = [rand(1, 2), rand(1, 1, 2), rand(1, 2)] - MatrixProduct{State,Periodic}(arrays) isa QuantumTensorNetwork - end - end - end - - @testset "merge" begin - @test begin - arrays = [rand(2, 2), rand(2, 2)] - mps = MatrixProduct{State,Open}(arrays) - merge(mps, mps') isa QuantumTensorNetwork - end - - @test begin - arrays = [rand(1, 1, 2), rand(1, 1, 2)] - mps = MatrixProduct{State,Periodic}(arrays) - merge(mps, mps') isa QuantumTensorNetwork - end - end - - @testset "norm" begin - mps = rand(MatrixProduct{State,Open}, n = 8, p = 2, χ = 8) - @test norm(mps) ≈ 1 - end -end diff --git a/test/Project.toml b/test/Project.toml index f186cef7..4221fac3 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -10,7 +10,6 @@ Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" NetworkLayout = "46757867-2c16-5918-afeb-47bfcb05e46a" OMEinsum = "ebe7aa44-baf0-506c-a96f-8464559b3922" Permutations = "2ae35dd2-176d-5d53-8349-f30d82d94d4f" -Quac = "b9105292-1415-45cf-bff1-d6ccf71e6143" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" diff --git a/test/Quantum_test.jl b/test/Quantum_test.jl deleted file mode 100644 index c7aa2f28..00000000 --- a/test/Quantum_test.jl +++ /dev/null @@ -1,152 +0,0 @@ -@testset "Quantum" begin - state = QuantumTensorNetwork( - TensorNetwork([Tensor(rand(2, 2), (:i, :k)), Tensor(rand(3, 2, 4), (:j, :k, :l))]), - Symbol[], # input - [:i, :j], # output - ) - - operator = QuantumTensorNetwork( - TensorNetwork([Tensor(rand(2, 4, 2), (:a, :c, :d)), Tensor(rand(3, 4, 3, 5), (:b, :c, :e, :f))]), - [:a, :b], # input - [:d, :e], # output - ) - - @testset "adjoint" begin - @testset "State" begin - adj = adjoint(state) - @test adj.input == state.output - @test adj.output == state.input - @test all(((a, b),) -> a == conj(b), zip(tensors(state), tensors(adj))) - end - - @testset "Operator" begin - adj = adjoint(operator) - @test adj.input == operator.output - @test adj.output == operator.input - @test all(((a, b),) -> a == conj(b), zip(tensors(operator), tensors(adj))) - end - end - - @testset "plug" begin - @test plug(state) == State() - @test plug(state') == Dual() - @test plug(operator) == Operator() - end - - @testset "sites" begin - @test issetequal(sites(state), [1, 2]) - @test issetequal(sites(operator), [1, 2]) - end - - @testset "inds" begin - @testset "State" begin - @test issetequal(inds(state), [:i, :j, :k, :l]) - @test issetequal(inds(state, set = :open), [:i, :j, :l]) - @test issetequal(inds(state, set = :inner), [:k]) - @test isempty(inds(state, set = :hyper)) - @test isempty(inds(state, set = :in)) - @test issetequal(inds(state, set = :out), [:i, :j]) - @test issetequal(inds(state, set = :physical), [:i, :j]) - @test issetequal(inds(state, set = :virtual), [:k, :l]) - end - - @testset "Operator" begin - @test issetequal(inds(operator), [:a, :b, :c, :d, :e, :f]) - @test issetequal(inds(operator, set = :open), [:a, :b, :d, :e, :f]) - @test issetequal(inds(operator, set = :inner), [:c]) - @test isempty(inds(operator, set = :hyper)) - @test issetequal(inds(operator, set = :in), [:a, :b]) - @test issetequal(inds(operator, set = :out), [:d, :e]) - @test issetequal(inds(operator, set = :physical), [:a, :b, :d, :e]) - @test issetequal(inds(operator, set = :virtual), [:c, :f]) - end - end - - @testset "merge" begin - @testset "(State, State)" begin - tn = merge(state, state') - - @test plug(tn) == Property() - - @test isempty(sites(tn, :in)) - @test isempty(sites(tn, :out)) - - @test isempty(inds(tn, set = :in)) - @test isempty(inds(tn, set = :out)) - @test isempty(inds(tn, set = :physical)) - @test issetequal(inds(tn), inds(tn, set = :virtual)) - end - - @testset "(State, Operator)" begin - tn = merge(state, operator) - - @test plug(tn) == State() - - @test isempty(sites(tn, :in)) - @test issetequal(sites(tn, :out), sites(operator, :out)) - - @test isempty(inds(tn, set = :in)) - @test issetequal(inds(tn, set = :out), inds(operator, :out)) - @test issetequal(inds(tn, set = :physical), inds(operator, :out)) - @test issetequal(inds(tn, set = :virtual), inds(state) ∪ inds(operator, :virtual)) - end - - @testset "(Operator, State)" begin - tn = merge(operator, state') - - @test plug(tn) == Dual() - - @test issetequal(sites(tn, :in), sites(operator, :in)) - @test isempty(sites(tn, :out)) - - @test issetequal(inds(tn, set = :in), inds(operator, :in)) - @test isempty(inds(tn, set = :out)) - @test issetequal(inds(tn, set = :physical), inds(operator, :in)) - @test issetequal( - inds(tn, set = :virtual), - inds(state, :virtual) ∪ inds(operator, :virtual) ∪ inds(operator, :out), - ) - end - - @testset "(Operator, Operator)" begin - tn = merge(operator, operator') - - @test plug(tn) == Operator() - - @test issetequal(sites(tn, :in), sites(operator, :in)) - @test issetequal(sites(tn, :out), sites(operator, :in)) - - @test issetequal(inds(tn, set = :in), inds(operator, :in)) - @test issetequal(inds(tn, set = :out), inds(operator, :in)) - @test issetequal(inds(tn, set = :physical), inds(operator, :in)) - @test inds(operator, :virtual) ⊆ inds(tn, set = :virtual) - end - - @testset "(Operator, Operator)" begin - tn = merge(operator', operator) - - @test plug(tn) == Operator() - - @test issetequal(sites(tn, :in), sites(operator, :out)) - @test issetequal(sites(tn, :out), sites(operator, :out)) - - @test issetequal(inds(tn, set = :in), inds(operator, :out)) - @test issetequal(inds(tn, set = :out), inds(operator, :out)) - @test issetequal(inds(tn, set = :physical), inds(operator, :out)) - @test inds(operator, :virtual) ⊆ inds(tn, set = :virtual) - end - - @testset "(State, Operator, State)" begin - tn = merge(state, operator, state') - - @test plug(tn) == Property() - - @test isempty(sites(tn, :in)) - @test isempty(sites(tn, :out)) - - @test isempty(inds(tn, set = :in)) - @test isempty(inds(tn, set = :out)) - @test isempty(inds(tn, set = :physical)) - end - end -end diff --git a/test/integration/Quac_test.jl b/test/integration/Quac_test.jl deleted file mode 100644 index 1b5179ba..00000000 --- a/test/integration/Quac_test.jl +++ /dev/null @@ -1,25 +0,0 @@ -@testset "Quac" begin - using Quac - using UUIDs: uuid4 - - @testset "Constructor" begin - n = 2 - qft = Quac.Algorithms.QFT(n) - tn = QuantumTensorNetwork(qft) - - @test tn isa QuantumTensorNetwork - @test issetequal(sites(tn), 1:n) - end - - # TODO currently broken - @testset "merge" begin - n = 2 - qft = QuantumTensorNetwork(Quac.Algorithms.QFT(n)) - iqft = replace(qft, [index => Symbol(uuid4()) for index in inds(qft)]...) - - tn = merge(qft, iqft) - - @test tn isa QuantumTensorNetwork - @test issetequal(sites(tn), 1:2) - end -end diff --git a/test/runtests.jl b/test/runtests.jl index f35ac9ce..e63c5589 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,7 +2,7 @@ using Test using Tenet using OMEinsum -@testset "Core tests" verbose = true begin +@testset "Unit tests" verbose = true begin include("Helpers_test.jl") include("Tensor_test.jl") include("Numerics_test.jl") @@ -10,16 +10,9 @@ using OMEinsum include("Transformations_test.jl") end -@testset "Quantum tests" verbose = true begin - include("Quantum_test.jl") - include("MatrixProductState_test.jl") - include("MatrixProductOperator_test.jl") -end - @testset "Integration tests" verbose = true begin include("integration/ChainRules_test.jl") include("integration/BlockArray_test.jl") - include("integration/Quac_test.jl") include("integration/Makie_test.jl") end