Skip to content

Commit

Permalink
add macro ham
Browse files Browse the repository at this point in the history
  • Loading branch information
Roger-luo committed Apr 7, 2018
1 parent 171f3dd commit 7e517ee
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 7 deletions.
2 changes: 0 additions & 2 deletions test/Hamiltonian/Core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ using Compat.Test
@testset "local hamiltonian" begin

mat = σ₁σ₂
display(mat)
println()
h = LocalHamiltonian(mat)
rhs = SubSites(Bit, 1, 0)
rhs_idx = Int(rhs) + 1
Expand Down
95 changes: 95 additions & 0 deletions test/Hamiltonian/FusedHamiltonian.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using QMTK
using QMTK.Consts.Pauli
import IterTools

struct FusedHamiltonian{D<:Tuple} <: AbstractHamiltonian
data::D
end

FusedHamiltonian(h::LocalHamiltonian...) = FusedHamiltonian(h)
function (h::FusedHamiltonian)(lattice::AbstractLattice, rhs::AbstractSites)
itrs = []
for each in h.data
push!(itrs, RegionIterator(each, lattice, rhs))
end
IterTools.chain(itrs...)
end


function make_hamiltonian(ex::Expr)
expr = Expr(:call, :FusedHamiltonian)
if Meta.isexpr(ex, :call)
if ex.args[1] == :sum # only one region
ex.args[1] = :LocalHamiltonian
return ex
elseif ex.args[1] == :+
for each in ex.args[2:end]
if each.args[1] == :sum
each.args[1] = :LocalHamiltonian
push!(expr.args, each)
elseif each.args[1] == :*
factor = each.args[2]
each.args[3].args[1] = :LocalHamiltonian
each.args[3].args[end] = Expr(:call, :*, factor, each.args[3].args[end])
push!(expr.args, each.args[3])
else
throw(ErrorException("Invalid Expression: $each"))
end
end
elseif ex.args[1] == :-
# preserve sign for the first one
each = ex.args[2]
if each.args[1] == :sum
each.args[1] = :LocalHamiltonian
push!(expr.args, each)
elseif each.args[1] == :*
factor = each.args[2]
each.args[3].args[1] = :LocalHamiltonian
each.args[3].args[end] = Expr(:call, :*, factor, each.args[3].args[end])
push!(expr.args, each.args[3])
else
throw(ErrorException("Invalid Expression: $each"))
end

for each in ex.args[3:end]
if each.args[1] == :sum
each.args[1] = :LocalHamiltonian
each.args[end] = Expr(:call, :*, -1, each.args[end]) # merge -1 to local matrix
push!(expr.args, each)
elseif each.args[1] == :*
factor = each.args[2]
each.args[3].args[1] = :LocalHamiltonian
each.args[3].args[end] = Expr(:call, :*, -1, factor, each.args[3].args[end])
push!(expr.args, each.args[3])
else
throw(ErrorException("Invalid Expression: $each"))
end
end
end
else
throw(ErrorException("Invalid Expression: $each"))
end
return expr
end

macro ham(expr::Expr)
make_hamiltonian(expr)
end

h = @ham sum(Region{1}, σ₁σ₂) + sum(Region{2}, σ₁σ₂)

chain = Chain(Fixed, 4)
rhs = rand(Bit, 4)
for (val, lhs) in h(chain, rhs)
@show val
@show lhs
end

# # merge factor into local matrix
# @ham 2 * sum(Region{1}, σ₁⊗σ₂) # => sum(Region{1}, 2 * σ₁⊗σ₂)

# mat = σ₁⊗σ₂
# h1 = LocalHamiltonian(Region{1}, mat)
# h2 = LocalHamiltonian(Region{2}, mat)

# FusedHamiltonian(h1, h2)
8 changes: 3 additions & 5 deletions test/Hamiltonian/Hamiltonian.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ end
include("RegionIter.jl")
end

