Initial Commit
This commit is contained in:
commit
a959137e22
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.vscode/
|
||||
**/Manifest.toml
|
4
Project.toml
Normal file
4
Project.toml
Normal file
@ -0,0 +1,4 @@
|
||||
name = "FeynmanDiagramGenerator"
|
||||
uuid = "8f7ec768-9801-4863-9e03-72391fd2204f"
|
||||
authors = ["antonr <s1509337@msx.tu-dresden.de>"]
|
||||
version = "0.1.0"
|
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
# FeynmanDiagrams.jl
|
||||
|
||||
Generator for FeynmanDiagrams of any QFT as long as all vertices have exactly 3 legs.
|
||||
|
||||
Very much WIP.
|
9
src/FeynmanDiagramGenerator.jl
Normal file
9
src/FeynmanDiagramGenerator.jl
Normal file
@ -0,0 +1,9 @@
|
||||
module FeynmanDiagramGenerator
|
||||
|
||||
export Forest
|
||||
|
||||
include("trees/trees.jl")
|
||||
include("trees/iterator.jl")
|
||||
include("trees/print.jl")
|
||||
|
||||
end # module FeynmanDiagramGenerator
|
102
src/trees/iterator.jl
Normal file
102
src/trees/iterator.jl
Normal file
@ -0,0 +1,102 @@
|
||||
|
||||
mutable struct ForestIterator
|
||||
# how many leaves do the left subtrees have
|
||||
left_leaves::Int
|
||||
left_subiterator::Union{ForestIterator,Missing}
|
||||
|
||||
# how many leaves do the right subtrees have
|
||||
right_leaves::Int
|
||||
right_subiterator::Union{ForestIterator,Missing}
|
||||
|
||||
# counter is like an id and incremented each time _iterate is called
|
||||
# important for symmetry breaking for iterators where n is even and the subtrees can have equal leave numbers
|
||||
counter::Int
|
||||
end
|
||||
|
||||
function ForestIterator(n::Int)
|
||||
@assert n >= 1 "Cannot create a ForestIterator with fewer than 1 leaves"
|
||||
if n == 1
|
||||
return missing
|
||||
end
|
||||
return ForestIterator(1, ForestIterator(1), n - 1, ForestIterator(n - 1), 1)
|
||||
end
|
||||
|
||||
ForestIterator(forest::Forest) = ForestIterator(forest.leaves)
|
||||
|
||||
"""
|
||||
IteratorSize(::Forest)
|
||||
|
||||
Would be OEIS sequence A001190, Wedderburn-Etherington numbers: Number of unlabeled binary rooted trees with n leaves.
|
||||
"""
|
||||
Base.IteratorSize(::Forest) = Base.SizeUnknown()
|
||||
Base.IteratorSize(::ForestIterator) = Base.SizeUnknown()
|
||||
|
||||
"""
|
||||
is_end(::ForestIterator)
|
||||
|
||||
Return whether the given [`ForestIterator`](@ref) is exhausted.
|
||||
"""
|
||||
is_end(::Missing) = true
|
||||
is_end(iterator::ForestIterator) = iterator.left_leaves + 1 >= iterator.right_leaves && is_end(iterator.left_subiterator) && is_end(iterator.right_subiterator)
|
||||
|
||||
"""
|
||||
tree(iterator::ForestIterator)
|
||||
|
||||
Return an [`AbstractTree`](@ref) made from the current state of the iterator.
|
||||
"""
|
||||
tree(::Missing) = EmptyTree()
|
||||
function tree(iterator::ForestIterator)
|
||||
return Subtree(tree(iterator.left_subiterator), tree(iterator.right_subiterator))
|
||||
end
|
||||
|
||||
"""
|
||||
_iterate(iterator::ForestIterator)
|
||||
|
||||
Internal function for iterating the [`ForestIterator`](@ref) once.
|
||||
"""
|
||||
function _iterate(iterator::ForestIterator)
|
||||
@assert !is_end(iterator) "Trying to iterate a forest iterator that is already at its end"
|
||||
iterator.counter += 1
|
||||
# reverse direction, iterate right first, then left (reset right), then try new balance
|
||||
if !is_end(iterator.right_subiterator)
|
||||
_iterate(iterator.right_subiterator)
|
||||
return nothing
|
||||
elseif !is_end(iterator.left_subiterator)
|
||||
iterator.right_subiterator = ForestIterator(iterator.right_leaves)
|
||||
|
||||
if (iterator.left_leaves == iterator.right_leaves)
|
||||
# if the subiterators have equal lengths, take care to start the one we reset where the other one currently is (to not get duplicates)
|
||||
# this actually only changes things at forest(8) and higher
|
||||
while (iterator.right_subiterator.counter <= iterator.left_subiterator.counter)
|
||||
_iterate(iterator.right_subiterator)
|
||||
end
|
||||
end
|
||||
_iterate(iterator.left_subiterator)
|
||||
|
||||
return nothing
|
||||
else
|
||||
iterator.right_leaves -= 1
|
||||
iterator.left_leaves += 1
|
||||
iterator.right_subiterator = ForestIterator(iterator.right_leaves)
|
||||
iterator.left_subiterator = ForestIterator(iterator.left_leaves)
|
||||
return nothing
|
||||
end
|
||||
end
|
||||
|
||||
function Base.iterate(forest::Forest)
|
||||
state = ForestIterator(forest.leaves)
|
||||
return (tree(state), state)
|
||||
end
|
||||
|
||||
function Base.iterate(forest::Forest, state::Missing)
|
||||
return nothing
|
||||
end
|
||||
|
||||
function Base.iterate(forest::Forest, state::ForestIterator)
|
||||
if (is_end(state))
|
||||
return nothing
|
||||
end
|
||||
|
||||
_iterate(state)
|
||||
return (tree(state), state)
|
||||
end
|
8
src/trees/print.jl
Normal file
8
src/trees/print.jl
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
function Base.show(io::IO, tree::EmptyTree)
|
||||
print(io, "T1")
|
||||
end
|
||||
|
||||
function Base.show(io::IO, tree::Subtree)
|
||||
print(io, "T$(leaves(tree))<$(tree.left)> <$(tree.right)>")
|
||||
end
|
60
src/trees/trees.jl
Normal file
60
src/trees/trees.jl
Normal file
@ -0,0 +1,60 @@
|
||||
# The subtrees of tree-level feynman diagrams
|
||||
# the subtrees are always binary since we assume that all feynman vertices have 3 leaves
|
||||
# the order of left and right don't matter because we are only interested in topologies
|
||||
|
||||
import Base.iterate
|
||||
|
||||
"""
|
||||
AbstractTree
|
||||
|
||||
Base type for trees, such as [`EmptyTree`](@ref) or [`Subtree`](@ref).
|
||||
|
||||
Implementations provide [`leaves`](@ref), returning the number of leaves of the tree.
|
||||
"""
|
||||
abstract type AbstractTree end
|
||||
|
||||
"""
|
||||
EmptyTree <: AbstractTree
|
||||
|
||||
A singleton type representing an empty tree, which has 1 leaf, see [`leaves`](@ref).
|
||||
"""
|
||||
struct EmptyTree <: AbstractTree end
|
||||
|
||||
"""
|
||||
Subtree <: AbstractTree
|
||||
|
||||
Representation of a specific subtree topology, with two subtrees of its own.
|
||||
"""
|
||||
struct Subtree <: AbstractTree
|
||||
left::AbstractTree
|
||||
right::AbstractTree
|
||||
end
|
||||
|
||||
"""
|
||||
Forest
|
||||
|
||||
Representation of a forest containing all topologically unique trees with a given number of leaves.
|
||||
Use [`iterate`](@ref) to iterate through the [`Subtree`](@ref)s.
|
||||
"""
|
||||
struct Forest
|
||||
leaves::Int
|
||||
|
||||
function Forest(n::Int)
|
||||
@assert n > 0 "Can not create forest of trees with $n leaves, must be at least 1"
|
||||
new(n)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
leaves(tree::AbstractTree)
|
||||
|
||||
Returns the number of leaves or leaves of the tree.
|
||||
"""
|
||||
function leaves end
|
||||
|
||||
leaves(tree::EmptyTree) = 1
|
||||
|
||||
leaves(tree::Subtree) = leaves(tree.left) + leaves(tree.right)
|
||||
|
||||
leaves(forest::Forest) = forest.leaves
|
3
test/Project.toml
Normal file
3
test/Project.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[deps]
|
||||
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
5
test/runtests.jl
Normal file
5
test/runtests.jl
Normal file
@ -0,0 +1,5 @@
|
||||
using SafeTestsets
|
||||
|
||||
@safetestset "Trees" begin
|
||||
include("trees.jl")
|
||||
end
|
26
test/trees.jl
Normal file
26
test/trees.jl
Normal file
@ -0,0 +1,26 @@
|
||||
using FeynmanDiagramGenerator
|
||||
|
||||
import FeynmanDiagramGenerator.EmptyTree
|
||||
import FeynmanDiagramGenerator.Subtree
|
||||
import FeynmanDiagramGenerator.leaves
|
||||
import FeynmanDiagramGenerator.ForestIterator
|
||||
|
||||
@testset "Number of leaves" begin
|
||||
@test leaves(EmptyTree()) == 1
|
||||
@test leaves(Subtree(EmptyTree(), EmptyTree())) == 2
|
||||
@test leaves(Subtree(EmptyTree(), Subtree(EmptyTree(), EmptyTree()))) == 3
|
||||
end
|
||||
|
||||
@testset "Number of Forests" begin
|
||||
@test_throws AssertionError Forest(0)
|
||||
@test_throws AssertionError ForestIterator(0)
|
||||
|
||||
groundtruth_lengths = [1, 1, 1, 2, 3, 6, 11, 23, 46, 98, 207, 451, 983, 2179, 4850, 10905, 24631, 56011, 127912, 293547]
|
||||
|
||||
@testset "Forest with $i leaves" for i in 1:20
|
||||
@test length([t for t in Forest(i)]) == groundtruth_lengths[i]
|
||||
for t in Forest(i)
|
||||
@test leaves(t) == i
|
||||
end
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user