25 Algorithm Lab — When Algorithms Compete
25.1 Subtitle
Benchmarking competing algorithm choices under realistic workload shapes.
Lab Focus Run controlled experiments, collect evidence, and compare algorithm choices under explicit assumptions.
25.2 Why This Lab Exists
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:
- Which algorithm wins for our workload profile?
- Where does each algorithm break down?
- Which assumptions must hold for the chosen strategy?
25.3 Lab Objectives
By the end of this lab, you should be able to:
- compare competing algorithms for the same requirement
- evaluate normal-case vs adverse-case behavior
- separate asymptotic reasoning from measured behavior
- justify a strategy choice with explicit tradeoffs
25.4 Competition Setup
Use one concrete problem:
“Find the shortest path from A to G in an unweighted graph.”
Competing strategies:
- DFS-style search (finds a path, not guaranteed shortest by hops)
- BFS-style search (guarantees minimum hops in unweighted graphs)
Why this setup works:
- same input graph
- same success/failure contract
- different quality/cost behavior
25.5 Nex Implementation
Suggested files:
algorithm_lab_2.nexalgorithm_lab_2_main.nex
If using the web IDE, place everything in one file and run App.run.
25.5.2 Graph Fixture
class 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
25.5.3 DFS-Style Competitor
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
25.5.4 BFS-Style Competitor
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
25.5.5 Driver: Run Competitions
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:
- both may find paths in nominal case
- BFS-style competitor returns shorter route in default fixture
- DFS-style competitor can return longer-but-valid route depending on branch order
25.6 Lab Tasks
25.6.1 Task A — Nominal Competition
Run both competitors on the default graph and record:
- found/unreachable status
- returned path
- hop count
- step count
25.6.2 Task B — Workload Variation
Modify graph shape and rerun:
- remove one shortcut edge
- add one distracting dead-end edge
Document which strategy is more sensitive to each change.
25.6.3 Task C — Constraint Stress
Introduce an explicit depth cap and evaluate:
- when DFS fails due to depth bound
- when BFS frontier growth becomes expensive
25.7 Decision Template
Use this template for final strategy choice:
- problem objective (reachability or shortest path)
- dominant workload shape
- correctness requirement (any path vs best path)
- preferred algorithm and why
- fallback strategy under stress
25.8 Deliverables
- runnable Nex code for both competitors
- experiment table across at least 3 graph variants
- one-page decision note with selected strategy
- explicit list of assumptions that must remain true
25.9 Forward Link
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.