From 6b959a5a6de0b95350a4a7246aa543eb1cc0cf84 Mon Sep 17 00:00:00 2001 From: Tao Wang Date: Fri, 17 Nov 2023 20:58:29 -0500 Subject: [PATCH] add from_coeff_map and test --- example/taylor_expansion.jl | 10 +++++-- src/utility.jl | 60 ++++++++++++++++++++++++++----------- test/taylor.jl | 27 ++++++++++++++--- 3 files changed, 72 insertions(+), 25 deletions(-) diff --git a/example/taylor_expansion.jl b/example/taylor_expansion.jl index 4a0aa067..72c6028e 100644 --- a/example/taylor_expansion.jl +++ b/example/taylor_expansion.jl @@ -6,18 +6,22 @@ using FeynmanDiagram.Utility: taylorexpansion!, build_derivative_backAD!, count_operation function benchmark_AD(glist::Vector{T}) where {T<:Graph} - taylormap = Dict{Int,TaylorSeries{T}}() + #taylormap = Dict{Int,TaylorSeries{T}}() totaloperation = [0, 0] taylorlist = Vector{TaylorSeries{T}}() for g in glist - @time t, taylormap = taylorexpansion!(g; taylormap=taylormap) + var_dependence = Dict{Int,Vector{Bool}}() + for leaf in FeynmanDiagram.Leaves(g) + var_dependence[leaf.id] = [true for _ in 1:get_numvars()] + end + @time t, taylormap, from_coeff_map = taylorexpansion!(g, var_dependence) operation = count_operation(t) totaloperation = totaloperation + operation push!(taylorlist, t) print("operation number: $(operation)\n") - t_compare = build_derivative_backAD!(g) + t_compare, leaftaylor = build_derivative_backAD!(g) for (order, coeff) in (t_compare.coeffs) @assert (eval!(coeff)) == (eval!(Taylor.taylor_factorial(order) * t.coeffs[order])) end diff --git a/src/utility.jl b/src/utility.jl index f399af7d..886f519a 100644 --- a/src/utility.jl +++ b/src/utility.jl @@ -27,10 +27,20 @@ using ..Taylor - `var_dependence::Dict{Int,Vector{Bool}}` A dictionary that specifies the variable dependence of target graph leaves. Should map the id of each leaf to a Bool vector. The length of the vector should be the same as number of variables. - `to_coeff_map::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target graph to its correponding taylor series. +`from_coeff_map::Dict{Int,Tuple{Int,Vector{Bool}}}` A dicitonary that maps a taylor coefficient to its owner FeynmanGraph. The key should be the id of coefficient graph, and value should be a tuple of (feynmangraph.id, order). """ -function taylorexpansion!(graph::G, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); to_coeff_map::Dict{Int,TaylorSeries{G}}=Dict{Int,TaylorSeries{G}}()) where {G<:Graph} +function taylorexpansion!(graph::G, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); to_coeff_map::Dict{Int,TaylorSeries{G}}=Dict{Int,TaylorSeries{G}}(), from_coeff_map::Dict{Int,Tuple{Int,Vector{Int}}}=Dict{Int,Tuple{Int,Vector{Int}}}()) where {G<:Graph} if haskey(to_coeff_map, graph.id) #If already exist, use taylor series in to_coeff_map. - return to_coeff_map[graph.id], to_coeff_map + if isleaf(graph) + for (order, coeff) in to_coeff_map[graph.id].coeffs + if haskey(from_coeff_map, coeff.id) + @assert from_coeff_map[coeff.id] == (graph.id, order) "The graph g$(graph.id) is mapped to two different leaf taylor series!" + else + from_coeff_map[coeff.id] = (graph.id, order) + end + end + end + return to_coeff_map[graph.id], to_coeff_map, from_coeff_map elseif isleaf(graph) if haskey(var_dependence, graph.id) @@ -48,12 +58,13 @@ function taylorexpansion!(graph::G, var_dependence::Dict{Int,Vector{Bool}}=Dict{ coeff = Graph([]; operator=ComputationalGraphs.Sum(), factor=graph.factor) result.coeffs[o] = coeff end + from_coeff_map[result.coeffs[o].id] = (graph.id, o) end to_coeff_map[graph.id] = result - return result, to_coeff_map + return result, to_coeff_map, from_coeff_map else - to_coeff_map[graph.id] = graph.factor * apply(graph.operator, [taylorexpansion!(sub, var_dependence; to_coeff_map=to_coeff_map)[1] for sub in graph.subgraphs], graph.subgraph_factors) - return to_coeff_map[graph.id], to_coeff_map + to_coeff_map[graph.id] = graph.factor * apply(graph.operator, [taylorexpansion!(sub, var_dependence; to_coeff_map=to_coeff_map, from_coeff_map=from_coeff_map)[1] for sub in graph.subgraphs], graph.subgraph_factors) + return to_coeff_map[graph.id], to_coeff_map, from_coeff_map end end @@ -112,10 +123,20 @@ end - `var_dependence::Dict{Int,Vector{Bool}}` A dictionary that specifies the variable dependence of target diagram leaves. Should map the id of each leaf to a Bool vector. The length of the vector should be the same as number of variables. - `to_coeff_map::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target diagram to its correponding taylor series. +`from_coeff_map::Dict{Int,Tuple{Int,Vector{Bool}}}` A dicitonary that maps a taylor coefficient to its owner FeynmanGraph. The key should be the id of coefficient graph, and value should be a tuple of (feynmangraph.id, order). """ -function taylorexpansion!(graph::Diagram{W}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); to_coeff_map::Dict{Int,TaylorSeries{Graph{W,W}}}=Dict{Int,TaylorSeries{Graph{W,W}}}()) where {W} +function taylorexpansion!(graph::Diagram{W}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); to_coeff_map::Dict{Int,TaylorSeries{Graph{W,W}}}=Dict{Int,TaylorSeries{Graph{W,W}}}(), from_coeff_map::Dict{Int,Tuple{Int,Vector{Int}}}=Dict{Int,Tuple{Int,Vector{Int}}}()) where {W} if haskey(to_coeff_map, graph.hash) #If already exist, use taylor series in to_coeff_map. - return to_coeff_map[graph.hash], to_coeff_map + if isempty(graph.subdiagram) + for (order, coeff) in to_coeff_map[graph.hash].coeffs + if haskey(from_coeff_map, coeff.id) + @assert from_coeff_map[coeff.id] == (graph.hash, order) "The graph g$(graph.hash) is mapped to two different leaf taylor series!" + else + from_coeff_map[coeff.id] = (graph.hash, order) + end + end + end + return to_coeff_map[graph.hash], to_coeff_map, from_coeff_map elseif isempty(graph.subdiagram) if haskey(var_dependence, graph.hash) @@ -129,12 +150,13 @@ function taylorexpansion!(graph::Diagram{W}, var_dependence::Dict{Int,Vector{Boo o = collect(order) coeff = Graph([]; operator=ComputationalGraphs.Sum(), factor=graph.factor) result.coeffs[o] = coeff + from_coeff_map[coeff.id] = (graph.hash, o) end to_coeff_map[graph.hash] = result - return result, to_coeff_map + return result, to_coeff_map, from_coeff_map else - to_coeff_map[graph.hash] = graph.factor * apply(typeof(graph.operator), [taylorexpansion!(sub, var_dependence; to_coeff_map=to_coeff_map)[1] for sub in graph.subdiagram], ones(W, length(graph.subdiagram))) - return to_coeff_map[graph.hash], to_coeff_map + to_coeff_map[graph.hash] = graph.factor * apply(typeof(graph.operator), [taylorexpansion!(sub, var_dependence; to_coeff_map=to_coeff_map, from_coeff_map=from_coeff_map)[1] for sub in graph.subdiagram], ones(W, length(graph.subdiagram))) + return to_coeff_map[graph.hash], to_coeff_map, from_coeff_map end end @@ -149,6 +171,7 @@ end The dependence is given by a vector of the length same as the number of variables. - `label::Tuple{LabelProduct,LabelProduct}` A Tuple fermi (first element) and bose LabelProduct (second element). - `to_coeff_map::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target diagram to its correponding taylor series. +`from_coeff_map::Dict{Int,Tuple{Int,Vector{Bool}}}` A dicitonary that maps a taylor coefficient to its owner FeynmanGraph. The key should be the id of coefficient graph, and value should be a tuple of (feynmangraph.id, order). """ function taylorexpansion!(graph::FeynmanGraph{F,W}, propagator_var::Tuple{Vector{Bool},Vector{Bool}}; to_coeff_map::Dict{Int,TaylorSeries{Graph{F,W}}}=Dict{Int,TaylorSeries{Graph{F,W}}}(), from_coeff_map::Dict{Int,Tuple{Int,Vector{Int}}}=Dict{Int,Tuple{Int,Vector{Int}}}()) where {F,W} var_dependence = Dict{Int,Vector{Bool}}() @@ -177,33 +200,34 @@ end - `propagator_var::Dict{DataType,Vector{Bool}}` A dictionary that specifies the variable dependence of different types of diagrams. Should be a map between DataTypes in DiagramID and Bool vectors. The dependence is given by a vector of the length same as the number of variables. - `to_coeff_map::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target diagram to its correponding taylor series. +- `from_coeff_map::Dict{Int,Tuple{Int,Vector{Bool}}}` A dicitonary that maps a taylor coefficient to its owner FeynmanGraph. The key should be the id of coefficient graph, and value should be a tuple of (feynmangraph.id, order). """ -function taylorexpansion!(graph::Diagram{W}, propagator_var::Dict{DataType,Vector{Bool}}; to_coeff_map::Dict{Int,TaylorSeries{Graph{W,W}}}=Dict{Int,TaylorSeries{Graph{W,W}}}()) where {W} +function taylorexpansion!(graph::Diagram{W}, propagator_var::Dict{DataType,Vector{Bool}}; to_coeff_map::Dict{Int,TaylorSeries{Graph{W,W}}}=Dict{Int,TaylorSeries{Graph{W,W}}}(), from_coeff_map::Dict{Int,Tuple{Int,Vector{Int}}}=Dict{Int,Tuple{Int,Vector{Int}}}()) where {W} var_dependence = Dict{Int,Vector{Bool}}() for leaf in Leaves(graph) if haskey(propagator_var, typeof(leaf.id)) var_dependence[leaf.hash] = [propagator_var[typeof(leaf.id)][idx] ? true : false for idx in 1:get_numvars()] end end - return taylorexpansion!(graph, var_dependence; to_coeff_map=to_coeff_map) + return taylorexpansion!(graph, var_dependence; to_coeff_map=to_coeff_map, from_coeff_map=from_coeff_map) end -function taylorexpansion!(graphs::Vector{G}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); to_coeff_map::Dict{Int,TaylorSeries{G}}=Dict{Int,TaylorSeries{G}}()) where {G<:Graph} +function taylorexpansion!(graphs::Vector{G}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); to_coeff_map::Dict{Int,TaylorSeries{G}}=Dict{Int,TaylorSeries{G}}(), from_coeff_map::Dict{Int,Tuple{Int,Vector{Int}}}=Dict{Int,Tuple{Int,Vector{Int}}}()) where {G<:Graph} result = Vector{TaylorSeries{G}}() for graph in graphs - taylor, _ = taylorexpansion!(graph, var_dependence; to_coeff_map=to_coeff_map) + taylor, _ = taylorexpansion!(graph, var_dependence; to_coeff_map=to_coeff_map, from_coeff_map=from_coeff_map) push!(result, taylor) end - return result, to_coeff_map + return result, to_coeff_map, from_coeff_map end -function taylorexpansion!(graphs::Vector{Diagram{W}}, propagator_var::Dict{DataType,Vector{Bool}}; to_coeff_map::Dict{Int,TaylorSeries{Graph{W,W}}}=Dict{Int,TaylorSeries{Graph{W,W}}}()) where {W} +function taylorexpansion!(graphs::Vector{Diagram{W}}, propagator_var::Dict{DataType,Vector{Bool}}; to_coeff_map::Dict{Int,TaylorSeries{Graph{W,W}}}=Dict{Int,TaylorSeries{Graph{W,W}}}(), from_coeff_map::Dict{Int,Tuple{Int,Vector{Int}}}=Dict{Int,Tuple{Int,Vector{Int}}}()) where {W} result = Vector{TaylorSeries{Graph{W,W}}}() for graph in graphs - taylor, _ = taylorexpansion!(graph, propagator_var; to_coeff_map=to_coeff_map) + taylor, _ = taylorexpansion!(graph, propagator_var; to_coeff_map=to_coeff_map, from_coeff_map=from_coeff_map) push!(result, taylor) end - return result, to_coeff_map + return result, to_coeff_map, from_coeff_map end """ taylorexpansion_withmap(g::G; coeffmode=true, var::Vector{Int}=collect(1:get_numvars())) where {G<:Graph} diff --git a/test/taylor.jl b/test/taylor.jl index 6320e62b..acbd6eda 100644 --- a/test/taylor.jl +++ b/test/taylor.jl @@ -62,7 +62,13 @@ end var_dependence[leaf.id] = [true for _ in 1:get_numvars()] end end - T, taylormap = taylorexpansion!(G, var_dependence) + T, taylormap, from_coeff_map = taylorexpansion!(G, var_dependence) + for leaf in Leaves(G) + t = taylormap[leaf.id] + for (order, coeff) in t.coeffs + @test from_coeff_map[coeff.id] == (leaf.id, order) + end + end T_compare, taylormap_compare = build_derivative_backAD!(G) leafmap1, leafvec1, leafmap2, leafvec2 = assign_random_numbers(G, taylormap, taylormap_compare) for (order, coeff) in T_compare.coeffs @@ -82,8 +88,13 @@ end set_variables("x y", orders=[2, 2]) propagator_var = ([true, false], [false, true]) # Specify variable dependence of fermi (first element) and bose (second element) particles. - t, taylormap = taylorexpansion!(g[1][1], propagator_var) - + t, taylormap, from_coeff_map = taylorexpansion!(g[1][1], propagator_var) + for leaf in Leaves(g[1][1]) + taylor = taylormap[leaf.id] + for (order, coeff) in taylor.coeffs + @test from_coeff_map[coeff.id] == (leaf.id, order) + end + end for (order, graph) in dict_g if graph[2][1] == g[2][1] idx = 1 @@ -206,7 +217,15 @@ end set_variables("x y"; orders=[2, 2]) propagator_var = Dict(DiagTree.BareGreenId => [true, false], DiagTree.BareInteractionId => [false, true]) # Specify variable dependence of fermi (first element) and bose (second element) particles. - t, taylormap = taylorexpansion!(root, propagator_var) + t, taylormap, from_coeff_map = taylorexpansion!(root, propagator_var) + for leaf in PostOrderDFS(root) + if isempty(leaf.subdiagram) + taylor = taylormap[leaf.hash] + for (order, coeff) in taylor.coeffs + @test from_coeff_map[coeff.id] == (leaf.hash, order) + end + end + end taylorleafmap, taylorleafvec = assign_leaves(root, taylormap) @test eval!(t.coeffs[[0, 0]], taylorleafmap, taylorleafvec) ≈ root.weight @test eval!(t.coeffs[[0, 1]], taylorleafmap, taylorleafvec) ≈ droot_dv.weight / taylor_factorial([0, 1])