-module(internal@bench@bench_utils). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/internal/bench/bench_utils.gleam"). -export([size_to_nodes/1, density_to_probability/1, random_graph/3, grid_graph/2, complete_graph/1, random_dag/2, bipartite_graph/2, format_time/1, graph_stats/1]). -export_type([graph_size/0, graph_density/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type graph_size() :: small | medium | large | x_large. -type graph_density() :: sparse | medium_density | dense. -file("src/internal/bench/bench_utils.gleam", 19). -spec size_to_nodes(graph_size()) -> integer(). size_to_nodes(Size) -> case Size of small -> 100; medium -> 1000; large -> 10000; x_large -> 100000 end. -file("src/internal/bench/bench_utils.gleam", 35). -spec density_to_probability(graph_density()) -> float(). density_to_probability(Density) -> case Density of sparse -> 0.01; medium_density -> 0.05; dense -> 0.2 end. -file("src/internal/bench/bench_utils.gleam", 47). ?DOC(" Generate a random graph for benchmarking\n"). -spec random_graph(graph_size(), graph_density(), integer()) -> yog@model:graph(nil, integer()). random_graph(Size, Density, _) -> Nodes = size_to_nodes(Size), Prob = density_to_probability(Density), yog@generators@random:erdos_renyi_gnp(Nodes, Prob). -file("src/internal/bench/bench_utils.gleam", 58). ?DOC(" Generate a grid graph (useful for pathfinding benchmarks)\n"). -spec grid_graph(integer(), integer()) -> yog@model:graph(nil, integer()). grid_graph(Width, Height) -> Graph = yog:undirected(), Graph@1 = begin _pipe = yog@internal@utils:range(0, (Width * Height) - 1), gleam@list:fold( _pipe, Graph, fun(G, Id) -> yog:add_node(G, Id, nil) end ) end, _pipe@1 = yog@internal@utils:range(0, Height - 1), gleam@list:fold( _pipe@1, Graph@1, fun(G@1, Y) -> _pipe@2 = yog@internal@utils:range(0, Width - 1), gleam@list:fold( _pipe@2, G@1, fun(Gg, X) -> Node = (Y * Width) + X, Gg@1 = case X < (Width - 1) of true -> yog:add_edge(Gg, Node, Node + 1, 1); false -> Gg end, case Y < (Height - 1) of true -> yog:add_edge(Gg@1, Node, Node + Width, 1); false -> Gg@1 end end ) end ). -file("src/internal/bench/bench_utils.gleam", 85). ?DOC(" Generate a complete graph for worst-case testing\n"). -spec complete_graph(integer()) -> yog@model:graph(nil, integer()). complete_graph(Nodes) -> yog@generators@classic:complete(Nodes). -file("src/internal/bench/bench_utils.gleam", 90). ?DOC(" Generate a DAG for topological sort benchmarks\n"). -spec random_dag(integer(), integer()) -> yog@model:graph(nil, integer()). random_dag(Nodes, Seed) -> Graph = yog:directed(), Graph@1 = begin _pipe = yog@internal@utils:range(0, Nodes - 1), gleam@list:fold( _pipe, Graph, fun(G, Id) -> yog:add_node(G, Id, nil) end ) end, _pipe@1 = yog@internal@utils:range(0, Nodes - 1), gleam@list:fold( _pipe@1, Graph@1, fun(G@1, From) -> _pipe@2 = yog@internal@utils:range(From + 1, Nodes - 1), gleam@list:fold( _pipe@2, G@1, fun(Gg, To) -> Should_add = ((((From * 31) + (To * 17)) + Seed) rem 10) < 3, case Should_add of true -> yog:add_edge(Gg, From, To, 1); false -> Gg end end ) end ). -file("src/internal/bench/bench_utils.gleam", 114). ?DOC(" Generate a bipartite graph for matching benchmarks\n"). -spec bipartite_graph(integer(), integer()) -> yog@model:graph(nil, integer()). bipartite_graph(Left_nodes, Right_nodes) -> yog@generators@classic:complete_bipartite(Left_nodes, Right_nodes). -file("src/internal/bench/bench_utils.gleam", 127). -spec float_to_string(float()) -> binary(). float_to_string(F) -> Rounded = begin _pipe = F, _pipe@1 = erlang:round(_pipe), erlang:integer_to_binary(_pipe@1) end, Rounded. -file("src/internal/bench/bench_utils.gleam", 119). ?DOC(" Format benchmark results for display\n"). -spec format_time(float()) -> binary(). format_time(Microseconds) -> case {Microseconds < 1000.0, Microseconds < 1000000.0} of {true, _} -> <<(float_to_string(Microseconds))/binary, " μs"/utf8>>; {false, true} -> <<(float_to_string(Microseconds / 1000.0))/binary, " ms"/utf8>>; {false, false} -> <<(float_to_string(Microseconds / 1000000.0))/binary, " s"/utf8>> end. -file("src/internal/bench/bench_utils.gleam", 134). ?DOC(" Extract graph statistics for reporting\n"). -spec graph_stats(yog@model:graph(any(), any())) -> {integer(), integer()}. graph_stats(Graph) -> Nodes = begin _pipe = yog:all_nodes(Graph), erlang:length(_pipe) end, Edge_count = case Graph of {graph, Kind, _, Out_edges, _} -> _pipe@1 = gleam@dict:fold( Out_edges, 0, fun(Count, _, To_edges) -> Count + maps:size(To_edges) end ), (fun(C) -> case Kind of undirected -> C; directed -> C end end)(_pipe@1) end, {Nodes, Edge_count}.