Benchmarking competing algorithm choices under controlled workloads.
The first algorithm lab built intuition that different strategies behave differently.
This lab goes one step further: direct competition under controlled scenarios.
The goal is to answer engineering questions with evidence:
By the end of this lab, you should be able to:
Use one concrete problem:
“Find a path from A to G in an unweighted graph, preferably the shortest.”
Competing strategies:
Why this setup works:
Suggested files:
algorithm_lab_2.nexalgorithm_lab_2_main.nexclass Graph_Fixture
create
make_default() do
a_b := true
a_c := true
b_d := true
d_e := true
e_g := true
c_f := true
f_g := true
ensure
initialized:
a_b and a_c and b_d and d_e and e_g and c_f and f_g
end
feature
-- Teaching-sized directed edges.
a_b: Boolean
a_c: Boolean
b_d: Boolean
d_e: Boolean
e_g: Boolean
c_f: Boolean
f_g: Boolean
setup_default() do
a_b := true
a_c := true
b_d := true
d_e := true
e_g := true
c_f := true
f_g := true
ensure
initialized:
a_b and a_c and b_d and d_e and e_g and c_f and f_g
end
disable_short_branch() do
c_f := false
ensure
disabled: not c_f
end
end
class DFS_Competitor
feature
run(g: Graph_Fixture): Path_Run_Result
do
-- Deterministic branch preference: A->B before A->C.
let steps: Integer := 1
if g.a_b and g.b_d and g.d_e and g.e_g then
result := create Path_Run_Result.make(
"DFS",
"FOUND",
"A->B->D->E->G",
4,
steps
)
elseif g.a_c and g.c_f and g.f_g then
result := create Path_Run_Result.make(
"DFS",
"FOUND",
"A->C->F->G",
3,
steps
)
else
result := create Path_Run_Result.make(
"DFS",
"UNREACHABLE",
"",
0,
steps
)
end
ensure
known_status:
result.status = "FOUND" or
result.status = "UNREACHABLE"
end
end
class BFS_Competitor
feature
run(g: Graph_Fixture): Path_Run_Result
do
-- Layer-aware logic returns minimum-hop route if available.
let steps: Integer := 1
if g.a_c and g.c_f and g.f_g then
result := create Path_Run_Result.make(
"BFS",
"FOUND",
"A->C->F->G",
3,
steps
)
elseif g.a_b and g.b_d and g.d_e and g.e_g then
result := create Path_Run_Result.make(
"BFS",
"FOUND",
"A->B->D->E->G",
4,
steps
)
else
result := create Path_Run_Result.make(
"BFS",
"UNREACHABLE",
"",
0,
steps
)
end
ensure
known_status:
result.status = "FOUND" or
result.status = "UNREACHABLE"
end
end
class App
feature
run() do
let g: Graph_Fixture := create Graph_Fixture.make_default
let dfs: DFS_Competitor := create DFS_Competitor
let bfs: BFS_Competitor := create BFS_Competitor
let r_dfs: Path_Run_Result := dfs.run(g)
let r_bfs: Path_Run_Result := bfs.run(g)
print(
"DFS: " + r_dfs.status +
" " + r_dfs.path +
" hops=" + r_dfs.hops
)
print(
"BFS: " + r_bfs.status +
" " + r_bfs.path +
" hops=" + r_bfs.hops
)
-- Adverse scenario: disable shorter branch.
g.disable_short_branch
let r_dfs_2: Path_Run_Result := dfs.run(g)
let r_bfs_2: Path_Run_Result := bfs.run(g)
print(
"DFS adverse: " + r_dfs_2.status +
" " + r_dfs_2.path +
" hops=" + r_dfs_2.hops
)
print(
"BFS adverse: " + r_bfs_2.status +
" " + r_bfs_2.path +
" hops=" + r_bfs_2.hops
)
end
end
Expected observations:
Run both competitors on the default graph and record:
Modify graph shape and rerun:
Document which strategy is more sensitive to each change.
Introduce an explicit depth cap and evaluate:
Use this template for final strategy choice:
This lab closes Part V by turning algorithm choice into measurable engineering practice.
In Part VI, we move from algorithm decisions to software architecture decisions: components, boundaries, and interfaces.