From 664434fb745e4c8f88b11514783866dfcb4c23de Mon Sep 17 00:00:00 2001 From: dcerkoney Date: Mon, 9 Oct 2023 20:01:31 -0400 Subject: [PATCH] Add back orders & remove unneeded parametric types --- src/backend/static.jl | 22 +++++------ src/computational_graph/abstractgraph.jl | 6 +-- src/computational_graph/feynmangraph.jl | 48 ++++++++++++------------ src/computational_graph/graph.jl | 32 ++++++++++++---- src/computational_graph/io.jl | 19 +++++----- src/computational_graph/optimize.jl | 26 ++++++------- src/quantum_operator/expression.jl | 2 +- test/computational_graph.jl | 2 - 8 files changed, 85 insertions(+), 72 deletions(-) diff --git a/src/backend/static.jl b/src/backend/static.jl index cae6b85f..003fc07d 100644 --- a/src/backend/static.jl +++ b/src/backend/static.jl @@ -31,12 +31,12 @@ function _to_static(::Type{ComputationalGraphs.Prod}, subgraphs::Vector{FeynmanG end """ - function to_julia_str(graphs::AbstractVector{G}; root::AbstractVector{Int}=[g.id for g in graphs], name::String="eval_graph!") where {G<:AbstractGraph} + function to_julia_str(graphs::AbstractVector{<:AbstractGraph}; root::AbstractVector{Int}=[g.id for g in graphs], name::String="eval_graph!") Compile a list of graphs into a string for a julia static function. The function takes two arguments: `root` and `leaf`. `root` is a vector of the root node ids of the graphs, and `leaf` is a vector of the leaf nodes' weights of the graphs. """ -function to_julia_str(graphs::AbstractVector{G}; root::AbstractVector{Int}=[g.id for g in graphs], name::String="eval_graph!") where {G<:AbstractGraph} +function to_julia_str(graphs::AbstractVector{<:AbstractGraph}; root::AbstractVector{Int}=[g.id for g in graphs], name::String="eval_graph!") head = "function $name(root::AbstractVector, leaf::AbstractVector)\n " body = "" leafidx = 1 @@ -60,8 +60,8 @@ function to_julia_str(graphs::AbstractVector{G}; root::AbstractVector{Int}=[g.id end """ - function to_julia_str(graphs::AbstractVector{G}, leafMap::Dict{Int,Int}; root::AbstractVector{Int}=[g.id for g in graphs], - name::String="eval_graph!") where {G<:AbstractGraph} + function to_julia_str(graphs::AbstractVector{<:AbstractGraph}, leafMap::Dict{Int,Int}; root::AbstractVector{Int}=[g.id for g in graphs], + name::String="eval_graph!") Compile a list of Feynman graphs into a string for a julia static function. The complied function takes two arguments: `root` and `leafVal`. `root` is a vector of the root node ids of the graphs, and `leafVal` is a vector of the leaf nodes' weights of the graphs. @@ -72,8 +72,8 @@ Compile a list of Feynman graphs into a string for a julia static function. The - `root` (AbstractVector{Int}, optional): The vector of the root node ids of the graphs (defaults to `[g.id for g in graphs]`). - `name` (String,optional): The name of the complied function (defaults to `"eval_graph!"`). """ -function to_julia_str(graphs::AbstractVector{G}, leafMap::Dict{Int,Int}; root::AbstractVector{Int}=[g.id for g in graphs], - name::String="eval_graph!") where {G<:AbstractGraph} +function to_julia_str(graphs::AbstractVector{<:AbstractGraph}, leafMap::Dict{Int,Int}; root::AbstractVector{Int}=[g.id for g in graphs], + name::String="eval_graph!") head = "function $name(root::AbstractVector, leafVal::AbstractVector)\n " body = "" for graph in graphs @@ -97,7 +97,7 @@ function to_julia_str(graphs::AbstractVector{G}, leafMap::Dict{Int,Int}; root::A end """ - function compile(graphs::AbstractVector{G}; root::AbstractVector{Int}=[g.id for g in graphs]) where {G<:AbstractGraph} + function compile(graphs::AbstractVector{<:AbstractGraph}; root::AbstractVector{Int}=[g.id for g in graphs]) Compile a list of graphs into a julia static function. The function takes two arguments: `root` and `leaf`. `root` is a vector of the root node ids of the graphs, and `leaf` is a vector of the leaf node ids of the graphs. @@ -118,16 +118,16 @@ leaf = [1.0, 2.0] @assert eval_graph!(root, leaf) ≈ (leaf[1] + leaf[2]) * factor ``` """ -function compile(graphs::AbstractVector{G}; - root::AbstractVector{Int}=[g.id for g in graphs]) where {G<:AbstractGraph} +function compile(graphs::AbstractVector{<:AbstractGraph}; + root::AbstractVector{Int}=[g.id for g in graphs]) # this function return a runtime generated function defined by compile() func_string = to_julia_str(graphs; root=root, name="func_name!") func_expr = Meta.parse(func_string) return @RuntimeGeneratedFunction(func_expr) end -function compile(graphs::AbstractVector{G}, leafMap::Dict{Int,Int}; - root::AbstractVector{Int}=[g.id for g in graphs]) where {G<:AbstractGraph} +function compile(graphs::AbstractVector{<:AbstractGraph}, leafMap::Dict{Int,Int}; + root::AbstractVector{Int}=[g.id for g in graphs]) # this function return a runtime generated function defined by compile() func_string = to_julia_str(graphs, leafMap; root=root, name="func_name!") func_expr = Meta.parse(func_string) diff --git a/src/computational_graph/abstractgraph.jl b/src/computational_graph/abstractgraph.jl index 1cb5d800..ca9a05c9 100644 --- a/src/computational_graph/abstractgraph.jl +++ b/src/computational_graph/abstractgraph.jl @@ -14,11 +14,11 @@ Base.show(io::IO, ::Type{Prod}) = print(io, "Ⓧ") # Is the unary form of operator 𝓞 trivial: 𝓞(G) ≡ G? # NOTE: this property implies that 𝓞(c * G) = c * G = c * 𝓞(G), so # we may propagate the subgraph factor c up to the parent graph. -unary_istrivial(::Type{O}) where {O<:AbstractOperator} = false -unary_istrivial(::Type{O}) where {O<:Union{Sum,Prod}} = true # (+g) ≡ g and (*g) ≡ g +unary_istrivial(::Type{<:AbstractOperator}) = false +unary_istrivial(::Type{<:Union{Sum,Prod}}) = true # (+g) ≡ g and (*g) ≡ g # Is the operation associative: a 𝓞 (b 𝓞 c) = (a 𝓞 b) 𝓞 c = a 𝓞 b 𝓞 c? -isassociative(::Type{O}) where {O<:AbstractOperator} = false +isassociative(::Type{<:AbstractOperator}) = false isassociative(::Type{Sum}) = true # NOTE: Associativity of Prod (graph composition) # requires Base.*(g1, g2) and Base./(g1, g2) diff --git a/src/computational_graph/feynmangraph.jl b/src/computational_graph/feynmangraph.jl index 4d275a76..ccbf6f8f 100644 --- a/src/computational_graph/feynmangraph.jl +++ b/src/computational_graph/feynmangraph.jl @@ -14,7 +14,6 @@ struct GenericDiag <: DiagramType end # Members: - `diagtype::DataType` classification of the Feynman diagram. Should be one of the following supported DiagramTypes: Interaction, ExternalVertex, Propagator, SelfEnergy, VertexDiag, GreenDiag, or GenericDiag. -- `orders::Vector{Int}` orders of the diagram, e.g. loop order, derivative order, etc. - `vertices::Vector{OperatorProduct}` vertices of the diagram. Each index is composited by the product of quantum operators. - `topology::Vector{Vector{Int}}` topology of the diagram. Each Vector{Int} stores vertices' index connected with each other (as a propagator). - `external_indices::Vector{Int}` indices of actual external vertices in terms of QuantumOperators @@ -23,7 +22,6 @@ struct GenericDiag <: DiagramType end # TODO: add additional properties, e.g., isconnected::Bool and isreducible::Bool mutable struct FeynmanProperties diagtype::DataType # :propagator, :interaction, :sigma, :green, :generic, ... - orders::Vector{Int} vertices::Vector{OperatorProduct} topology::Vector{Vector{Int}} external_indices::Vector{Int} @@ -43,7 +41,7 @@ Base.:(==)(a::FeynmanProperties, b::FeynmanProperties) = Base.isequal(a, b) Returns a copy of the given FeynmanProperties `p` modified to have no topology. """ -drop_topology(p::FeynmanProperties) = FeynmanProperties(p.diagtype, p.orders, p.vertices, [], p.external_indices, p.external_legs) +drop_topology(p::FeynmanProperties) = FeynmanProperties(p.diagtype, p.vertices, [], p.external_indices, p.external_legs) """ mutable struct FeynmanGraph{F,W} @@ -53,6 +51,7 @@ drop_topology(p::FeynmanProperties) = FeynmanProperties(p.diagtype, p.orders, p. # Members: - `id::Int` the unique hash id to identify the diagram - `name::Symbol` name of the diagram +- `orders::Vector{Int}` orders associated with the Feynman graph, e.g., loop/derivative orders - `properties::FeynmanProperties` diagrammatic properties, e.g., the operator vertices and topology - `subgraphs::Vector{FeynmanGraph{F,W}}` vector of sub-diagrams - `subgraph_factors::Vector{F}` scalar multiplicative factors associated with each subdiagram @@ -75,6 +74,7 @@ julia> g = FeynmanGraph([g1,g2]; vertices=[𝑓⁺(1),𝑓⁻(2),𝑓⁺(3),𝑓 mutable struct FeynmanGraph{F,W} <: AbstractGraph # FeynmanGraph id::Int name::String # "" by default + orders::Vector{Int} properties::FeynmanProperties subgraphs::Vector{FeynmanGraph{F,W}} @@ -101,7 +101,7 @@ mutable struct FeynmanGraph{F,W} <: AbstractGraph # FeynmanGraph - `name` name of the diagram - `diagtype::DiagramType` type of the diagram - `operator::AbstractOperator` node operation, Sum, Prod, etc. - - `orders` orders of the diagram + - `orders` orders associated with the Feynman graph, e.g., loop/derivative orders - `ftype` typeof(factor) - `wtype` typeof(weight) - `factor` overall scalar multiplicative factor for this diagram (e.g., permutation sign) @@ -115,8 +115,8 @@ mutable struct FeynmanGraph{F,W} <: AbstractGraph # FeynmanGraph if isnothing(vertices) vertices = [external_operators(g) for g in subgraphs if diagram_type(g) != Propagator] end - properties = FeynmanProperties(typeof(diagtype), orders, vertices, topology, external_indices, external_legs) - return new{ftype,wtype}(uid(), name, properties, subgraphs, subgraph_factors, typeof(operator), factor, weight) + properties = FeynmanProperties(typeof(diagtype), vertices, topology, external_indices, external_legs) + return new{ftype,wtype}(uid(), name, orders, properties, subgraphs, subgraph_factors, typeof(operator), factor, weight) end """ @@ -139,10 +139,10 @@ mutable struct FeynmanGraph{F,W} <: AbstractGraph # FeynmanGraph """ function FeynmanGraph(subgraphs::AbstractVector, properties::FeynmanProperties; subgraph_factors=one.(eachindex(subgraphs)), name="", operator::AbstractOperator=Sum(), - ftype=_dtype.factor, wtype=_dtype.weight, factor=one(ftype), weight=zero(wtype) + orders=zeros(Int, 16), ftype=_dtype.factor, wtype=_dtype.weight, factor=one(ftype), weight=zero(wtype) ) @assert length(properties.external_indices) == length(properties.external_legs) - return new{ftype,wtype}(uid(), name, properties, subgraphs, subgraph_factors, typeof(operator), factor, weight) + return new{ftype,wtype}(uid(), name, orders, properties, subgraphs, subgraph_factors, typeof(operator), factor, weight) end end @@ -163,56 +163,56 @@ is_internal(g::FeynmanGraph, i::Int) = (i in g.properties.external_indices) == f """ function diagram_type(g::FeynmanGraph) - Return the diagram type (::DiagramType) of FeynmanGraph `g`. + Returns the diagram type (::DiagramType) of FeynmanGraph `g`. """ diagram_type(g::FeynmanGraph) = g.properties.diagtype """ function orders(g::FeynmanGraph) - Return the derivative orders (::Vector{Int}) of FeynmanGraph `g`. + Returns the loop/derivative orders (::Vector{Int}) of FeynmanGraph `g`. """ -orders(g::FeynmanGraph) = g.properties.orders +orders(g::FeynmanGraph) = g.orders """ function vertices(g::FeynmanGraph) - Return all vertices (::Vector{OperatorProduct}) of FeynmanGraph `g`. + Returns all vertices (::Vector{OperatorProduct}) of FeynmanGraph `g`. """ vertices(g::FeynmanGraph) = g.properties.vertices """ function topology(g::FeynmanGraph) - Return the topology (::Vector{Vector{Int}}) of FeynmanGraph `g`. + Returns the topology (::Vector{Vector{Int}}) of FeynmanGraph `g`. """ topology(g::FeynmanGraph) = g.properties.topology """ function external_legs(g::FeynmanGraph) - Return a list of Boolean indices external_legs (::Vector{Bool}) indicating which external vertices of FeynmanGraph `g` have real legs (true: real leg, false: fake leg). + Returns a list of Boolean indices external_legs (::Vector{Bool}) indicating which external vertices of FeynmanGraph `g` have real legs (true: real leg, false: fake leg). """ external_legs(g::FeynmanGraph) = g.properties.external_legs """ function external_indices(g::FeynmanGraph) - Return a list of indices (::Vector{Int}}) to the external vertices of the FeynmanGraph `g`. + Returns a list of indices (::Vector{Int}}) to the external vertices of the FeynmanGraph `g`. """ external_indices(g::FeynmanGraph) = g.properties.external_indices """ function external_operators(g::FeynmanGraph) - Return all physical external operators (::OperatorProduct}) of FeynmanGraph `g`. + Returns all physical external operators (::OperatorProduct}) of FeynmanGraph `g`. """ external_operators(g::FeynmanGraph) = OperatorProduct(OperatorProduct(g.properties.vertices)[g.properties.external_indices]) """ function external_labels(g::FeynmanGraph) - Return the labels of all physical external vertices of FeynmanGraph `g`. + Returns the labels of all physical external vertices of FeynmanGraph `g`. """ external_labels(g::FeynmanGraph) = [o.label for o in external_operators(g)] @@ -238,7 +238,7 @@ end - `c2` scalar multiple """ function Base.:*(g1::FeynmanGraph{F,W}, c2::C) where {F,W,C} - g = FeynmanGraph([g1,], g1.properties; subgraph_factors=[F(c2),], operator=Prod(), ftype=F, wtype=W) + g = FeynmanGraph([g1,], g1.properties; subgraph_factors=[F(c2),], operator=Prod(), orders=orders(g1), ftype=F, wtype=W) # Merge multiplicative link if g1.operator == Prod && onechild(g1) g.subgraph_factors[1] *= g1.subgraph_factors[1] @@ -257,7 +257,7 @@ end - `g2` Feynman graph """ function Base.:*(c1::C, g2::FeynmanGraph{F,W}) where {F,W,C} - g = FeynmanGraph([g2,], g2.properties; subgraph_factors=[F(c1),], operator=Prod(), ftype=F, wtype=W) + g = FeynmanGraph([g2,], g2.properties; subgraph_factors=[F(c1),], operator=Prod(), orders=orders(g2), ftype=F, wtype=W) # Merge multiplicative link if g2.operator == Prod && onechild(g2) g.subgraph_factors[1] *= g2.subgraph_factors[1] @@ -282,8 +282,8 @@ function linear_combination(g1::FeynmanGraph{F,W}, g2::FeynmanGraph{F,W}, c1::C, @assert Set(external_operators(g1)) == Set(external_operators(g2)) "g1 and g2 have different external vertices." empty_topology = [] # No topology for Sum nodes total_vertices = union(vertices(g1), vertices(g2)) - properties = FeynmanProperties(diagram_type(g1), orders(g1), total_vertices, empty_topology, external_indices(g1), external_legs(g1)) - g = FeynmanGraph([g1, g2], properties; subgraph_factors=[F(c1), F(c2)], operator=Sum(), ftype=F, wtype=W) + properties = FeynmanProperties(diagram_type(g1), total_vertices, empty_topology, external_indices(g1), external_legs(g1)) + g = FeynmanGraph([g1, g2], properties; subgraph_factors=[F(c1), F(c2)], operator=Sum(), orders=orders(g1), ftype=F, wtype=W) # Convert multiplicative links to in-place form if g1.operator == Prod && onechild(g1) g.subgraph_factors[1] *= g1.subgraph_factors[1] @@ -301,7 +301,7 @@ end Given a vector 𝐠 of graphs each with the same type and external/internal vertices and an equally-sized vector 𝐜 of constants, returns a new - graph representing the linear combination (𝐜 ⋅ 𝐠). All input Graphs + graph representing the linear combination (𝐜 ⋅ 𝐠). All input Feynman graphs must have the same diagram type, orders, and external vertices. # Arguments: @@ -315,8 +315,8 @@ function linear_combination(graphs::Vector{FeynmanGraph{F,W}}, constants::Vector g1 = graphs[1] empty_topology = [] # No topology for Sum nodes total_vertices = union(Iterators.flatten(vertices.(graphs))) - properties = FeynmanProperties(diagram_type(g1), orders(g1), total_vertices, empty_topology, external_indices(g1), external_legs(g1)) - g = FeynmanGraph(graphs, properties; subgraph_factors=constants, operator=Sum(), ftype=F, wtype=W) + properties = FeynmanProperties(diagram_type(g1), total_vertices, empty_topology, external_indices(g1), external_legs(g1)) + g = FeynmanGraph(graphs, properties; subgraph_factors=constants, operator=Sum(), orders=orders(g1), ftype=F, wtype=W) # Convert multiplicative links to in-place form for (i, sub_g) in enumerate(g.subgraphs) if sub_g.operator == Prod && onechild(sub_g) diff --git a/src/computational_graph/graph.jl b/src/computational_graph/graph.jl index 15e588be..f07e77f9 100644 --- a/src/computational_graph/graph.jl +++ b/src/computational_graph/graph.jl @@ -6,6 +6,7 @@ # Members: - `id::Int` the unique hash id to identify the diagram - `name::Symbol` name of the diagram +- `orders::Vector{Int}` orders associated with the graph, e.g., derivative orders - `subgraphs::Vector{Graph{F,W}}` vector of sub-diagrams - `subgraph_factors::Vector{F}` scalar multiplicative factors associated with each subgraph. Note that the subgraph factors may be manipulated algebraically. To associate a fixed multiplicative factor with this graph which carries some semantic meaning, use the `factor` argument instead. - `operator::DataType` node operation. Addition and multiplication are natively supported via operators Sum and Prod, respectively. Should be a concrete subtype of `AbstractOperator`. @@ -27,7 +28,8 @@ julia> g = Graph([g1, g2]; operator=ComputationalGraphs.Sum()) mutable struct Graph{F,W} <: AbstractGraph # Graph id::Int name::String # "" by default - + orders::Vector{Int} + subgraphs::Vector{Graph{F,W}} subgraph_factors::Vector{F} @@ -45,6 +47,7 @@ mutable struct Graph{F,W} <: AbstractGraph # Graph - `subgraphs` vector of sub-diagrams - `subgraph_factors` scalar multiplicative factors associated with each subgraph. Note that the subgraph factors may be manipulated algebraically. To associate a fixed multiplicative factor with this graph which carries some semantic meaning, use the `factor` argument instead. - `name` name of the diagram + - `orders` orders associated with the graph, e.g., derivative orders - `operator` node operation, i.e., Sum, Prod, or a user-defined operator `Op <: AbstractOperator` - `ftype` typeof(factor) - `wtype` typeof(weight) @@ -52,12 +55,19 @@ mutable struct Graph{F,W} <: AbstractGraph # Graph - `weight` the weight of this node """ function Graph(subgraphs::AbstractVector; subgraph_factors=one.(eachindex(subgraphs)), name="", operator::AbstractOperator=Sum(), - ftype=_dtype.factor, wtype=_dtype.weight, factor=one(ftype), weight=zero(wtype) + orders=zeros(Int, 16), ftype=_dtype.factor, wtype=_dtype.weight, factor=one(ftype), weight=zero(wtype) ) - return new{ftype,wtype}(uid(), name, subgraphs, subgraph_factors, typeof(operator), factor, weight) + return new{ftype,wtype}(uid(), name, orders, subgraphs, subgraph_factors, typeof(operator), factor, weight) end end +""" + function orders(g::Graph) + + Returns the derivative orders (::Vector{Int}) of Graph `g`. +""" +orders(g::Graph) = g.orders + """ function Base.:*(g1::Graph{F,W}, c2::C) where {F,W,C} @@ -68,7 +78,7 @@ end - `c2` scalar multiple """ function Base.:*(g1::Graph{F,W}, c2::C) where {F,W,C} - g = Graph([g1,]; subgraph_factors=[F(c2),], operator=Prod(), ftype=F, wtype=W) + g = Graph([g1,]; subgraph_factors=[F(c2),], operator=Prod(), orders=orders(g1), ftype=F, wtype=W) # Merge multiplicative link if g1.operator == Prod && onechild(g1) g.subgraph_factors[1] *= g1.subgraph_factors[1] @@ -87,7 +97,7 @@ end - `g2` computational graph """ function Base.:*(c1::C, g2::Graph{F,W}) where {F,W,C} - g = Graph([g2,]; subgraph_factors=[F(c1),], operator=Prod(), ftype=F, wtype=W) + g = Graph([g2,]; subgraph_factors=[F(c1),], operator=Prod(), orders=orders(g2), ftype=F, wtype=W) # Merge multiplicative link if g2.operator == Prod && onechild(g2) g.subgraph_factors[1] *= g2.subgraph_factors[1] @@ -100,6 +110,7 @@ end function linear_combination(g1::Graph{F,W}, g2::Graph{F,W}, c1::C, c2::C) where {F,W,C} Returns a graph representing the linear combination `c1*g1 + c2*g2`. + Graphs `g1` and `g2` must have the same orders. # Arguments: - `g1` first computational graph @@ -108,7 +119,8 @@ end - `c2` second scalar multiple """ function linear_combination(g1::Graph{F,W}, g2::Graph{F,W}, c1::C, c2::C) where {F,W,C} - g = Graph([g1, g2]; subgraph_factors=[F(c1), F(c2)], operator=Sum(), ftype=F, wtype=W) + @assert orders(g1) == orders(g2) "g1 and g2 have different orders." + g = Graph([g1, g2]; subgraph_factors=[F(c1), F(c2)], operator=Sum(), orders=orders(g1), ftype=F, wtype=W) # Convert multiplicative links to in-place form if g1.operator == Prod && onechild(g1) g.subgraph_factors[1] *= g1.subgraph_factors[1] @@ -126,16 +138,18 @@ end Given a vector 𝐠 of graphs each with the same type and external/internal vertices and an equally-sized vector 𝐜 of constants, returns a new - graph representing the linear combination (𝐜 ⋅ 𝐠). + graph representing the linear combination (𝐜 ⋅ 𝐠). + All input graphs must have the same orders. # Arguments: - `graphs` vector of computational graphs - `constants` vector of scalar multiples """ function linear_combination(graphs::Vector{Graph{F,W}}, constants::Vector{C}) where {F,W,C} + @assert alleq(orders.(graphs)) "Graphs do not all have the same order." # parameters = union(getproperty.(graphs, :parameters)) g1 = graphs[1] - g = Graph(graphs; subgraph_factors=constants, operator=Sum(), ftype=F, wtype=W) + g = Graph(graphs; subgraph_factors=constants, operator=Sum(), orders=orders(g1), ftype=F, wtype=W) # Convert multiplicative links to in-place form for (i, sub_g) in enumerate(g.subgraphs) if sub_g.operator == Prod && onechild(sub_g) @@ -150,6 +164,7 @@ end function Base.:+(g1::Graph{F,W}, g2::Graph{F,W}) where {F,W} Returns a graph `g1 + g2` representing the addition of `g2` with `g1`. + Graphs `g1` and `g2` must have the same orders. # Arguments: - `g1` first computational graph @@ -163,6 +178,7 @@ end function Base.:-(g1::Graph{F,W}, g2::Graph{F,W}) where {F,W} Returns a graph `g1 - g2` representing the subtraction of `g2` from `g1`. + Graphs `g1` and `g2` must have the same orders. # Arguments: - `g1` first computational graph diff --git a/src/computational_graph/io.jl b/src/computational_graph/io.jl index 522db67b..a84c141b 100644 --- a/src/computational_graph/io.jl +++ b/src/computational_graph/io.jl @@ -17,7 +17,7 @@ function short(factor, ignore=nothing) end end -function _stringrep(graph::G, color=true) where {G<:AbstractGraph} +function _stringrep(graph::AbstractGraph, color=true) namestr = isempty(graph.name) ? "" : "-$(graph.name)" idstr = "$(graph.id)$namestr" if graph isa FeynmanGraph @@ -25,23 +25,22 @@ function _stringrep(graph::G, color=true) where {G<:AbstractGraph} end fstr = short(graph.factor, one(graph.factor)) wstr = short(graph.weight) + ostr = string(orders(graph)) # =$(node.weight*(2π)^(3*node.id.para.innerLoopNum)) if length(graph.subgraphs) == 0 - return isempty(fstr) ? "$idstr=$wstr" : "$(idstr)⋅$(fstr)=$wstr" + return isempty(fstr) ? "$(idstr)$(ostr)=$wstr" : "$(idstr)⋅$(fstr)=$wstr" else - return "$idstr=$wstr=$(fstr)$(graph.operator) " + return "$(idstr)$(ostr)=$wstr=$(fstr)$(graph.operator) " end end """ - show(io::IO, graph::G; kwargs...) where {G<:AbstractGraph} + show(io::IO, graph::AbstractGraph; kwargs...) - Write a text representation of `graph` to the output stream `io`. - - To add support for a user-defined graph type `G`, provide an overload method `Base.show(io::IO, graph::G; kwargs...)` with a custom text representation. + Write a text representation of an AbstractGraph `graph` to the output stream `io`. """ -function Base.show(io::IO, graph::G; kwargs...) where {G<:AbstractGraph} +function Base.show(io::IO, graph::AbstractGraph; kwargs...) if length(graph.subgraphs) == 0 typestr = "" else @@ -50,7 +49,7 @@ function Base.show(io::IO, graph::G; kwargs...) where {G<:AbstractGraph} end print(io, "$(_stringrep(graph, true))$typestr") end -Base.show(io::IO, ::MIME"text/plain", graph::G; kwargs...) where {G<:AbstractGraph} = Base.show(io, graph; kwargs...) +Base.show(io::IO, ::MIME"text/plain", graph::AbstractGraph; kwargs...) = Base.show(io, graph; kwargs...) """ function plot_tree(graph::AbstractGraph; verbose = 0, maxdepth = 6) @@ -107,7 +106,7 @@ function plot_tree(graph::AbstractGraph; verbose=0, maxdepth=6) # t.write(outfile="/home/kun/test.txt", format=8) t.show(tree_style=ts) end -function plot_tree(graphs::Vector{G}; kwargs...) where {G<:AbstractGraph} +function plot_tree(graphs::Vector{<:AbstractGraph}; kwargs...) for graph in graphs plot_tree(graph; kwargs...) end diff --git a/src/computational_graph/optimize.jl b/src/computational_graph/optimize.jl index aa8e6143..b5bddf9a 100644 --- a/src/computational_graph/optimize.jl +++ b/src/computational_graph/optimize.jl @@ -1,4 +1,4 @@ -function optimize!(graphs::Union{Tuple,AbstractVector{G}}; verbose=0, normalize=nothing) where {G<:AbstractGraph} +function optimize!(graphs::Union{Tuple,AbstractVector{<:AbstractGraph}}; verbose=0, normalize=nothing) if isempty(graphs) return nothing else @@ -10,13 +10,13 @@ function optimize!(graphs::Union{Tuple,AbstractVector{G}}; verbose=0, normalize= end end -function optimize(graphs::Union{Tuple,AbstractVector{G}}; verbose=0, normalize=nothing) where {G<:AbstractGraph} +function optimize(graphs::Union{Tuple,AbstractVector{<:AbstractGraph}}; verbose=0, normalize=nothing) graphs_new = deepcopy(graphs) leaf_mapping = optimize!(graphs_new) return graphs_new, leaf_mapping end -function merge_all_chain_prefactors!(g::G; verbose=0) where {G<:AbstractGraph} +function merge_all_chain_prefactors!(g::AbstractGraph; verbose=0) verbose > 0 && println("merge prefactors of all nodes representing trivial unary chains toward root level.") # Post-order DFS for sub_g in g.subgraphs @@ -27,7 +27,7 @@ function merge_all_chain_prefactors!(g::G; verbose=0) where {G<:AbstractGraph} return g end -function merge_all_chain_prefactors!(graphs::AbstractVector{G}; verbose=0) where {G<:AbstractGraph} +function merge_all_chain_prefactors!(graphs::AbstractVector{<:AbstractGraph}; verbose=0) verbose > 0 && println("merge prefactors of all nodes representing trivial unary chains toward root level.") # Post-order DFS for g in graphs @@ -37,7 +37,7 @@ function merge_all_chain_prefactors!(graphs::AbstractVector{G}; verbose=0) where return graphs end -function merge_all_factorless_chains!(g::G; verbose=0) where {G<:AbstractGraph} +function merge_all_factorless_chains!(g::AbstractGraph; verbose=0) verbose > 0 && println("merge all nodes representing factorless trivial unary chains.") # Post-order DFS for sub_g in g.subgraphs @@ -48,7 +48,7 @@ function merge_all_factorless_chains!(g::G; verbose=0) where {G<:AbstractGraph} return g end -function merge_all_factorless_chains!(graphs::AbstractVector{G}; verbose=0) where {G<:AbstractGraph} +function merge_all_factorless_chains!(graphs::AbstractVector{<:AbstractGraph}; verbose=0) verbose > 0 && println("merge all nodes representing factorless trivial unary chains.") # Post-order DFS for g in graphs @@ -58,21 +58,21 @@ function merge_all_factorless_chains!(graphs::AbstractVector{G}; verbose=0) wher return graphs end -function merge_all_chains!(g::G; verbose=0) where {G<:AbstractGraph} +function merge_all_chains!(g::AbstractGraph; verbose=0) verbose > 0 && println("merge all nodes representing trivial unary chains.") merge_all_chain_prefactors!(g, verbose=verbose) merge_all_factorless_chains!(g, verbose=verbose) return g end -function merge_all_chains!(graphs::AbstractVector{G}; verbose=0) where {G<:AbstractGraph} +function merge_all_chains!(graphs::AbstractVector{<:AbstractGraph}; verbose=0) verbose > 0 && println("merge all nodes representing trivial unary chains.") merge_all_chain_prefactors!(graphs, verbose=verbose) merge_all_factorless_chains!(graphs, verbose=verbose) return graphs end -function merge_all_linear_combinations!(g::G; verbose=0) where {G<:AbstractGraph} +function merge_all_linear_combinations!(g::AbstractGraph; verbose=0) verbose > 0 && println("merge nodes representing a linear combination of a non-unique list of graphs.") # Post-order DFS for sub_g in g.subgraphs @@ -83,7 +83,7 @@ function merge_all_linear_combinations!(g::G; verbose=0) where {G<:AbstractGraph return g end -function merge_all_linear_combinations!(graphs::AbstractVector{G}; verbose=0) where {G<:AbstractGraph} +function merge_all_linear_combinations!(graphs::AbstractVector{<:AbstractGraph}; verbose=0) verbose > 0 && println("merge nodes representing a linear combination of a non-unique list of graphs.") # Post-order DFS for g in graphs @@ -93,7 +93,7 @@ function merge_all_linear_combinations!(graphs::AbstractVector{G}; verbose=0) wh return graphs end -function unique_leaves(_graphs::AbstractVector{G}) where {G<:AbstractGraph} +function unique_leaves(_graphs::AbstractVector{<:AbstractGraph}) ############### find the unique Leaves ##################### uniqueGraph = [] mapping = Dict{Int,Int}() @@ -117,9 +117,9 @@ function unique_leaves(_graphs::AbstractVector{G}) where {G<:AbstractGraph} return uniqueGraph, mapping end -function remove_duplicated_leaves!(graphs::AbstractVector{G}; verbose=0, normalize=nothing, kwargs...) where {G<:AbstractGraph} +function remove_duplicated_leaves!(graphs::AbstractVector{<:AbstractGraph}; verbose=0, normalize=nothing, kwargs...) verbose > 0 && println("remove duplicated leaves.") - leaves = Vector{G}() + leaves = Vector{eltype(graphs)}() for g in graphs append!(leaves, collect(Leaves(g))) end diff --git a/src/quantum_operator/expression.jl b/src/quantum_operator/expression.jl index ab48c69f..8e6e9572 100644 --- a/src/quantum_operator/expression.jl +++ b/src/quantum_operator/expression.jl @@ -190,7 +190,7 @@ end The parity of a permutation P is +1 if the number of 2-cycles (swaps) in an n-cycle decomposition with n ≤ 2 is even, and -1 if the number of 2-cycles is odd. """ -function parity(p::W) where {W<:AbstractVector{Int}} +function parity(p::AbstractVector{Int}) count = 0 p_swap = copy(p) for i in eachindex(p) diff --git a/test/computational_graph.jl b/test/computational_graph.jl index 4d7748b5..bfeb5d43 100644 --- a/test/computational_graph.jl +++ b/test/computational_graph.jl @@ -278,7 +278,6 @@ end @test external_legs(g1) == [false, false, true, true] parameters = FeynmanProperties( diagram_type(g1), - orders(g1), vertices(g1), topology(g1), external_indices(g1), @@ -286,7 +285,6 @@ end ) parameters_no_topology = FeynmanProperties( diagram_type(g1), - orders(g1), vertices(g1), [], external_indices(g1),