Skip to content

Commit

Permalink
Merge pull request #11 from mtsch/gradient-descent
Browse files Browse the repository at this point in the history
Add density profile ansatz
  • Loading branch information
mtsch authored Aug 28, 2024
2 parents 86ce163 + e6f58e4 commit 9adc98c
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 28 deletions.
4 changes: 2 additions & 2 deletions src/Gutzwiller.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ using SpecialFunctions
using Tables
using VectorInterface

import Rimu.Hamiltonians.extended_hubbard_interaction as ebh

export num_parameters, val_and_grad
include("ansatz/abstract.jl")
export VectorAnsatz
Expand All @@ -27,6 +25,8 @@ export MultinomialAnsatz
include("ansatz/multinomial.jl")
export JastrowAnsatz, RelativeJastrowAnsatz
include("ansatz/jastrow.jl")
export DensityProfileAnsatz
include("ansatz/densityprofile.jl")
export ExtendedAnsatz
include("ansatz/combination.jl")

Expand Down
28 changes: 28 additions & 0 deletions src/ansatz/densityprofile.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
DensityProfileAnsatz(hamiltonian) <: AbstractAnsatz
```math
D(|f⟩; p) = exp(-∑_{i=1}^M p_i ⟨f|n_i|f⟩)
```
"""
struct DensityProfileAnsatz{A,N,H} <: AbstractAnsatz{A,Float64,N}
hamiltonian::H
end

function DensityProfileAnsatz(hamiltonian)
address = starting_address(hamiltonian)
@assert address isa SingleComponentFockAddress
N = num_modes(address)
return DensityProfileAnsatz{typeof(address),N,typeof(hamiltonian)}(hamiltonian)
end

Rimu.build_basis(dp::DensityProfileAnsatz) = build_basis(dp.hamiltonian)

function val_and_grad(dp::DensityProfileAnsatz, addr, params)
o = onr(addr)
exponent = dot(o, params)
val = exp(-exponent)
grad = -val * o
return val, grad
end
(dp::DensityProfileAnsatz)(addr, params) = exp(-dot(onr(addr), params))
10 changes: 5 additions & 5 deletions src/ansatz/extgutzwiller.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ Rimu.build_basis(gv::ExtendedGutzwillerAnsatz) = build_basis(gv.hamiltonian)

function val_and_grad(gv::ExtendedGutzwillerAnsatz, addr, params)
g1, g2 = params
ebh_interaction, diag = ebh(addr)
ebh_interaction, diag = Rimu.Hamiltonians.extended_hubbard_interaction(addr)

val = exp(-g1 * diag + -g2*ebh_interaction)
val = exp(-g1 * diag + -g2 * Rimu.Hamiltonians.extended_hubbard_interaction_interaction)
der_g1 = -diag * val
der_g2 = -ebh_interaction * val
der_g2 = -Rimu.Hamiltonians.extended_hubbard_interaction_interaction * val

return val, SVector(der_g1, der_g2)
end

function (gv::ExtendedGutzwillerAnsatz)(addr, params)
g1,g2 = params
ebh_int, bh_int = ebh(addr)
return exp(-g1*bh_int + -g2*ebh_int)
ebh_int, bh_int = Rimu.Hamiltonians.extended_hubbard_interaction(addr)
return exp(-g1 * bh_int + -g2 * ebh_int)
end
25 changes: 11 additions & 14 deletions src/ansatz/jastrow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,34 @@ using Rimu.Hamiltonians: circshift_dot
JastrowAnsatz(hamiltonian) <: AbstractAnsatz
```math
J_i = exp(-∑_{k=1}^M ∑_{l=k}^M p_{k,l} n_k n_l)
J(|f⟩; p) = exp(-∑_{k=1}^M ∑_{l=k}^M p_{k,l} ⟨f|n_k n_l|f⟩)
```
With translationally invariant Hamiltonians, use [`RelativeJastrowAnsatz`](@ref) instead.
"""
struct JastrowAnsatz{A,T,N,H} <: AbstractAnsatz{A,T,N}
struct JastrowAnsatz{A,N,H} <: AbstractAnsatz{A,Float64,N}
hamiltonian::H
end

function JastrowAnsatz(hamiltonian)
address = starting_address(hamiltonian)
@assert address isa SingleComponentFockAddress
N = num_modes(address) * (num_modes(address) + 1) ÷ 2
return JastrowAnsatz{typeof(address),Float64,N,typeof(hamiltonian)}(hamiltonian)
return JastrowAnsatz{typeof(address),N,typeof(hamiltonian)}(hamiltonian)
end

Rimu.build_basis(j::JastrowAnsatz) = build_basis(j.hamiltonian)

function val_and_grad(j::JastrowAnsatz, addr, params)
function val_and_grad(j::JastrowAnsatz{A,N}, addr::A, params) where {A,N}
o = onr(addr)
M = num_modes(addr)

