The Ansatz class
The Lattice type
A Lattice is a graph that reprents the connectivity pattern between different physical sites. Its vertices are Lanes and wherever an edge exists between two Lanes, it means that those two sites can interact locally. A Lattice is constructed by passing a Graph and a dictionary mapping Lanes to the original graph's vertices:
julia> using Graphs
julia> graph = path_graph(4)
{4, 3} undirected simple Int64 graph
julia> lattice = Lattice(graph, Dict([lane"1" => 1, lane"2" => 2, lane"3" => 3, lane"4" => lane"4"]))
ERROR: MethodError: no method matching nv(::Dict{Lane{1}, Any})
The function `nv` exists, but no method is defined for this combination of argument types.
Closest candidates are:
nv(!Matched::Lattice)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/Lattice.jl:116
nv(!Matched::TreeWidthSolver.MaskedBitGraph{INT}) where INT
@ TreeWidthSolver ~/.julia/packages/TreeWidthSolver/7H21e/src/bitgraphs.jl:26
nv(!Matched::Graphs.Test.GenericDiGraph)
@ Graphs ~/.julia/packages/Graphs/1ALGD/src/Test/Test.jl:88
...Because the kind of graph topologies we use are quite common, we provide some shortcuts:
julia> lattice = Lattice(Val(:chain), 4)
Lattice(Lane[Lane{1}((1,)), Lane{1}((2,)), Lane{1}((3,)), Lane{1}((4,))], Graphs.SimpleGraphs.SimpleGraph{Int64}(3, [[2], [1, 3], [2, 4], [3]]))
julia> lattice = Lattice(Val(:grid), 3, 5)
ERROR: MethodError: no method matching Lattice(::Val{:grid}, ::Int64, ::Int64)
The type `Lattice` exists, but no method is defined for this combination of argument types when trying to construct it.
Closest candidates are:
Lattice(::Any, ::Any)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/Lattice.jl:47
Lattice(!Matched::Val{:rectangular}, ::Any, ::Any; periodic)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/Lattice.jl:194
Lattice(!Matched::Val{:lieb}, ::Any, ::Any)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/Lattice.jl:205
...
julia> lattice = Lattice(Val(:lieb), 2, 2)
Lattice(Lane[Lane{2}((1, 1)), Lane{2}((1, 2)), Lane{2}((1, 3)), Lane{2}((1, 4)), Lane{2}((1, 5)), Lane{2}((2, 1)), Lane{2}((2, 3)), Lane{2}((2, 5)), Lane{2}((3, 1)), Lane{2}((3, 2)) … Lane{2}((3, 4)), Lane{2}((3, 5)), Lane{2}((4, 1)), Lane{2}((4, 3)), Lane{2}((4, 5)), Lane{2}((5, 1)), Lane{2}((5, 2)), Lane{2}((5, 3)), Lane{2}((5, 4)), Lane{2}((5, 5))], Graphs.SimpleGraphs.SimpleGraph{Int64}(24, [[2, 6], [1, 3], [2, 4, 7], [3, 5], [4, 8], [1, 9], [3, 11], [5, 13], [6, 10, 14], [9, 11] … [11, 13], [8, 12, 16], [9, 17], [11, 19], [13, 21], [14, 18], [17, 19], [15, 18, 20], [19, 21], [16, 20]]))The Ansatz type
A Ansatz is a Quantum Tensor Network with a fixed graph structure, represented by a Lattice.
julia> lattice = Lattice(Val(:chain), 4)
Lattice(Lane[Lane{1}((1,)), Lane{1}((2,)), Lane{1}((3,)), Lane{1}((4,))], Graphs.SimpleGraphs.SimpleGraph{Int64}(3, [[2], [1, 3], [2, 4], [3]]))
julia> tn = TensorNetwork([
Tensor(rand(2,2), (:p1, :v12)),
Tensor(rand(2,2,4), (:p2, :v12, :v23)),
Tensor(rand(2,4,2), (:p3, :v23, :v34)),
Tensor(rand(2,2), (:p4, :v34)),
])
TensorNetwork (#tensors=4, #inds=7)
julia> qtn = Quantum(tn, Dict([site"1" => :p1, site"2" => :p2, site"3" => :p3, site"4" => :p4]))
Quantum (inputs=0, outputs=4)
julia> ansatz = Ansatz(qtn, lattice)
Ansatz (inputs=0, outputs=4)Just as Quantum adds information to a TensorNetwork on how to map open indices to input/output physical sites, a Ansatz teaches a Quantum on how to map Lattice Lanes to Tensors.
julia> tensors(ansatz; at=lane"1")
2×2 Tensor{Float64, 2, Matrix{Float64}}:
0.797867 0.807897
0.112541 0.768081Because ...
julia> inds(ansatz; bond=(lane"1", lane"2"))
:v12Time Evolution
[evolve!] is a high-level wrapper for different methods used for time-evolution.
Note
In other Tensor Network and Quantum Computing libraries, you may know evolve! by the name of apply! or apply. Given that the word "apply" has many semantic acceptions, we believe that "evolve" fits better to its purpose.
julia> gate = Gate([0 1; 1 0], [site"1", site"1'"])
Gate([0 1; 1 0], Site[1, 1'])
julia> evolve!(tn, gate)
ERROR: MethodError: no method matching evolve!(::TensorNetwork, ::Gate)
The function `evolve!` exists, but no method is defined for this combination of argument types.
Closest candidates are:
evolve!(!Matched::Tenet.AbstractAnsatz, ::Any; threshold, maxdim, normalize, kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/Ansatz.jl:417
evolve!(!Matched::Canonical, !Matched::Tenet.AbstractMPS, !Matched::Tenet.AbstractMPO; kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/MPS.jl:640
evolve!(!Matched::MixedCanonical, !Matched::Tenet.AbstractMPS, !Matched::Tenet.AbstractMPO; kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/MPS.jl:628
...When applying a multi-site gate, there are different numerical methods that can be used for approximate evolution of states. As of the time of writing, only the "Simple Update" algorithm is implemented in simple_update! but we plan to implement other methods like "Full Update" algorithm in the future.
Tip
evolve! is just a wrapper over different numerical methods for evolving states. You're free to call simple_update! directly if you want.
Warning
Currently, only 2-site gates are supported.
For example, this is how you would evolve / apply a two-site local operator using both evolve!](/api/ansatz#Tenet.evolve!-Tuple{Tenet.AbstractAnsatz,%20Any}) and [simple_update!:
julia> evolve!(tn, Gate(rand(2,2,2,2), [site"1", site"2", site"1'", site"2'"]))
ERROR: MethodError: no method matching evolve!(::TensorNetwork, ::Gate)
The function `evolve!` exists, but no method is defined for this combination of argument types.
Closest candidates are:
evolve!(!Matched::Tenet.AbstractAnsatz, ::Any; threshold, maxdim, normalize, kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/Ansatz.jl:417
evolve!(!Matched::Canonical, !Matched::Tenet.AbstractMPS, !Matched::Tenet.AbstractMPO; kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/MPS.jl:640
evolve!(!Matched::MixedCanonical, !Matched::Tenet.AbstractMPS, !Matched::Tenet.AbstractMPO; kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/MPS.jl:628
...
julia> simple_update!(tn, Gate(rand(2,2,2,2), [site"1", site"2", site"1'", site"2'"]))
ERROR: MethodError: no method matching simple_update!(::TensorNetwork, ::Gate)
The function `simple_update!` exists, but no method is defined for this combination of argument types.
Closest candidates are:
simple_update!(!Matched::Tenet.AbstractAnsatz, ::Gate; threshold, maxdim, kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/Ansatz.jl:449As you operate on a Ansatz, it will make sure that the Lattice topology is preserve through different operations. So a two-site Gate between non-connected Lanes is forbidden:
julia> evolve!(tn, Gate(rand(2,2,2,2), [site"1", site"4", site"1'", site"4'"])) # this errors
ERROR: MethodError: no method matching evolve!(::TensorNetwork, ::Gate)
The function `evolve!` exists, but no method is defined for this combination of argument types.
Closest candidates are:
evolve!(!Matched::Tenet.AbstractAnsatz, ::Any; threshold, maxdim, normalize, kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/Ansatz.jl:417
evolve!(!Matched::Canonical, !Matched::Tenet.AbstractMPS, !Matched::Tenet.AbstractMPO; kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/MPS.jl:640
evolve!(!Matched::MixedCanonical, !Matched::Tenet.AbstractMPS, !Matched::Tenet.AbstractMPO; kwargs...)
@ Tenet ~/work/Tenet.jl/Tenet.jl/src/MPS.jl:628
...DocumenterMermaid.MermaidScriptBlock([...])