# @testset "kron macros" begin
# include("KronMacro.jl")
# end


@testset "kron macros" begin
include("KronMacro.jl")
end
123 changes: 123 additions & 0 deletions test/Hamiltonian/test.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import QMTK: toexpr, kronparse, getid, Chain, Fixed, bonds, kronsum
using QMTK.Consts.Pauli

mutable struct ExprKernel
ex::Expr
legs::Vector
end

function ExprKernel(ex::Expr)
kernel = make_kernel_legs!(ExprKernel(ex, []))
kernel.ex = expr2lambda(ex)
return kernel
end

function toexpr(kernel::ExprKernel)
Expr(:->, Expr(:tuple, kernel.legs...), Expr(:block, Expr(:quote, kernel.ex)))
end

make_kernel_legs!(kernel::ExprKernel, ex::Symbol) = kernel
make_kernel_legs!(kernel::ExprKernel) = make_kernel_legs!(kernel, kernel.ex)

function make_kernel_legs!(kernel::ExprKernel, ex::Expr)
if Meta.isexpr(ex, :call)
for each in ex.args
make_kernel_legs!(kernel, each)
end
elseif Meta.isexpr(ex, :ref)
for each in ex.args[2:end]
if !(each in kernel.legs)
push!(kernel.legs, each)
end
end
else
throw(ErrorException("Invalid Expression $(ex)"))
end
return kernel
end

function ref2lambda(expr)
for i = 2:length(expr.args)
expr.args[i] = Expr(:$, expr.args[i])
end
return expr
end

function expr2lambda(expr)
if isa(expr, Symbol)
return expr
end

if Meta.isexpr(expr, :call)
for (i, each) in enumerate(expr.args)
expr.args[i] = expr2lambda(each)
end
elseif Meta.isexpr(expr, :ref)
return ref2lambda(expr)
else
throw(ErrorException("Invalid Expression $(expr)"))
end
return expr
end

macro kron(region, expr)
kernels = []
if Meta.isexpr(expr, :block)
for each in expr.args
if !Meta.isexpr(each, :line)
push!(kernels, ExprKernel(each))
end
end
else
push!(kernels, ExprKernel(expr))
end

kernel = kernels[1]

kernel_ex = toexpr(kernel)
ex = :(kronsum($(esc(kernel_ex)), $region))
for kernel in kernels[2:end]
ex = :(kronsum($(esc(toexpr(kernel))), $region) + $ex)
end

return ex
end


# kernel = ExprKernel(:(σ₁[i] * σ₁[j]))
# f = eval(toexpr(kernel))
# println(f(1, 2))
chain = Chain(Fixed, 4)
# f = @kron bonds(chain, 1)
# println(f(1, 2))
h = @kron bonds(chain, 1) σ₁[i] * σ₁[j]

# t = kronsum(bonds(chain, 1)) do i, j
# :(σ₁[$i] * σ₁[$j])
# end

println(h == t)
# println(@macroexpand @kron bonds(chain, 1) σ₁[i] * σ₁[j])

# kernel = ExprKernel(:(a[i] * (b[j] + c[k])))

# println(kernel.legs)
# ex = toexpr(kernel)
# f = eval(ex)
# println(f(1, 2, 3))
# println(kernel.ex)
# println(kernel.legs)

# i, j, k = 2, 3, 4
# # ex = expr2lambda(:(a[i] * (b[j] + c[k])))
# # expr2kernel(ex)

# ex = eval(Expr(:quote, kernel.ex))
# println(ex)

# # @kron sum(bonds(chain, 1)) a[i] * b[j]

# # @kron sum(bonds(chain, 1)) begin
# # a[i] * b[j]
# # a[i] * b[j]
# # end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ using Compat.Test

include("Base/Base.jl")
include("Lattice/Lattice.jl")
include("Hamiltonian/Hamiltonian.jl")
include("Samplers.jl")
include("Space.jl")

0 comments on commit 7e517ee

Please sign in to comment.