Skip to content

Commit

Permalink
Merge pull request #184 from numericalEFT/daniel
Browse files Browse the repository at this point in the history
Improve graph I/O
  • Loading branch information
dcerkoney authored Sep 25, 2024
2 parents b7957b3 + fbe6ab4 commit 79f254b
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 109 deletions.
6 changes: 3 additions & 3 deletions src/computational_graph/ComputationalGraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ export multi_product, linear_combination, feynman_diagram, propagator, interacti
# export 𝐺ᶠ, 𝐺ᵇ, 𝐺ᵠ, 𝑊, Green2, Interaction


include("tree_properties.jl")
export haschildren, onechild, isleaf, isbranch, ischain, has_zero_subfactors, eldest, count_operation

include("operation.jl")
include("io.jl")
export plot_tree

include("tree_properties.jl")
export haschildren, onechild, isleaf, isbranch, ischain, has_zero_subfactors, eldest, count_operation

include("eval.jl")
export eval!

Expand Down
22 changes: 21 additions & 1 deletion src/computational_graph/abstractgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@ Base.isequal(a::AbstractOperator, b::AbstractOperator) = (typeof(a) == typeof(b)
Base.:(==)(a::AbstractOperator, b::AbstractOperator) = Base.isequal(a, b)
apply(o::AbstractOperator, diags) = error("not implemented!")

Base.print(io::IO, o::AbstractOperator) = print(io, typeof(o))
Base.print(io::IO, ::Type{Sum}) = print(io, "Sum")
Base.print(io::IO, ::Type{Prod}) = print(io, "Prod")
Base.print(io::IO, ::Type{Unitary}) = print(io, "Unitary")
Base.print(io::IO, ::Type{Power{N}}) where {N} = print(io, "Power{$N}")

Base.show(io::IO, o::AbstractOperator) = print(io, typeof(o))
Base.show(io::IO, ::Type{Sum}) = print(io, "")
Base.show(io::IO, ::Type{Prod}) = print(io, "")
Base.show(io::IO, ::Type{Prod}) = print(io, " ")
Base.show(io::IO, ::Type{Unitary}) = print(io, "𝟙")
Base.show(io::IO, ::Type{Power{N}}) where {N} = print(io, "^$N")

Expand Down Expand Up @@ -89,6 +95,13 @@ function operator(g::AbstractGraph) end
"""
function weight(g::AbstractGraph) end

"""
function properties(g::AbstractGraph)
Returns additional properties, if any, of the computational graph `g`.
"""
function properties(g::AbstractGraph) end

"""
function subgraph(g::AbstractGraph, i=1)
Expand Down Expand Up @@ -184,6 +197,13 @@ function set_weight!(g::AbstractGraph, weight)
"""
function set_weight!(g::AbstractGraph, weight) end

"""
function set_properties!(g::AbstractGraph, properties)
Update the properties of graph `g` to `properties`.
"""
function set_properties!(g::AbstractGraph, properties) end

"""
function set_subgraph!(g::AbstractGraph, subgraph::AbstractGraph, i=1)
Expand Down
89 changes: 67 additions & 22 deletions src/computational_graph/io.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
function _ops_to_str(ops::Vector{OperatorProduct})
strs = ["$(o)" for o in ops]
function _ops_to_string(ops::Vector{OperatorProduct})
strs = [string(o) for o in ops]
return join(strs, "|")
end

function _ops_to_repr(ops::Vector{OperatorProduct})
reprs = [repr(o) for o in ops]
return join(reprs, "|")
end

function short(factor, ignore=nothing)
if isnothing(ignore) == false && applicable(isapprox, factor, ignore) && factor ignore
return ""
Expand All @@ -25,31 +30,77 @@ function short_orders(orders)
end
return orders_no_trailing_zeros
end

function _namestring(graph::AbstractGraph)
return isnothing(name(graph)) ? "" : string(name(graph))
end

function _namestr(graph::AbstractGraph)
return isempty(name(graph)) ? "" : "-$(name(graph))"
function _namestring(graph::FeynmanGraph)
return isempty(name(graph)) ? "" : string(name(graph), ", ")
end

function _idstring(graph::AbstractGraph)
return string(id(graph), _namestr(graph))
return _namestring(graph)
end

function _idstring(graph::FeynmanGraph)
return string(id(graph), _namestr(graph), ":", _ops_to_str(vertices(graph)))
return string(_namestring(graph), _ops_to_string(vertices(graph)))
end

_idrepr(graph::AbstractGraph) = _idstring(graph)

function _idrepr(graph::FeynmanGraph)
return string(_namestring(graph), _ops_to_repr(vertices(graph)))
end

function _stringrep(graph::AbstractGraph, color=true)
idstr = _idstring(graph)
properties = graph.properties
wstr = short(weight(graph))
ostr = short_orders(orders(graph))
# =$(node.weight*(2π)^(3*node.id.para.innerLoopNum))
function _propertystring(graph::AbstractGraph)
return isnothing(properties(graph)) ? "" : string(properties(graph))
end

function _weightstring(graph::AbstractGraph)
if isleaf(graph)
return "$(short(weight(graph)))"
end
typestr = join(["$(id(g))" for g in subgraphs(graph)], ",")
return "$(operator(graph))($(typestr))=$(short(weight(graph)))"
end

function _weightrepr(graph::AbstractGraph)
if isleaf(graph)
return isnothing(properties) ? "$(idstr)$(ostr)=$wstr" : "$(idstr)$(properties)$(ostr)=$wstr"
return "$(short(weight(graph)))"
end
typestr = join(["$(id(g))" for g in subgraphs(graph)], ",")
return "$(repr(operator(graph)))($(typestr))=$(short(weight(graph)))"
end

function _stringrep(graph::AbstractGraph; color=false, plain=false)
if color
idprefix = "\u001b[32m$(id(graph))\u001b[0m: "
else
return isnothing(properties) ? "$(idstr)$(ostr)=$wstr=$(operator(graph)) " : "$(idstr)$(properties)$(ostr)=$wstr=$(operator(graph)) "
idprefix = string(id(graph), ": ")
end
idsuffix = plain ? _idstring(graph) : _idrepr(graph)

propertystr = _propertystring(graph) * short_orders(orders(graph))
if isempty(idsuffix) == false && isempty(propertystr) == false
idsuffix *= ", "
end
idsuffix *= propertystr

wstr = plain ? _weightstring(graph) : _weightrepr(graph)
if isempty(idsuffix) == false
wstr = "=" * wstr
end
return "$(idprefix)$(idsuffix)$(wstr)"
end

"""
print(io::IO, graph::AbstractGraph)
Write an un-decorated text representation of an AbstractGraph `graph` to the output stream `io`.
"""
function Base.print(io::IO, graph::AbstractGraph)
print(io, _stringrep(graph; plain=true))
end

"""
Expand All @@ -58,13 +109,7 @@ end
Write a text representation of an AbstractGraph `graph` to the output stream `io`.
"""
function Base.show(io::IO, graph::AbstractGraph; kwargs...)
if isleaf(graph) == 0
typestr = ""
else
typestr = join(["$(id(g))" for g in subgraphs(graph)], ",")
typestr = "($typestr)"
end
print(io, "$(_stringrep(graph, true))$typestr")
print(io, _stringrep(graph))
end
Base.show(io::IO, ::MIME"text/plain", graph::AbstractGraph; kwargs...) = Base.show(io, graph; kwargs...)

Expand All @@ -87,7 +132,7 @@ function plot_tree(graph::AbstractGraph; verbose=0, maxdepth=6)
if level > maxdepth
return
end
name = "$(_stringrep(node, false))"
name = _stringrep(node)
nt = t.add_child(name=name)

if length(subgraphs(node)) > 0
Expand Down
22 changes: 2 additions & 20 deletions src/computational_graph/tree_properties.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
##################### AbstractTrees interface for AbstractGraphs ###########################

## Things that make printing prettier
AbstractTrees.printnode(io::IO, g::AbstractGraph) = print(io, "\u001b[32m$(id(g))\u001b[0m : $g")
AbstractTrees.printnode(io::IO, g::AbstractGraph) = print(io, _stringrep(g; color=true))

## Guarantee type-stable tree iteration for Graphs and FeynmanGraphs
AbstractTrees.NodeType(::Graph) = HasNodeType()
Expand Down Expand Up @@ -80,30 +80,12 @@ function ischain(g::AbstractGraph)
return false
end

# """
# function isfactorless(g)

# Returns whether the graph g is factorless, i.e., has unity factor and, if applicable,
# subgraph factor(s). Note that this function does not recurse through subgraphs of g, so
# that one may have, e.g., `isfactorless(g) == true` but `isfactorless(eldest(g)) == false`.

# # Arguments:
# - `g::AbstractGraph`: graph to be analyzed
# """
# function isfactorless(g::AbstractGraph)
# if isleaf(g)
# return isapprox_one(factor(g))
# else
# return all(isapprox_one.([factor(g); subgraph_factors(g)]))
# end
# end

"""
function has_zero_subfactors(g)
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.,
`isfactorless(g) == true` but `isfactorless(eldest(g)) == false`.
`has_zero_subfactors(g) == true` but `has_zero_subfactors(eldest(g)) == false`.
By convention, returns `false` if g is a leaf.
# Arguments:
Expand Down
3 changes: 2 additions & 1 deletion src/quantum_operator/expression.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ Base.setindex!(o::OperatorProduct, v::QuantumOperator, i::Int) = o.operators[i]
Base.length(o::OperatorProduct) = length(o.operators)
Base.size(o::OperatorProduct) = size(o.operators)

Base.show(io::IO, o::OperatorProduct) = print(io, reduce(*, ["$o" for o in o.operators]))
Base.print(io::IO, o::OperatorProduct) = print(io, reduce(*, [string(o) for o in o.operators]))
Base.show(io::IO, o::OperatorProduct) = print(io, reduce(*, [repr(o) for o in o.operators]))
Base.show(io::IO, ::MIME"text/plain", o::OperatorProduct) = Base.show(io, o)

"""
Expand Down
11 changes: 10 additions & 1 deletion src/quantum_operator/operator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ struct BosonCreation <: AbstractQuantumOperator end
struct BosonAnnihilation <: AbstractQuantumOperator end
struct Classic <: AbstractQuantumOperator end

Base.print(io::IO, o::AbstractQuantumOperator) = print(io, typeof(o))
Base.print(io::IO, ::Type{FermiCreation}) = print(io, "FermiCreation")
Base.print(io::IO, ::Type{FermiAnnihilation}) = print(io, "FermiAnnihilation")
Base.print(io::IO, ::Type{Majorana}) = print(io, "Majorana")
Base.print(io::IO, ::Type{BosonCreation}) = print(io, "BosonCreation")
Base.print(io::IO, ::Type{BosonAnnihilation}) = print(io, "BosonAnnihilation")
Base.print(io::IO, ::Type{Classic}) = print(io, "Classic")

Base.show(io::IO, ::Type{FermiCreation}) = print(io, "f⁺")
Base.show(io::IO, ::Type{FermiAnnihilation}) = print(io, "f⁻")
Base.show(io::IO, ::Type{Majorana}) = print(io, "f")
Expand Down Expand Up @@ -65,7 +73,8 @@ Base.:(==)(a::QuantumOperator, b::QuantumOperator) = Base.isequal(a, b)
# Relabel constructor
QuantumOperator(qo::QuantumOperator, label::Int) = QuantumOperator(qo.operator(), label)

Base.show(io::IO, o::QuantumOperator) = print(io, "$(o.operator)($(o.label))")
Base.print(io::IO, o::QuantumOperator) = print(io, "$(o.operator)($(o.label))")
Base.show(io::IO, o::QuantumOperator) = print(io, "$(repr(o.operator))($(o.label))")
Base.show(io::IO, ::MIME"text/plain", o::QuantumOperator) = Base.show(io, o)

"""
Expand Down
Loading

0 comments on commit 79f254b

Please sign in to comment.