val = 0.0
grad = zeros(typeof(params))
grad = zeros(SVector{N,Float64})

p = 0
for i in 1:M, j in i:M
@inbounds for i in 1:M, j in i:M
p += 1

onproduct = o[i] * o[j]
local_val = params[p] * onproduct
val += local_val
Expand Down Expand Up @@ -66,19 +65,19 @@ For a translationally invariant Hamiltonian, this is equivalent to [`JastrowAnsa
but has fewer parameters.
```math
R_i = exp(-∑_{d=0}^{M÷2} p_d ∑_{k=1}^{M} n_k n_{k + d})
J(|f⟩; p) = exp(-∑_{d=0}^{M÷2} p_d ∑_{k=1}^{M} ⟨f|n_k n_{k + d}|f⟩)
```
"""
struct RelativeJastrowAnsatz{A,T,N,H} <: AbstractAnsatz{A,T,N}
struct RelativeJastrowAnsatz{A,N,H} <: AbstractAnsatz{A,Float64,N}
hamiltonian::H
end

function RelativeJastrowAnsatz(hamiltonian)
address = starting_address(hamiltonian)
@assert address isa SingleComponentFockAddress
N = cld(num_modes(address), 2)
return RelativeJastrowAnsatz{typeof(address),Float64,N,typeof(hamiltonian)}(hamiltonian)
return RelativeJastrowAnsatz{typeof(address),N,typeof(hamiltonian)}(hamiltonian)
end

Rimu.build_basis(rj::RelativeJastrowAnsatz) = build_basis(rj.hamiltonian)
Expand All @@ -88,10 +87,8 @@ function val_and_grad(rj::RelativeJastrowAnsatz, addr, params)
M = num_parameters(rj)

products = ntuple(i -> circshift_dot(o, o, i - 1), Val(M))
val = sum(1:M) do i
params[i] * circshift_dot(o, o, i - 1)
end
val = exp(-val)
exponent = dot(params, products)
val = exp(-exponent)
grad = -SVector{M,Float64}(products .* val)

return val, grad
Expand Down
8 changes: 8 additions & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Rimu = "c53c40cc-bd84-11e9-2cf4-a9fde2b9386e"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
19 changes: 13 additions & 6 deletions test/ansatz.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ using Rimu
using ForwardDiff

function check_ansatz(H, ansatz, params)
@testset "$H / $ansatz" begin
@testset "$H / $(nameof(typeof(ansatz)))" begin
# these tests look dumb, but assuming H and params are selected properly, they do
# make sense.
@testset "properties" begin
Expand All @@ -14,7 +14,7 @@ function check_ansatz(H, ansatz, params)
end

@testset "val_and_grad" begin
addrs = rand(build_basis(H), 5)
addrs = [starting_address(H); rand(build_basis(H), 10)]
for addr in addrs
val1 = ansatz(addr, params)
val2, grad1 = val_and_grad(ansatz, addr, params)
Expand Down Expand Up @@ -47,13 +47,20 @@ end
HubbardMom1D(BoseFS(10, 5 => 3); u=4),
HubbardRealSpace(FermiFS2C((1,0,0,1), (1,1,0,0)); geometry=PeriodicBoundaries(2,2)),
)
check_ansatz(H, GutzwillerAnsatz(H), [0.4])
M = num_modes(starting_address(H))

check_ansatz(H, GutzwillerAnsatz(H), rand(1))
if H isa ExtendedHubbardReal1D
check_ansatz(H, ExtendedGutzwillerAnsatz(H), [0.4, 0.5])
#check_ansatz(H, ExtendedGutzwillerAnsatz(H), rand(2))
end
if starting_address(H) isa BoseFS
check_ansatz(H, MultinomialAnsatz(H), [0.5])
check_ansatz(H, GutzwillerAnsatz(H) + MultinomialAnsatz(H), [0.5, 0.4, 0.2])
check_ansatz(H, MultinomialAnsatz(H), rand(1))
check_ansatz(H, GutzwillerAnsatz(H) + MultinomialAnsatz(H), rand(3))
end
if starting_address(H) isa SingleComponentFockAddress
check_ansatz(H, JastrowAnsatz(H), rand((M * (M + 1)) ÷ 2))
check_ansatz(H, RelativeJastrowAnsatz(H), rand(cld(M, 2)))
check_ansatz(H, DensityProfileAnsatz(H), rand(M))
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion test/sampling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ using KrylovKit

for ansatz in (
GutzwillerAnsatz(H),
ExtendedGutzwillerAnsatz(H),
#ExtendedGutzwillerAnsatz(H),
MultinomialAnsatz(H),
)
@testset "$ansatz" begin
Expand Down

0 comments on commit 9adc98c

Please sign in to comment.