Skip to content

Commit

Permalink
Merge pull request #159 from numericalEFT/computgraph_pchou
Browse files Browse the repository at this point in the history
Update optimize, Compilers, and GV
  • Loading branch information
houpc authored Nov 30, 2023
2 parents 6034184 + 16a8493 commit 27bdeee
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
fail-fast: false
matrix:
version:
- "1.6"
# - "1.6"
# - "nightly"
- "1.9"
os:
Expand Down
152 changes: 112 additions & 40 deletions src/backend/static.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,29 @@ function to_static(::Type{ComputationalGraphs.Power{N}}, subgraphs::Vector{Feynm
end

"""
function to_julia_str(graphs::AbstractVector{<:AbstractGraph}; root::AbstractVector{Int}=[id(g) for g in graphs], name::String="eval_graph!")
function to_julia_str(graphs::AbstractVector{<:AbstractGraph}, leafMap::Dict{Int,Int}; root::AbstractVector{Int}=[id(g) 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.
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.
# Arguments:
- `graphs` (AbstractVector{G}): The vector object representing the Feynman graphs,
- `root` (AbstractVector{Int}, optional): The vector of the root node ids of the graphs (defaults to `[id(g) for g in graphs]`).
- `name` (String,optional): The name of the complied function (defaults to `"eval_graph!"`).
# Returns:
- A String representing the compiled Julia function.
- `leafMap (Dict{Int,G})`: A dictionary that maps the index of the leaf weight's table `leafVal` to the leaf graph.
"""
function to_julia_str(graphs::AbstractVector{<:AbstractGraph}; root::AbstractVector{Int}=[id(g) for g in graphs], name::String="eval_graph!")
head = "function $name(root::AbstractVector, leaf::AbstractVector)\n "
function to_julia_str(graphs::AbstractVector{<:AbstractGraph}; root::AbstractVector{Int}=[id(g) for g in graphs],
name::String="eval_graph!")
head = "\nfunction $name(root::AbstractVector, leafVal::AbstractVector)\n"
body = ""
leafidx = 1
inds_visitedleaf = Int[]
inds_visitednode = Int[]
idx_leafVal = 1
map_validx_leaf = Dict{Int,eltype(graphs)}() # mapping from the index of the leafVal to the leaf graph
for graph in graphs
for g in PostOrderDFS(graph) #leaf first search
g_id = id(g)
Expand All @@ -85,70 +97,89 @@ function to_julia_str(graphs::AbstractVector{<:AbstractGraph}; root::AbstractVec
if isempty(subgraphs(g)) #leaf
g_id in inds_visitedleaf && continue
factor_str = factor(g) == 1 ? "" : " * $(factor(g))"
body *= " $target = leaf[$leafidx]$factor_str\n "
leafidx += 1
body *= " $target = leafVal[$idx_leafVal]$factor_str\n"
map_validx_leaf[idx_leafVal] = g
idx_leafVal += 1
push!(inds_visitedleaf, g_id)
else
g_id in inds_visitednode && continue
factor_str = factor(g) == 1 ? "" : " * $(factor(g))"
body *= " $target = $(to_static(operator(g), subgraphs(g), subgraph_factors(g)))$factor_str\n "
body *= " $target = $(to_static(operator(g), subgraphs(g), subgraph_factors(g)))$factor_str\n"
push!(inds_visitednode, g_id)
end
if isroot
body *= " $target_root = $target\n "
body *= " $target_root = $target\n"
end
end
end
tail = "end"
return head * body * tail
return head * body * tail, map_validx_leaf
end

"""
function to_julia_str(graphs::AbstractVector{<:AbstractGraph}, leafMap::Dict{Int,Int}; root::AbstractVector{Int}=[id(g) 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.
function julia_to_C_typestr(type::DataType)
if type == Float64
return "double "
elseif type == Float32
return "float "
elseif type == Int64
return "long long "
elseif type == Int32
return "int "
elseif type == ComplexF32
return "complex float "
elseif type == ComplexF64
return "complex double "
elseif type <: Array
return julia_to_C_typestr(eltype(type)) * "*"
else
error("Unsupported type")
end
end

# Arguments:
- `graphs` (AbstractVector{G}): The vector object representing the Feynman graphs,
- `leafMap (Dict{Int,Int})`: The mapping dictionary from the id of each leaf to the index of the leaf weight's table `leafVal`.
- `root` (AbstractVector{Int}, optional): The vector of the root node ids of the graphs (defaults to `[id(g) for g in graphs]`).
- `name` (String,optional): The name of the complied function (defaults to `"eval_graph!"`).
"""
function to_julia_str(graphs::AbstractVector{<:AbstractGraph}, leafMap::Dict{Int,Int}; root::AbstractVector{Int}=[id(g) for g in graphs],
name::String="eval_graph!")
head = "function $name(root::AbstractVector, leafVal::AbstractVector)\n "
function to_Cstr(graphs::AbstractVector{<:AbstractGraph}; root::AbstractVector{Int}=[id(g) for g in graphs],
datatype::DataType=_dtype.weight, name::String="eval_graph")
# head = "#include <stdio.h>"
ctype_str = julia_to_C_typestr(datatype)
head = "\nvoid $name($ctype_str*root, $ctype_str*leafVal)\n{\n"

declare = " $ctype_str"
body = ""
inds_visitedleaf = Int[]
inds_visitednode = Int[]
idx_leafVal = 0
map_validx_leaf = Dict{Int,eltype(graphs)}() # mapping from the index of the leafVal to the leaf graph
for graph in graphs
for g in PostOrderDFS(graph) #leaf first search
g_id = id(g)
target = "g$(g_id)"
isroot = false
if g_id in root
target_root = "root[$(findfirst(x -> x == g_id, root))]"
target_root = "root[$(findfirst(x -> x == g_id, root)-1)]"
isroot = true
end
if isempty(subgraphs(g)) #leaf
g_id in inds_visitedleaf && continue
declare *= " g$g_id,"
factor_str = factor(g) == 1 ? "" : " * $(factor(g))"
body *= " $target = leafVal[$(leafMap[g_id])]$factor_str\n "
body *= " $target = leafVal[$idx_leafVal]$factor_str;\n"
idx_leafVal += 1
map_validx_leaf[idx_leafVal] = g
push!(inds_visitedleaf, g_id)
else
g_id in inds_visitednode && continue
declare *= " g$g_id,"
factor_str = factor(g) == 1 ? "" : " * $(factor(g))"
body *= " $target = $(to_static(operator(g), subgraphs(g), subgraph_factors(g)))$factor_str\n "
body *= " $target = $(to_static(operator(g), subgraphs(g), subgraph_factors(g)))$factor_str;\n"
push!(inds_visitednode, g_id)
end
if isroot
body *= " $target_root = $target\n "
body *= " $target_root = $target;\n"
end
end
end
tail = "end"
return head * body * tail
declare = chop(declare) * ";\n"
tail = "}"
return head * declare * body * tail, map_validx_leaf
end

"""
Expand Down Expand Up @@ -176,15 +207,56 @@ leaf = [1.0, 2.0]
function compile(graphs::AbstractVector{<:AbstractGraph};
root::AbstractVector{Int}=[id(g) 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_string, leafmap = to_julia_str(graphs; root=root, name="eval_graph!")
func_expr = Meta.parse(func_string)
return @RuntimeGeneratedFunction(func_expr)
return @RuntimeGeneratedFunction(func_expr), leafmap
end

function compile(graphs::AbstractVector{<:AbstractGraph}, leafMap::Dict{Int,Int};
root::AbstractVector{Int}=[id(g) 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)
return @RuntimeGeneratedFunction(func_expr)
"""
function compile_Julia(graphs::AbstractVector{<:AbstractGraph}, filename::String;
root::AbstractVector{Int}=[id(g) for g in graphs], func_name="eval_graph!")
Compiles a set of graphs into Julia code and append the generated code to a specified file.
# Arguments
- `graphs::AbstractVector{<:AbstractGraph}`: An array of graph objects. These graphs are processed to generate Julia code.
- `filename::String`: The name of the file to which the generated code will be appended. The file is created if it does not exist.
- `root::AbstractVector{Int}` (keyword): An array of integers representing root nodes for each graph in `graphs`. By default, it is an array of IDs obtained by calling `id(g)` for each graph `g` in `graphs`.
- `func_name::String` (keyword): The base name for the function(s) to be generated. Defaults to `"eval_graph!"`.
# Returns
- A dictionary (`leafmap`) that maps the index of the leaf weight's table `leafVal` to the leaf graph.
"""
function compile_Julia(graphs::AbstractVector{<:AbstractGraph}, filename::String;
root::AbstractVector{Int}=[id(g) for g in graphs], func_name="eval_graph!")
func_string, leafmap = to_julia_str(graphs; root=root, name=func_name)
open(filename, "a") do f
write(f, func_string)
end
return leafmap
end

"""
function compile_C(graphs::AbstractVector{<:AbstractGraph}, filename::String;
datatype::DataType=_dtype.weight, root::AbstractVector{Int}=[id(g) for g in graphs], func_name="eval_graph")
Compiles a set of graphs into C language code and append the generated code to a specified file.
# Arguments
- `datatype::DataType`: This type is used for variables types in the generated C code.
- `graphs::AbstractVector{<:AbstractGraph}`: An array of graph objects. These graphs are processed to generate Julia code.
- `filename::String`: The name of the file to which the generated code will be appended. The file is created if it does not exist.
- `root::AbstractVector{Int}` (keyword): An array of integers representing root nodes for each graph in `graphs`. By default, it is an array of IDs obtained by calling `id(g)` for each graph `g` in `graphs`.
- `func_name::String` (keyword): The base name for the function(s) to be generated. Defaults to `"eval_graph"`.
# Returns
- A dictionary (`leafmap`) that maps the index of the leaf weight's table `leafVal` to the leaf graph.
"""
function compile_C(graphs::AbstractVector{<:AbstractGraph}, filename::String;
datatype::DataType=_dtype.weight, root::AbstractVector{Int}=[id(g) for g in graphs], func_name="eval_graph")
func_string, leafmap = to_Cstr(graphs; datatype=datatype, root=root, name=func_name)
open(filename, "a") do f
write(f, func_string)
end
return leafmap
end
44 changes: 14 additions & 30 deletions src/computational_graph/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,17 @@
- `graphs`: A tuple or vector of graphs.
- `verbose`: Level of verbosity (default: 0).
- `normalize`: Optional function to normalize the graphs (default: nothing).
# Returns:
- A mapping dictionary from the id of each unique leaf node to its index in collect(1:length(leafs)).
"""
function optimize!(graphs::Union{Tuple,AbstractVector{<:AbstractGraph}}; verbose=0, normalize=nothing)
if isempty(graphs)
return nothing
else
graphs = collect(graphs)
leaf_mapping = remove_duplicated_leaves!(graphs, verbose=verbose, normalize=normalize)
remove_duplicated_leaves!(graphs, verbose=verbose, normalize=normalize)
flatten_all_chains!(graphs, verbose=verbose)
merge_all_linear_combinations!(graphs, verbose=verbose)
return leaf_mapping

return graphs
end
end

Expand All @@ -35,12 +33,11 @@ end
# Returns:
- A tuple/vector of optimized graphs.
- A mapping dictionary from the id of each unique leaf node to its index in collect(1:length(leafs)).
"""
function optimize(graphs::Union{Tuple,AbstractVector{<:AbstractGraph}}; verbose=0, normalize=nothing)
graphs_new = deepcopy(graphs)
leaf_mapping = optimize!(graphs_new, verbose=verbose, normalize=normalize)
return graphs_new, leaf_mapping
optimize!(graphs_new, verbose=verbose, normalize=normalize)
return graphs_new
end

"""
Expand Down Expand Up @@ -190,34 +187,28 @@ end
- `graphs`: A collection of graphs to be processed.
# Returns:
- The vector of unique leaf nodes.
- The vector of unique leaf nodes' index.
- A mapping dictionary from the id of each unique leaf node to its index in collect(1:length(leafs)).
- A mapping dictionary from the id of each leaf to the unique leaf node.
"""
function unique_leaves(graphs::AbstractVector{<:AbstractGraph})
############### find the unique Leaves #####################
unique_graphs = []
unique_graphs_id = Int[]
mapping = Dict{Int,Int}()
mapping = Dict{Int,eltype(graphs)}()

idx = 1
for g in graphs
flag = true
for (ie, e) in enumerate(unique_graphs)
for e in unique_graphs
if isequiv(e, g, :id)
mapping[id(g)] = ie
mapping[id(g)] = e
flag = false
break
end
end
if flag
push!(unique_graphs, g)
push!(unique_graphs_id, g.id)
mapping[g.id] = idx
idx += 1
mapping[id(g)] = g
end
end
return unique_graphs, unique_graphs_id, mapping
return mapping
end

"""
Expand All @@ -229,9 +220,6 @@ end
- `graphs`: A collection of graphs to be processed.
- `verbose`: Level of verbosity (default: 0).
- `normalize`: Optional function to normalize the graphs (default: nothing).
# Returns:
- A mapping dictionary from the id of each unique leaf node to its index in collect(1:length(leafs)).
"""
function remove_duplicated_leaves!(graphs::Union{Tuple,AbstractVector{<:AbstractGraph}}; verbose=0, normalize=nothing, kwargs...)
verbose > 0 && println("remove duplicated leaves.")
Expand All @@ -248,24 +236,20 @@ function remove_duplicated_leaves!(graphs::Union{Tuple,AbstractVector{<:Abstract
sort!(leaves, by=x -> id(x)) #sort the id of the leaves in an asscend order
unique!(x -> id(x), leaves) #filter out the leaves with the same id number

_unique_leaves, uniqueleaves_id, mapping = unique_leaves(leaves)
mapping = unique_leaves(leaves)
verbose > 0 && length(leaves) > 0 && println("Number of independent Leaves $(length(leaves))$(length(_unique_leaves))")

leafmap = Dict{Int,Int}()
for g in graphs
for n in PreOrderDFS(g)
for (si, sub_g) in enumerate(subgraphs(n))
if isleaf(sub_g)
set_subgraph!(n, _unique_leaves[mapping[id(sub_g)]], si)
if sub_g.id uniqueleaves_id
leafmap[sub_g.id] = mapping[sub_g.id]
end
set_subgraph!(n, mapping[id(sub_g)], si)
end
end
end
end

return leafmap
return graphs
end

"""
Expand Down
Loading

0 comments on commit 27bdeee

Please sign in to comment.