From 0d3ce5e4b6cf674b42fb71440ccc2a0ec408e990 Mon Sep 17 00:00:00 2001 From: houpc Date: Thu, 31 Oct 2024 02:14:22 +0800 Subject: [PATCH 1/6] bugfix for remove_zero_valued_subgraphs! --- src/computational_graph/transform.jl | 7 +++++++ src/computational_graph/tree_properties.jl | 2 ++ 2 files changed, 9 insertions(+) diff --git a/src/computational_graph/transform.jl b/src/computational_graph/transform.jl index a763167b..9d2fb30e 100644 --- a/src/computational_graph/transform.jl +++ b/src/computational_graph/transform.jl @@ -399,6 +399,13 @@ function remove_zero_valued_subgraphs!(g::AbstractGraph) mask_zeros = findall(x -> x != zero(x), subg_fac) if isempty(mask_zeros) mask_zeros = [1] # retain eldest(g) if all subfactors are zero + else + if g.operator == Prod + idx = findfirst(x -> x==zero(x), subg_fac) + if !isnothing(idx) + append!(mask_zeros, idx) + end + end end set_subgraphs!(g, subg[mask_zeros]) set_subgraph_factors!(g, subg_fac[mask_zeros]) diff --git a/src/computational_graph/tree_properties.jl b/src/computational_graph/tree_properties.jl index df91a36a..aac26841 100644 --- a/src/computational_graph/tree_properties.jl +++ b/src/computational_graph/tree_properties.jl @@ -94,6 +94,8 @@ end function has_zero_subfactors(g::AbstractGraph) if isleaf(g) return false # convention: subgraph_factors = [] ⟹ subfactorless = false + elseif g.operator == Prod && 0 in subgraph_factors(g) + return true else return iszero(subgraph_factors(g)) end From 32dc86239c5eb24a4f3dc71fa0ea713f66f31de6 Mon Sep 17 00:00:00 2001 From: houpc Date: Thu, 31 Oct 2024 12:16:13 +0800 Subject: [PATCH 2/6] ignore docs/Manifest --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7e805654..f76823c2 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ docs/assets # committed for packages, but should be committed for applications that require a static # environment. Manifest.toml +docs/Manifest.toml # Ignore intermediate latex files *.aux From f448dac99a9077a47a17d72d0de112f9950db8dd Mon Sep 17 00:00:00 2001 From: houpc Date: Thu, 31 Oct 2024 12:16:23 +0800 Subject: [PATCH 3/6] ignore docs/Manifest --- docs/Manifest.toml | 97 --------------------------------- docs/src/manual/counterterms.md | 2 +- 2 files changed, 1 insertion(+), 98 deletions(-) delete mode 100644 docs/Manifest.toml diff --git a/docs/Manifest.toml b/docs/Manifest.toml deleted file mode 100644 index c0e4fbb8..00000000 --- a/docs/Manifest.toml +++ /dev/null @@ -1,97 +0,0 @@ -# This file is machine-generated - editing it directly is not advised - -[[ANSIColoredPrinters]] -git-tree-sha1 = "574baf8110975760d391c710b6341da1afa48d8c" -uuid = "a4c015fc-c6ff-483c-b24f-f7ea428134e9" -version = "0.0.1" - -[[Base64]] -uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" - -[[Dates]] -deps = ["Printf"] -uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" - -[[DocStringExtensions]] -deps = ["LibGit2"] -git-tree-sha1 = "b19534d1895d702889b219c382a6e18010797f0b" -uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.8.6" - -[[Documenter]] -deps = ["ANSIColoredPrinters", "Base64", "Dates", "DocStringExtensions", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"] -git-tree-sha1 = "f425293f7e0acaf9144de6d731772de156676233" -uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -version = "0.27.10" - -[[FeynmanDiagram]] -path = ".." -uuid = "e424a512-dbd9-41ff-9883-094748823e72" -version = "0.1.0" - -[[IOCapture]] -deps = ["Logging", "Random"] -git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a" -uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" -version = "0.2.2" - -[[InteractiveUtils]] -deps = ["Markdown"] -uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" - -[[JSON]] -deps = ["Dates", "Mmap", "Parsers", "Unicode"] -git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37" -uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" -version = "0.21.2" - -[[LibGit2]] -deps = ["Base64", "NetworkOptions", "Printf", "SHA"] -uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" - -[[Logging]] -uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" - -[[Markdown]] -deps = ["Base64"] -uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" - -[[Mmap]] -uuid = "a63ad114-7e13-5084-954f-fe012c677804" - -[[NetworkOptions]] -uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" - -[[Parsers]] -deps = ["Dates"] -git-tree-sha1 = "ae4bbcadb2906ccc085cf52ac286dc1377dceccc" -uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.1.2" - -[[Printf]] -deps = ["Unicode"] -uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" - -[[REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] -uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" - -[[Random]] -deps = ["Serialization"] -uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" - -[[SHA]] -uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" - -[[Serialization]] -uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" - -[[Sockets]] -uuid = "6462fe0b-24de-5631-8697-dd941f90decc" - -[[Test]] -deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] -uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[[Unicode]] -uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" diff --git a/docs/src/manual/counterterms.md b/docs/src/manual/counterterms.md index 12d8a72c..d1bf83a5 100644 --- a/docs/src/manual/counterterms.md +++ b/docs/src/manual/counterterms.md @@ -134,7 +134,7 @@ Since the order of differentiation w.r.t. $\mu$ and $\lambda$ does not matter, i An example of the interaction counterterm evaluation for a diagram with $n_\lambda = 3$ and $m$ interaction lines. Since the Julia implementation evaluates the interaction counterterms of a given diagram as $\frac{(-\lambda)^n}{n!}\partial^n_\lambda V^m_\lambda$, we pick up an extra factor of $l!$ on each $l$th-order derivative in the chain rule. -![An example of the representation of interaction counterterm diagrams via differentiation.](../../assets/derivative_example.svg#derivative_example) +![An example of the representation of interaction counterterm diagrams via differentiation.](../assets/derivative_example.svg) ## Benchmark of counterterms in the UEG From b8ee2a0b6de023eff241dd3a21f2174a7da3f8db Mon Sep 17 00:00:00 2001 From: houpc Date: Thu, 31 Oct 2024 14:10:53 +0800 Subject: [PATCH 4/6] fix makedocs --- docs/make.jl | 2 ++ docs/src/index.md | 1 + docs/src/lib/utility.md | 7 +++++++ docs/src/manual/feynman_rule.md | 12 ++++++------ 4 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 docs/src/lib/utility.md diff --git a/docs/make.jl b/docs/make.jl index da46915a..509da8cd 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -13,6 +13,7 @@ makedocs(; canonical="https://numericaleft.github.io/FeynmanDiagram.jl", assets=["assets/custom.css"] ), + checkdocs=:exports, # check only exported names within the modules pages=[ "Home" => "index.md", "Manual" => [ @@ -29,6 +30,7 @@ makedocs(; "lib/GV.md", "lib/parquet.md", "lib/backend.md", + "lib/utility.md" ] ] ) diff --git a/docs/src/index.md b/docs/src/index.md index 680935ee..28c9c4dc 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -23,6 +23,7 @@ Pages = [ "lib/GV.md", "lib/parquet.md", "lib/backend.md", + "lib/utility.md", ] Depth = 2 ``` diff --git a/docs/src/lib/utility.md b/docs/src/lib/utility.md new file mode 100644 index 00000000..ed5f0b0a --- /dev/null +++ b/docs/src/lib/utility.md @@ -0,0 +1,7 @@ +# Utility + +## API + +```@autodocs +Modules = [FeynmanDiagram.Utility] +``` \ No newline at end of file diff --git a/docs/src/manual/feynman_rule.md b/docs/src/manual/feynman_rule.md index d12dba4a..981225f7 100644 --- a/docs/src/manual/feynman_rule.md +++ b/docs/src/manual/feynman_rule.md @@ -81,9 +81,9 @@ G = g - g\Sigma g + g\Sigma g \Sigma g - ... ## Perturbative Expansion of the Green's Function -![Sign rule for the Wick contractions.](../../assets/diagrams/green0.svg#green0) +![Sign rule for the Wick contractions.](../assets/diagrams/green0.svg) -![Diagrammatic expansion of the Green's function.](../../assets/diagrams/green.svg#green) +![Diagrammatic expansion of the Green's function.](../assets/diagrams/green.svg) The sign of a Green's function diagram is given by ``(-1)^{n_v} \xi^{n_F}``, where @@ -95,7 +95,7 @@ The sign of a Green's function diagram is given by ``(-1)^{n_v} \xi^{n_F}``, whe From the Green's function diagrams, one can derive the __negative__ self-energy diagram, -![Diagrammatic expansion of the self-energy.](../../assets/diagrams/sigma.svg#sigma) +![Diagrammatic expansion of the self-energy.](../assets/diagrams/sigma.svg) ```math \begin{aligned} @@ -123,7 +123,7 @@ where the indices $x, y$ could be different from diagrams to diagrams, and $\Gam \Sigma_{3, x} -\Sigma^{Hartree}_{3, x} = G_{3,y} \cdot V_{3, 4} \cdot \Gamma^3_{4,y,x}, ``` -![Diagrammatic expansion of the 3-point vertex function.](../../assets/diagrams/gamma3.svg#gamma3) +![Diagrammatic expansion of the 3-point vertex function.](../assets/diagrams/gamma3.svg) The diagram weights are given by, @@ -146,7 +146,7 @@ The 4-point vertex function is related to the 3-point vertex function through an where the indices $x, y, s, t$ could be different from diagrams to diagrams. -![Diagrammatic expansion of the 4-point vertex function.](../../assets/diagrams/gamma4.svg#gamma4) +![Diagrammatic expansion of the 4-point vertex function.](../assets/diagrams/gamma4.svg) The diagram weights are given by, @@ -169,7 +169,7 @@ The susceptibility can be derived from ``\Gamma^{(4)}``. \chi_{1,2} \equiv \left<\mathcal{T} n_1 n_2\right>_{\text{connected}} = \xi G_{1,2} G_{2, 1} + \xi G_{1,s} G_{t, 1} \Gamma^{(4)}_{s, t, y, x} G_{2,y} G_{x, 2} ``` -![Diagrammatic expansion of the susceptibility.](../../assets/diagrams/susceptibility.svg#susceptibility) +![Diagrammatic expansion of the susceptibility.](../assets/diagrams/susceptibility.svg) We define the polarization ``P`` as the one-interaction irreducible (or proper) vertex function, From db67fa34dfb874ab3ab68f1cd7714a490b57deca Mon Sep 17 00:00:00 2001 From: houpc Date: Thu, 31 Oct 2024 14:51:23 +0800 Subject: [PATCH 5/6] add tests for remove_zero_valued_subgraphs --- test/computational_graph.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/computational_graph.jl b/test/computational_graph.jl index 2edb248e..c95e16ee 100644 --- a/test/computational_graph.jl +++ b/test/computational_graph.jl @@ -330,14 +330,19 @@ end sg3 = Graph([l4]; subgraph_factors=[0], operator=O2()) sg4 = Graph([l5, l6, l7]; subgraph_factors=[0, 0, 0], operator=O3()) sg5 = l8 + sg6 = Graph([l2, l3]; subgraph_factors=[1.0, 0.0], operator=Graphs.Prod()) # graphs g = Graph([sg1, sg2, sg3, sg4, sg5]; subgraph_factors=[1, 1, 1, 1, 0], operator=O()) g_test = Graph([sg1, sg2]; subgraph_factors=[1, 1], operator=O()) + g1 = Graph([sg1, sg2, sg3, sg4, sg5, sg6]; subgraph_factors=[1, 1, 1, 1, 0, 2], operator=Graphs.Sum()) + g1_test = Graph([sg1, sg2]; subgraph_factors=[1, 1], operator=Graphs.Sum()) gp = Graph([sg3, sg4, sg5]; subgraph_factors=[1, 1, 0], operator=O()) gp_test = Graph([sg3]; subgraph_factors=[0], operator=O()) Graphs.remove_zero_valued_subgraphs!(g) + Graphs.remove_zero_valued_subgraphs!(g1) Graphs.remove_zero_valued_subgraphs!(gp) @test isequiv(g, g_test, :id) + @test isequiv(g1, g1_test, :id) @test isequiv(gp, gp_test, :id) end end @@ -387,14 +392,19 @@ end sg3 = Graph([l4]; subgraph_factors=[0], operator=O2()) sg4 = Graph([l5, l6, ssg1]; subgraph_factors=[0, 0, 1], operator=O3()) sg5 = l8 + sg6 = Graph([l2, sg3]; subgraph_factors=[1.0, 2.0], operator=Graphs.Prod()) # graphs g = Graph([sg1, sg2, sg3, sg4, sg5]; subgraph_factors=[1, 1, 1, 1, 0], operator=O()) g_test = Graph([sg1, sg2_test]; subgraph_factors=[1, 1], operator=O()) + g1 = Graph([sg1, sg2, sg3, sg4, sg5, sg6]; subgraph_factors=[1, 1, 1, 1, 0, -1], operator=Graphs.Sum()) + g1_test = Graph([sg1, sg2_test]; subgraph_factors=[1, 1], operator=Graphs.Sum()) gp = Graph([sg3, sg4, sg5]; subgraph_factors=[1, 1, 0], operator=O()) gp_test = Graph([sg3]; subgraph_factors=[0], operator=O()) Graphs.remove_all_zero_valued_subgraphs!(g) + Graphs.remove_all_zero_valued_subgraphs!(g1) Graphs.remove_all_zero_valued_subgraphs!(gp) @test isequiv(g, g_test, :id) + @test isequiv(g1, g1_test, :id) @test isequiv(gp, gp_test, :id) end @testset "Merge all linear combinations" begin From 391fd5c041d4e450cebed2c0337e6380d80bcfb4 Mon Sep 17 00:00:00 2001 From: houpc Date: Thu, 31 Oct 2024 21:16:42 +0800 Subject: [PATCH 6/6] udpate mask_zero_subgraph_factors and has_zero_subfactors with multiple dispatch --- src/computational_graph/feynmangraph.jl | 2 + src/computational_graph/graph.jl | 2 + src/computational_graph/transform.jl | 59 ++++++++++++++---- src/computational_graph/tree_properties.jl | 41 ++++++++---- test/computational_graph.jl | 72 ++++++++++++++++------ 5 files changed, 131 insertions(+), 45 deletions(-) diff --git a/src/computational_graph/feynmangraph.jl b/src/computational_graph/feynmangraph.jl index 33874783..94212a1f 100644 --- a/src/computational_graph/feynmangraph.jl +++ b/src/computational_graph/feynmangraph.jl @@ -111,6 +111,8 @@ mutable struct FeynmanGraph{F<:Number,W} <: AbstractGraph # FeynmanGraph @assert length(external_indices) == length(external_legs) if typeof(operator) <: Power @assert length(subgraphs) == 1 "FeynmanGraph with Power operator must have one and only one subgraph." + elseif typeof(operator) <: Unitary + @assert length(subgraphs) == 0 "FeynmanGraph with Unitary operator must have no subgraphs." end # @assert allunique(subgraphs) "all subgraphs must be distinct." if isnothing(vertices) diff --git a/src/computational_graph/graph.jl b/src/computational_graph/graph.jl index 7a3e94e8..c72154d3 100644 --- a/src/computational_graph/graph.jl +++ b/src/computational_graph/graph.jl @@ -60,6 +60,8 @@ mutable struct Graph{F<:Number,W} <: AbstractGraph # Graph ) if typeof(operator) <: Power @assert length(subgraphs) == 1 "Graph with Power operator must have one and only one subgraph." + elseif typeof(operator) <: Unitary + @assert length(subgraphs) == 0 "Graph with Unitary operator must have no subgraphs." end # @assert allunique(subgraphs) "all subgraphs must be distinct." g = new{ftype,wtype}(uid(), String(name), orders, subgraphs, subgraph_factors, typeof(operator), weight, properties) diff --git a/src/computational_graph/transform.jl b/src/computational_graph/transform.jl index 9d2fb30e..e3c36d51 100644 --- a/src/computational_graph/transform.jl +++ b/src/computational_graph/transform.jl @@ -374,6 +374,47 @@ end """ flatten_chains(g::AbstractGraph) = flatten_chains!(deepcopy(g)) +""" + function mask_zero_subgraph_factors(operator::Type{<:AbstractOperator}, subg_fac::Vector{F}) where {F} + + Returns a list of indices that should be considered when performing the operation (e.g., Sum, Prod, Power), effectively masking out zero values as appropriate. + + The behavior of the function depends on the operator type: + - `Sum`: Returns all indices that are not equal to zero. + - `Prod`: Returns the index of the first zero value, or all indices if none are found. + - `Power`: Returns `[1]`, or error if the power is negative. + - Other `AbstractOperator`: Defaults to return all indices. +""" +function mask_zero_subgraph_factors(::Type{Sum}, subg_fac::Vector{F}) where {F} + mask_zeros = findall(x -> x != zero(x), subg_fac) + if isempty(mask_zeros) + mask_zeros = [1] + end + return mask_zeros +end +function mask_zero_subgraph_factors(::Type{Prod}, subg_fac::Vector{F}) where {F} + idx = findfirst(x -> x == zero(x), subg_fac) + if isnothing(idx) + mask_zeros = eachindex(subg_fac) + else + mask_zeros = [idx] + end + return mask_zeros +end +function mask_zero_subgraph_factors(::Type{Power{N}}, subg_fac::Vector{F}) where {N,F} + if N >= 0 + return [1] + else + error("0^$N is illegal!") + end +end +function mask_zero_subgraph_factors(::Type{<:AbstractOperator}, subg_fac::Vector{F}) where {F} + @info("Masking zero-valued subgraphs when the node operator is $operator is not implemented. Defaulted to no mask! \n" * + "It's better to define a method `mask_zero_subgraph_factors(operator::Type, subg_fac::Vector{F})`." + ) + return eachindex(subg_fac) +end + """ function remove_zero_valued_subgraphs!(g::AbstractGraph) @@ -391,22 +432,16 @@ function remove_zero_valued_subgraphs!(g::AbstractGraph) zero_sgf = zero(subg_fac[1]) # F(0) # Find subgraphs with all-zero subgraph_factors and propagate subfactor one level up for (i, sub_g) in enumerate(subg) - if has_zero_subfactors(sub_g) + if isleaf(sub_g) + continue + end + if has_zero_subfactors(sub_g, sub_g.operator) subg_fac[i] = zero_sgf end end + # Remove marked zero subgraph factor subgraph(s) of g - mask_zeros = findall(x -> x != zero(x), subg_fac) - if isempty(mask_zeros) - mask_zeros = [1] # retain eldest(g) if all subfactors are zero - else - if g.operator == Prod - idx = findfirst(x -> x==zero(x), subg_fac) - if !isnothing(idx) - append!(mask_zeros, idx) - end - end - end + mask_zeros = mask_zero_subgraph_factors(g.operator, subg_fac) set_subgraphs!(g, subg[mask_zeros]) set_subgraph_factors!(g, subg_fac[mask_zeros]) return g diff --git a/src/computational_graph/tree_properties.jl b/src/computational_graph/tree_properties.jl index aac26841..5c41159b 100644 --- a/src/computational_graph/tree_properties.jl +++ b/src/computational_graph/tree_properties.jl @@ -81,24 +81,39 @@ function ischain(g::AbstractGraph) end """ - function has_zero_subfactors(g) + function has_zero_subfactors(g::AbstractGraph, operator_type::Type{<:AbstractOperator}) - Returns whether the graph g has only zero-valued subgraph factor(s). - Note that this function does not recurse through subgraphs of g, so that one may have, e.g., - `has_zero_subfactors(g) == true` but `has_zero_subfactors(eldest(g)) == false`. - By convention, returns `false` if g is a leaf. + Determines whether the graph `g` has only zero-valued subgraph factors based on the specified operator type. + This function does not recurse through the subgraphs of `g`, so it only checks the immediate subgraph factors. + If `g` is a leaf (i.e., has no subgraphs), the function returns `false` by convention. + The behavior of the function depends on the operator type: + - `Sum`: Checks if all subgraph factors are zero. + - `Prod`: Checks if any subgraph factor is zero. + - `Power{N}`: Checks if the first subgraph factor is zero. + - Other `AbstractOperator`: Defaults to return `false`. # Arguments: - `g::AbstractGraph`: graph to be analyzed +- `operator`: the operator used in graph `g` """ -function has_zero_subfactors(g::AbstractGraph) - if isleaf(g) - return false # convention: subgraph_factors = [] ⟹ subfactorless = false - elseif g.operator == Prod && 0 in subgraph_factors(g) - return true - else - return iszero(subgraph_factors(g)) - end +function has_zero_subfactors(g::AbstractGraph, ::Type{Sum}) + @assert g.operator == Sum "Operator must be Sum" + return iszero(subgraph_factors(g)) +end + +function has_zero_subfactors(g::AbstractGraph, ::Type{Prod}) + @assert g.operator == Prod "Operator must be Prod" + return 0 in subgraph_factors(g) +end + +function has_zero_subfactors(g::AbstractGraph, ::Type{Power{N}}) where {N} + @assert g.operator <: Power "Operator must be a Power" + return iszero(subgraph_factors(g)[1]) +end + +function has_zero_subfactors(g::AbstractGraph, ::Type{<:AbstractOperator}) + @info "has_zero_subfactors: Operator type $operator is not specifically defined. Defaults to return false." + return false end """ diff --git a/test/computational_graph.jl b/test/computational_graph.jl index c95e16ee..e4e34e8b 100644 --- a/test/computational_graph.jl +++ b/test/computational_graph.jl @@ -324,25 +324,40 @@ end l6 = Graph([]; factor=6) l7 = Graph([]; factor=7) l8 = Graph([]; factor=8) + l2_test = Graph([]; factor=2) + Graphs.remove_zero_valued_subgraphs(l2) + @test isequiv(l2, l2_test, :id) # subgraphs sg1 = l1 - sg2 = Graph([l2, l3]; subgraph_factors=[1.0, 0.0], operator=O1()) - sg3 = Graph([l4]; subgraph_factors=[0], operator=O2()) - sg4 = Graph([l5, l6, l7]; subgraph_factors=[0, 0, 0], operator=O3()) + sg2 = Graph([l2, l3]; subgraph_factors=[1.0, 0.0], operator=Graphs.Sum()) + sg2_test = Graph([l2]; subgraph_factors=[1.0], operator=Graphs.Sum()) + sg3 = Graph([l4]; subgraph_factors=[0], operator=Graphs.Power(2)) + sg3_test = Graph([l4]; subgraph_factors=[0], operator=Graphs.Power(2)) + sg4 = Graph([l5, l6, l7]; subgraph_factors=[0, 0, 0], operator=Graphs.Sum()) sg5 = l8 sg6 = Graph([l2, l3]; subgraph_factors=[1.0, 0.0], operator=Graphs.Prod()) + sg6c = deepcopy(sg6) + sg6c_test = Graph([l3]; subgraph_factors=[0.0], operator=Graphs.Prod()) + Graphs.remove_zero_valued_subgraphs!(sg2) + Graphs.remove_zero_valued_subgraphs!(sg3) + @test isequiv(sg2, sg2_test, :id) + @test isequiv(sg3, sg3_test, :id) + @test isequiv(sg6, sg6c, :id) # graphs - g = Graph([sg1, sg2, sg3, sg4, sg5]; subgraph_factors=[1, 1, 1, 1, 0], operator=O()) - g_test = Graph([sg1, sg2]; subgraph_factors=[1, 1], operator=O()) + g = Graph([sg1, sg2, sg3, sg4, sg5]; subgraph_factors=[1, 1, 1, 1, 0], operator=Graphs.Sum()) + g_test = Graph([sg1, sg2]; subgraph_factors=[1, 1], operator=Graphs.Sum()) g1 = Graph([sg1, sg2, sg3, sg4, sg5, sg6]; subgraph_factors=[1, 1, 1, 1, 0, 2], operator=Graphs.Sum()) g1_test = Graph([sg1, sg2]; subgraph_factors=[1, 1], operator=Graphs.Sum()) - gp = Graph([sg3, sg4, sg5]; subgraph_factors=[1, 1, 0], operator=O()) - gp_test = Graph([sg3]; subgraph_factors=[0], operator=O()) + g2 = Graph([sg1, sg2, sg3, sg4, sg5, sg6]; subgraph_factors=[1, 1, 1, 1, 0, 2], operator=O1()) + g2_test = Graph([sg1, sg2, sg3, sg4, sg5, sg6]; subgraph_factors=[1, 1, 1, 1, 0, 2], operator=O1()) + gp = Graph([sg3, sg4, sg5]; subgraph_factors=[1, 1, 0], operator=Graphs.Sum()) + gp_test = Graph([sg3]; subgraph_factors=[0], operator=Graphs.Sum()) Graphs.remove_zero_valued_subgraphs!(g) Graphs.remove_zero_valued_subgraphs!(g1) Graphs.remove_zero_valued_subgraphs!(gp) @test isequiv(g, g_test, :id) @test isequiv(g1, g1_test, :id) + @test isequiv(g2, g2_test, :id) @test isequiv(gp, gp_test, :id) end end @@ -387,24 +402,32 @@ end ssg1 = Graph([l7]; subgraph_factors=[0], operator=O()) # subgraphs sg1 = l1 - sg2 = Graph([l2, l3]; subgraph_factors=[1.0, 0.0], operator=O1()) - sg2_test = Graph([l2]; subgraph_factors=[1.0], operator=O1()) - sg3 = Graph([l4]; subgraph_factors=[0], operator=O2()) - sg4 = Graph([l5, l6, ssg1]; subgraph_factors=[0, 0, 1], operator=O3()) + sg2 = Graph([l2, l3]; subgraph_factors=[1.0, 0.0], operator=Graphs.Sum()) + sg2c = deepcopy(sg2) + sg2_test = Graph([l2]; subgraph_factors=[1.0], operator=Graphs.Sum()) + sg3 = Graph([l4]; subgraph_factors=[0], operator=Graphs.Sum()) + sg4 = Graph([l5, l6, ssg1]; subgraph_factors=[0, 0, 3], operator=Graphs.Sum()) + sg4c = deepcopy(sg4) + sg4_test = Graph([ssg1], subgraph_factors=[3], operator=Graphs.Sum()) sg5 = l8 sg6 = Graph([l2, sg3]; subgraph_factors=[1.0, 2.0], operator=Graphs.Prod()) # graphs - g = Graph([sg1, sg2, sg3, sg4, sg5]; subgraph_factors=[1, 1, 1, 1, 0], operator=O()) - g_test = Graph([sg1, sg2_test]; subgraph_factors=[1, 1], operator=O()) + g = Graph([sg1, sg2, sg3, sg4, sg5]; subgraph_factors=[1, 1, 1, 1, 0], operator=Graphs.Sum()) + g_test = Graph([sg1, sg2_test, sg4_test]; subgraph_factors=[1, 1, 1], operator=Graphs.Sum()) g1 = Graph([sg1, sg2, sg3, sg4, sg5, sg6]; subgraph_factors=[1, 1, 1, 1, 0, -1], operator=Graphs.Sum()) - g1_test = Graph([sg1, sg2_test]; subgraph_factors=[1, 1], operator=Graphs.Sum()) - gp = Graph([sg3, sg4, sg5]; subgraph_factors=[1, 1, 0], operator=O()) - gp_test = Graph([sg3]; subgraph_factors=[0], operator=O()) + g1_test = Graph([sg1, sg2_test, sg4_test]; subgraph_factors=[1, 1, 1], operator=Graphs.Sum()) + + g2 = Graph([sg1, sg2c, sg3, sg4c, sg5, sg6]; subgraph_factors=[1, 0, 1, 1, 0, -1], operator=O1()) + g2_test = Graph([sg1, sg2_test, sg3, sg4_test, sg5, sg6]; subgraph_factors=[1, 0, 0, 1, 0, 0], operator=O1()) + gp = Graph([sg3, sg4, sg5]; subgraph_factors=[1, 0, 0], operator=Graphs.Sum()) + gp_test = Graph([sg3]; subgraph_factors=[0], operator=Graphs.Sum()) Graphs.remove_all_zero_valued_subgraphs!(g) Graphs.remove_all_zero_valued_subgraphs!(g1) + Graphs.remove_all_zero_valued_subgraphs!(g2) Graphs.remove_all_zero_valued_subgraphs!(gp) @test isequiv(g, g_test, :id) @test isequiv(g1, g1_test, :id) + @test isequiv(g2, g2_test, :id) @test isequiv(gp, gp_test, :id) end @testset "Merge all linear combinations" begin @@ -1050,7 +1073,8 @@ end @testset verbose = true "Tree properties" begin using FeynmanDiagram.ComputationalGraphs: - haschildren, onechild, isleaf, isbranch, ischain, eldest, count_operation + haschildren, onechild, isleaf, isbranch, ischain, eldest, count_operation, has_zero_subfactors + # Leaves: gᵢ g1 = Graph([]) g2 = Graph([], factor=2) @@ -1068,6 +1092,8 @@ end g10 = g1 * g2 + g8 * g9 h2 = Graph([g1, g2]; subgraph_factors=[0, 0], operator=Graphs.Sum()) h3 = Graph([g1, g2]; subgraph_factors=[1, 0], operator=Graphs.Sum()) + h4 = Graph([g1]; subgraph_factors=[0], operator=Graphs.Power(2)) + h5 = Graph([g1, g2]; subgraph_factors=[0, 0], operator=O()) glist = [g1, g2, g8, g9, g10] @testset "Leaves" begin @@ -1087,7 +1113,7 @@ end @test isbranch(g3) @test ischain(g3) @test isleaf(eldest(g3)) - @test has_zero_subfactors(h1) + @test has_zero_subfactors(h1, h1.operator) end @testset "Chains" begin @test haschildren(g6) @@ -1107,8 +1133,14 @@ end @test count_operation(g8) == [1, 0] @test count_operation(g9) == [2, 0] @test count_operation(g10) == [4, 2] - @test has_zero_subfactors(h2) - @test has_zero_subfactors(h3) == false + @test has_zero_subfactors(h2, h2.operator) + @test has_zero_subfactors(h3, h3.operator) == false + @test has_zero_subfactors(h4, h4.operator) + @test has_zero_subfactors(h5, h5.operator) == false + function FeynmanDiagram.has_zero_subfactors(g::AbstractGraph, ::Type{O}) + return iszero(g.subgraph_factors) + end + @test has_zero_subfactors(h5, h5.operator) end @testset "Iteration" begin count_pre = sum(1 for node in PreOrderDFS(g9))