diff --git a/example/benchmark.jl b/example/benchmark.jl index 334a8882..653909a7 100644 --- a/example/benchmark.jl +++ b/example/benchmark.jl @@ -22,13 +22,13 @@ function assign_leaves(g::FeynmanGraph, taylormap) return leafmap, leafvec end -dict_g, fl, bl, leafmap = diagdictGV(:sigma, [(2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 2, 0), (2, 1, 2), (2, 2, 2)], 3) +#dict_g, fl, bl, leafmap = diagdictGV(:sigma, [(2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 2, 0), (2, 1, 2), (2, 2, 2)], 3) +dict_g, lp, leafmap = diagdictGV(:sigma, [(3, 0, 0), (3, 0, 3), (3, 0, 2), (3, 0, 1)]) +g = dict_g[(3, 0, 0)] -g = dict_g[(2, 0, 0)] - -set_variables("x y", orders=[2, 2]) +set_variables("x y", orders=[1, 3]) 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, (fl, bl)) +t, taylormap, from_coeff_map = taylorexpansion!(g[1][1], propagator_var) for (order, graph) in dict_g if graph[2][1] == g[2][1] @@ -36,6 +36,8 @@ for (order, graph) in dict_g else idx = 2 end + print("$(count_operation(t.coeffs[[order[2],order[3]]]))\n") + print("$(count_operation(graph[1][idx]))\n") print("$(order) $(eval!(graph[1][idx])) $(eval!(t.coeffs[[order[2],order[3]]]))\n") end 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/computational_graph/tree_properties.jl b/src/computational_graph/tree_properties.jl index 82f4cce4..84e2819b 100644 --- a/src/computational_graph/tree_properties.jl +++ b/src/computational_graph/tree_properties.jl @@ -119,7 +119,7 @@ end # Arguments: - `g::Graph`: graph for which to find the total number of operations. """ -function count_operation(g::Graph) +function count_operation(g::G) where {G<:AbstractGraph} totalsum = 0 totalprod = 0 for node in PreOrderDFS(g) @@ -134,7 +134,7 @@ function count_operation(g::Graph) return [totalsum, totalprod] end -function count_operation(g::Array{G}) where {G<:Graph} +function count_operation(g::Vector{G}) where {G<:AbstractGraph} visited = Set{Int}() totalsum = 0 totalprod = 0 @@ -156,7 +156,7 @@ function count_operation(g::Array{G}) where {G<:Graph} end -function count_operation(g::Dict{Vector{Int},G}) where {G<:Graph} +function count_operation(g::Dict{Vector{Int},G}) where {G<:AbstractGraph} visited = Set{Int}() totalsum = 0 totalprod = 0 diff --git a/src/diagram_tree/tree.jl b/src/diagram_tree/tree.jl index 8f34f9ab..fc30a5c1 100644 --- a/src/diagram_tree/tree.jl +++ b/src/diagram_tree/tree.jl @@ -236,3 +236,40 @@ AbstractTrees.nodetype(::Diagram{W}) where {W} = Diagram{W} # (They are not sufficient to solve all internal inference issues, however.) Base.eltype(::Type{<:TreeIterator{Diagram{W}}}) where {W} = Diagram{W} Base.IteratorEltype(::Type{<:TreeIterator{Diagram{W}}}) where {W} = Base.HasEltype() + +function count_operation(g::T) where {T<:Diagram} + totalsum = 0 + totalprod = 0 + for node in PreOrderDFS(g) + #print(node.hash) + if length(node.subdiagram) > 0 + if node.operator isa Prod + totalprod += length(node.subdiagram) - 1 + elseif node.operator isa Sum + totalsum += length(node.subdiagram) - 1 + end + end + end + return [totalsum, totalprod] +end + +function count_operation(g::Vector{T}) where {T<:Diagram} + visited = Set{Int}() + totalsum = 0 + totalprod = 0 + for graph in g + for node in PreOrderDFS(graph) + if !(node.hash in visited) + push!(visited, node.hash) + if length(node.subdiagram) > 0 + if node.operator isa Prod + totalprod += length(node.subdiagram) - 1 + elseif node.operator isa Sum + totalsum += length(node.subdiagram) - 1 + end + end + end + end + end + return [totalsum, totalprod] +end diff --git a/src/utility.jl b/src/utility.jl index aa8241d9..886f519a 100644 --- a/src/utility.jl +++ b/src/utility.jl @@ -19,18 +19,28 @@ using ..Taylor """ - function taylorexpansion!(graph::G, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); taylormap::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}}()) where {G<:Graph} Return a taylor series of graph g, together with a map of between nodes of g and correponding taylor series. # Arguments: - `graph` Target graph - `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. -- `taylormap::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target graph to its correponding taylor series. +- `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}}(); taylormap::Dict{Int,TaylorSeries{G}}=Dict{Int,TaylorSeries{G}}()) where {G<:Graph} - if haskey(taylormap, graph.id) #If already exist, use taylor series in taylormap. - return taylormap[graph.id], taylormap +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. + 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,28 +58,39 @@ 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 - taylormap[graph.id] = result - return result, taylormap + to_coeff_map[graph.id] = result + return result, to_coeff_map, from_coeff_map else - taylormap[graph.id] = graph.factor * apply(graph.operator, [taylorexpansion!(sub, var_dependence; taylormap=taylormap)[1] for sub in graph.subgraphs], graph.subgraph_factors) - return taylormap[graph.id], taylormap + 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 """ - function taylorexpansion!(graph::FeynmanGraph{F,W}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); taylormap::Dict{Int,TaylorSeries{G}}=Dict{Int,TaylorSeries{G}}()) where {F,W} + function taylorexpansion!(graph::FeynmanGraph{F,W}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); to_coeff_map::Dict{Int,TaylorSeries{G}}=Dict{Int,TaylorSeries{G}}()) where {F,W} Return a taylor series of FeynmanGraph g, together with a map of between nodes of g and correponding taylor series. # Arguments: - `graph` Target FeynmanGraph - `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. -- `taylormap::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target graph to its correponding taylor series. +- `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::FeynmanGraph{F,W}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); taylormap::Dict{Int,TaylorSeries{Graph{F,W}}}=Dict{Int,TaylorSeries{Graph{F,W}}}()) where {F,W} - if haskey(taylormap, graph.id) #If already exist, use taylor series in taylormap. - return taylormap[graph.id], taylormap +function taylorexpansion!(graph::FeynmanGraph{F,W}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,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} + if haskey(to_coeff_map, graph.id) #If already exist, use taylor series in 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) @@ -83,28 +104,39 @@ function taylorexpansion!(graph::FeynmanGraph{F,W}, var_dependence::Dict{Int,Vec o = collect(order) coeff = Graph([]; operator=ComputationalGraphs.Sum(), factor=graph.factor) result.coeffs[o] = coeff + from_coeff_map[coeff.id] = (graph.id, o) end - taylormap[graph.id] = result - return result, taylormap + to_coeff_map[graph.id] = result + return result, to_coeff_map, from_coeff_map else - taylormap[graph.id] = graph.factor * apply(graph.operator, [taylorexpansion!(sub, var_dependence; taylormap=taylormap)[1] for sub in graph.subgraphs], graph.subgraph_factors) - return taylormap[graph.id], taylormap + 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 """ - function taylorexpansion!(graph::Diagram{W}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); taylormap::Dict{Int,TaylorSeries{G}}=Dict{Int,TaylorSeries{G}}()) where {W} + function taylorexpansion!(graph::Diagram{W}, var_dependence::Dict{Int,Vector{Bool}}=Dict{Int,Vector{Bool}}(); to_coeff_map::Dict{Int,TaylorSeries{G}}=Dict{Int,TaylorSeries{G}}()) where {W} Return a taylor series of Diagram g, together with a map of between nodes of g and correponding taylor series. # Arguments: - `graph` Target diagram - `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. -- `taylormap::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target diagram to its correponding taylor series. +- `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}}(); taylormap::Dict{Int,TaylorSeries{Graph{W,W}}}=Dict{Int,TaylorSeries{Graph{W,W}}}()) where {W} - if haskey(taylormap, graph.hash) #If already exist, use taylor series in taylormap. - return taylormap[graph.hash], taylormap +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. + 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) @@ -118,17 +150,18 @@ 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 - taylormap[graph.hash] = result - return result, taylormap + to_coeff_map[graph.hash] = result + return result, to_coeff_map, from_coeff_map else - taylormap[graph.hash] = graph.factor * apply(typeof(graph.operator), [taylorexpansion!(sub, var_dependence; taylormap=taylormap)[1] for sub in graph.subdiagram], ones(W, length(graph.subdiagram))) - return taylormap[graph.hash], taylormap + 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 """ - function taylorexpansion!(graph::FeynmanGraph{F,W}, propagator_var::Tuple{Vector{Bool},Vector{Bool}}, label::Tuple{LabelProduct,LabelProduct}; taylormap::Dict{Int,TaylorSeries{Graph{F,W}}}=Dict{Int,TaylorSeries{Graph{F,W}}}()) where {F,W} + function taylorexpansion!(graph::FeynmanGraph{F,W}, propagator_var::Tuple{Vector{Bool},Vector{Bool}}, label::Tuple{LabelProduct,LabelProduct}; to_coeff_map::Dict{Int,TaylorSeries{Graph{F,W}}}=Dict{Int,TaylorSeries{Graph{F,W}}}()) where {F,W} Return a taylor series of FeynmanGraph g, together with a map of between nodes of g and correponding taylor series. In this set up, the leaves that are the same type of propagators (fermi or bose) depend on the same set of variables, whereas other types of Feynman diagrams (such as vertices) depends on no variables that need to be differentiated (for AD purpose, they are just constants). @@ -137,9 +170,10 @@ end - `propagator_var::Tuple{Vector{Bool},Vector{Bool}}` A Tuple that specifies the variable dependence of fermi (first element) and bose propagator (second element). 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). -- `taylormap::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target diagram to its correponding taylor series. +- `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}}; taylormap::Dict{Int,TaylorSeries{Graph{F,W}}}=Dict{Int,TaylorSeries{Graph{F,W}}}()) where {F,W} +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}}() for leaf in Leaves(graph) if ComputationalGraphs.diagram_type(leaf) == ComputationalGraphs.Propagator @@ -153,11 +187,11 @@ function taylorexpansion!(graph::FeynmanGraph{F,W}, propagator_var::Tuple{Vector end end end - return taylorexpansion!(graph, var_dependence; taylormap=taylormap) + return taylorexpansion!(graph, var_dependence; to_coeff_map=to_coeff_map, from_coeff_map=from_coeff_map) end """ - function taylorexpansion!(graph::Diagram{W}, propagator_var::Dict{DataType,Vector{Bool}}; taylormap::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}}}()) where {W} Return a taylor series of Diagram g, together with a map of between nodes of g and correponding taylor series. In this set up, the leaves that are the same type of diagrams (such as Green functions) depend on the same set of variables. @@ -165,28 +199,36 @@ end - `graph` Target Diagram - `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. -- `taylormap::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target diagram to its correponding taylor series. +- `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}}; taylormap::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; taylormap=taylormap) + 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}}(); taylormap::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; taylormap=taylormap) + taylor, _ = taylorexpansion!(graph, var_dependence; to_coeff_map=to_coeff_map, from_coeff_map=from_coeff_map) push!(result, taylor) end - return result, taylormap + 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}}}(), 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, from_coeff_map=from_coeff_map) + push!(result, taylor) + end + 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} @@ -372,4 +414,16 @@ function count_operation(graphs::Vector{TaylorSeries{G}}) where {G<:Graph} end end +function count_operation(graphs::Vector{TaylorSeries{G}}, order::Vector{Int}) where {G<:Graph} + if length(graphs) == 0 + return [0, 0] + else + allcoeffs = Vector{G}() + for g in graphs + push!(allcoeffs, g.coeffs[order]) + end + return count_operation(allcoeffs) + end +end + end \ No newline at end of file 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])