From a97a87888116c6915aa48e4e3083c42b79bcc18e Mon Sep 17 00:00:00 2001 From: Anton Reinhard Date: Mon, 13 Nov 2023 14:15:57 +0100 Subject: [PATCH] Add abcmodel tests, Add groundtruth for AB->AB process, fix calculation --- src/MetagraphOptimization.jl | 16 ++++++-- src/models/abc/compute.jl | 3 +- src/models/abc/particle.jl | 7 ++-- test/Project.toml | 1 + test/runtests.jl | 1 + test/unit_tests_abcmodel.jl | 26 +++++++++++++ test/unit_tests_estimator.jl | 17 ++++++++- test/unit_tests_execution.jl | 72 ++++++++++++++++++++++++++++-------- 8 files changed, 119 insertions(+), 24 deletions(-) create mode 100644 test/unit_tests_abcmodel.jl diff --git a/src/MetagraphOptimization.jl b/src/MetagraphOptimization.jl index d6256ff..20dac65 100644 --- a/src/MetagraphOptimization.jl +++ b/src/MetagraphOptimization.jl @@ -5,6 +5,7 @@ A module containing tools to work on DAGs. """ module MetagraphOptimization +# graph types export DAG export Node export Edge @@ -18,6 +19,7 @@ export FusedComputeTask export PossibleOperations export GraphProperties +# graph functions export make_node export make_edge export insert_node @@ -31,6 +33,7 @@ export get_properties export get_exit_node export is_valid, is_scheduled +# graph operation related export Operation export AppliedOperation export NodeFusion @@ -42,6 +45,10 @@ export can_pop export reset_graph! export get_operations +# ABC model +export ParticleValue +export ParticleA, ParticleB, ParticleC +export ABCProcessDescription, ABCProcessInput, ABCModel export ComputeTaskP export ComputeTaskS1 export ComputeTaskS2 @@ -49,14 +56,17 @@ export ComputeTaskV export ComputeTaskU export ComputeTaskSum +# code generation related export execute export parse_dag, parse_process export gen_process_input export get_compute_function -export ParticleValue -export ParticleA, ParticleB, ParticleC -export ABCProcessDescription, ABCProcessInput, ABCModel +# estimator +export cost_type, graph_cost +export GlobalMetricEstimator, CDCost + +# machine info export Machine export get_machine_info diff --git a/src/models/abc/compute.jl b/src/models/abc/compute.jl index df5f865..d5f6056 100644 --- a/src/models/abc/compute.jl +++ b/src/models/abc/compute.jl @@ -55,7 +55,8 @@ function compute(::ComputeTaskS2, data1::ParticleValue{P}, data2::ParticleValue{ @assert isapprox(data1.p.momentum.py, -data2.p.momentum.py, rtol = 0.001, atol = sqrt(eps())) "py: $(data1.p.momentum.py) vs. $(data2.p.momentum.py)" @assert isapprox(data1.p.momentum.pz, -data2.p.momentum.pz, rtol = 0.001, atol = sqrt(eps())) "pz: $(data1.p.momentum.pz) vs. $(data2.p.momentum.pz)" =# - return data1.v * inner_edge(data1.p) * data2.v + inner = inner_edge(data1.p) + return data1.v * inner * data2.v end """ diff --git a/src/models/abc/particle.jl b/src/models/abc/particle.jl index 368165b..6db9a1c 100644 --- a/src/models/abc/particle.jl +++ b/src/models/abc/particle.jl @@ -1,5 +1,7 @@ using QEDbase +import QEDbase.mass + """ ABCModel <: AbstractPhysicsModel @@ -87,9 +89,9 @@ For 2 given (non-equal) particle types, return the third of ABC. """ function interaction_result(t1::Type{T1}, t2::Type{T2}) where {T1 <: ABCParticle, T2 <: ABCParticle} @assert t1 != t2 - if t1 != Type{ParticleA} && t2 != Type{ParticleA} + if t1 != ParticleA && t2 != ParticleA return ParticleA - elseif t1 != Type{ParticleB} && t2 != Type{ParticleB} + elseif t1 != ParticleB && t2 != ParticleB return ParticleB else return ParticleC @@ -161,7 +163,6 @@ Takes 4 effective FLOP. function preserve_momentum(p1::ABCParticle, p2::ABCParticle) t3 = interaction_result(typeof(p1), typeof(p2)) p3 = t3(p1.momentum + p2.momentum) - return p3 end diff --git a/test/Project.toml b/test/Project.toml index fbcc5de..9f8b1ad 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,4 +1,5 @@ [deps] +AccurateArithmetic = "22286c92-06ac-501d-9306-4abd417d9753" QEDbase = "10e22c08-3ccb-4172-bfcf-7d7aa3d04d93" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/runtests.jl b/test/runtests.jl index ab5013c..7244983 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -7,6 +7,7 @@ using Test include("unit_tests_nodes.jl") include("unit_tests_properties.jl") include("unit_tests_estimator.jl") + include("unit_tests_abcmodel.jl") include("node_reduction.jl") include("unit_tests_graph.jl") include("unit_tests_execution.jl") diff --git a/test/unit_tests_abcmodel.jl b/test/unit_tests_abcmodel.jl new file mode 100644 index 0000000..42581b5 --- /dev/null +++ b/test/unit_tests_abcmodel.jl @@ -0,0 +1,26 @@ +using MetagraphOptimization +using QEDbase + +import MetagraphOptimization.interaction_result + +def_momentum = SFourMomentum(1.0, 0.0, 0.0, 0.0) + +testparticleTypes = [ParticleA, ParticleB, ParticleC] +testparticles = [ParticleA(def_momentum), ParticleB(def_momentum), ParticleC(def_momentum)] + +@testset "Unit Tests ABC-Model" begin + @testset "Interaction Result" begin + for p1 in testparticleTypes, p2 in testparticleTypes + if (p1 == p2) + @test_throws AssertionError interaction_result(p1, p2) + else + @test interaction_result(p1, p2) == setdiff(testparticleTypes, [p1, p2])[1] + end + end + end + + @testset "Vertex" begin + @test isapprox(MetagraphOptimization.vertex(), 1 / 137.0) + end +end +println("ABC-Model Unit Tests Complete!") diff --git a/test/unit_tests_estimator.jl b/test/unit_tests_estimator.jl index 7d3915e..d73be68 100644 --- a/test/unit_tests_estimator.jl +++ b/test/unit_tests_estimator.jl @@ -1,4 +1,17 @@ -@testset "Unit Tests Estimator" begin end +@testset "Unit Tests Estimator" begin + @testset "Global Metric Estimator" begin + estimator = GlobalMetricEstimator() -println("Estimator Unit Tests Complete!") \ No newline at end of file + @test cost_type(estimator) == CDCost + + graph = parse_dag(joinpath(@__DIR__, "..", "input", "AB->AB.txt"), ABCModel()) + + estimate = graph_cost(estimator, graph) + + @test estimate.data == 976 + @test estimate.computeEffort == 53 + @test isapprox(estimate.computeIntensity, 0.05430327868852459) + end +end +println("Estimator Unit Tests Complete!") diff --git a/test/unit_tests_execution.jl b/test/unit_tests_execution.jl index 4877076..00c3243 100644 --- a/test/unit_tests_execution.jl +++ b/test/unit_tests_execution.jl @@ -1,9 +1,51 @@ import MetagraphOptimization.ABCParticle +import MetagraphOptimization.interaction_result using QEDbase +using AccurateArithmetic include("../examples/profiling_utilities.jl") +const RTOL = sqrt(eps(Float64)) + +function check_particle_reverse_moment(p1::SFourMomentum, p2::SFourMomentum) + @test isapprox(abs(p1.E), abs(p2.E)) + @test isapprox(p1.px, -p2.px) + @test isapprox(p1.py, -p2.py) + @test isapprox(p1.pz, -p2.pz) + return nothing +end + +function ground_truth_graph_result(input::ABCProcessInput) + # formula for one diagram: + # u_Bp * iλ * u_Ap * S_C * u_B * iλ * u_A + # for the second diagram: + # u_B * iλ * u_Ap * S_C * u_Bp * iλ * u_Ap + # the "u"s are all 1, we ignore the i, λ is 1/137. + + constant = (1 / 137.0)^2 + + # calculate particle C in diagram 1 + diagram1_C = ParticleC(input.inParticles[1].momentum + input.inParticles[2].momentum) + diagram2_C = ParticleC(input.inParticles[1].momentum + input.outParticles[2].momentum) + + diagram1_Cp = ParticleC(input.outParticles[1].momentum + input.outParticles[2].momentum) + diagram2_Cp = ParticleC(input.outParticles[1].momentum + input.inParticles[2].momentum) + + check_particle_reverse_moment(diagram1_Cp.momentum, diagram1_C.momentum) + check_particle_reverse_moment(diagram2_Cp.momentum, diagram2_C.momentum) + @test isapprox(getMass2(diagram1_C.momentum), getMass2(diagram1_Cp.momentum)) + @test isapprox(getMass2(diagram2_C.momentum), getMass2(diagram2_Cp.momentum)) + + inner1 = MetagraphOptimization.inner_edge(diagram1_C) + inner2 = MetagraphOptimization.inner_edge(diagram2_C) + + diagram1_result = inner1 * constant + diagram2_result = inner2 * constant + + return sum_kbn([diagram1_result, diagram2_result]) +end + @testset "Unit Tests Execution" begin machine = get_machine_info() @@ -23,29 +65,29 @@ include("../examples/profiling_utilities.jl") ParticleB(SFourMomentum(0.823648, 0.835061, 0.474802, -0.277915)), ], ) - expected_result = 0.00013916495566048735 + expected_result = ground_truth_graph_result(particles_2_2) @testset "AB->AB no optimization" begin for _ in 1:10 # test in a loop because graph layout should not change the result graph = parse_dag(joinpath(@__DIR__, "..", "input", "AB->AB.txt"), ABCModel()) - @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = 0.001) + @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = RTOL) # graph should be fully scheduled after being executed @test is_scheduled(graph) func = get_compute_function(graph, process_2_2, machine) - @test isapprox(func(particles_2_2), expected_result; rtol = 0.001) + @test isapprox(func(particles_2_2), expected_result; rtol = RTOL) end end @testset "AB->AB after random walk" begin - for i in 1:1000 + for i in 1:200 graph = parse_dag(joinpath(@__DIR__, "..", "input", "AB->AB.txt"), ABCModel()) random_walk!(graph, 50) @test is_valid(graph) - @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = 0.001) + @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = RTOL) # graph should be fully scheduled after being executed @test is_scheduled(graph) @@ -63,20 +105,20 @@ include("../examples/profiling_utilities.jl") @testset "AB->ABBB no optimization" begin for _ in 1:5 # test in a loop because graph layout should not change the result graph = parse_dag(joinpath(@__DIR__, "..", "input", "AB->ABBB.txt"), ABCModel()) - @test isapprox(execute(graph, process_2_4, machine, particles_2_4), expected_result; rtol = 0.001) + @test isapprox(execute(graph, process_2_4, machine, particles_2_4), expected_result; rtol = RTOL) func = get_compute_function(graph, process_2_4, machine) - @test isapprox(func(particles_2_4), expected_result; rtol = 0.001) + @test isapprox(func(particles_2_4), expected_result; rtol = RTOL) end end @testset "AB->ABBB after random walk" begin - for i in 1:200 + for i in 1:50 graph = parse_dag(joinpath(@__DIR__, "..", "input", "AB->ABBB.txt"), ABCModel()) random_walk!(graph, 100) @test is_valid(graph) - @test isapprox(execute(graph, process_2_4, machine, particles_2_4), expected_result; rtol = 0.001) + @test isapprox(execute(graph, process_2_4, machine, particles_2_4), expected_result; rtol = RTOL) end end @@ -105,8 +147,8 @@ include("../examples/profiling_utilities.jl") # try execute @test is_valid(graph) - expected_result = 0.00013916495566048735 - @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = 0.001) + expected_result = ground_truth_graph_result(particles_2_2) + @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = RTOL) end @@ -135,8 +177,8 @@ include("../examples/profiling_utilities.jl") # try execute @test is_valid(graph) - expected_result = 0.00013916495566048735 - @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = 0.001) + expected_result = ground_truth_graph_result(particles_2_2) + @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = RTOL) end @testset "AB->AB fusion edge case" for _ in 1:20 @@ -169,8 +211,8 @@ include("../examples/profiling_utilities.jl") # try execute @test is_valid(graph) - expected_result = 0.00013916495566048735 - @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = 0.001) + expected_result = ground_truth_graph_result(particles_2_2) + @test isapprox(execute(graph, process_2_2, machine, particles_2_2), expected_result; rtol = RTOL) end end