Skip to content

Commit 91df9bc

Browse files
pratzlPhil Ratzloff
andauthored
Algo paper (#10)
* Implement doc_revision_plan: standardize algorithm docs and headers Doc pages (all 13 algorithms): - Add Postconditions, Throws, Remarks sections per C++26 vocabulary - Add concept constraints to Parameters tables (G6) - Rename Notes → Remarks on 5 pages (G1) - Update TOC with new sections (G7) - Expand Returns semantics for non-void algorithms (G5) Header changes: - H1: Normalize exception doc format across all 13 headers - H2: Align postcondition annotations with doc pages - H3: Add [[nodiscard]] to topological_sort (3 overloads) and triangle_count - H4: Add noexcept to triangle_count (tc.hpp) Supporting files: - New: agents/function_semantics.md, agents/doc_revision_plan.md - Updated: agents/algorithm_doc_guide.md (added section templates) - Archived: obsolete agent docs → agents/archive/ * Normalize line endings in .vscode/settings.json --------- Co-authored-by: Phil Ratzloff <phil.ratzloff@sas.com>
1 parent 7db942f commit 91df9bc

11 files changed

Lines changed: 754 additions & 62 deletions

.vscode/settings.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
{
2-
"cmake.configureOnOpen": false,
3-
"cmake.preferredGenerators": [
4-
"Ninja"
5-
],
6-
"cmake.generator": "Ninja",
7-
"cmake.cmakePath": "cmake"
8-
}
1+
{
2+
"cmake.configureOnOpen": false,
3+
"cmake.preferredGenerators": [
4+
"Ninja"
5+
],
6+
"cmake.generator": "Ninja",
7+
"cmake.cmakePath": "cmake"
8+
}

agents/algorithm_doc_guide.md

Lines changed: 104 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ are included only when the algorithm has the relevant feature.
4646
- [Examples](#examples)
4747
- [Complexity](#complexity)
4848
- [Preconditions](#preconditions)
49-
- [Notes](#notes) ← (if applicable)
49+
- [Postconditions](#postconditions) ← (if applicable)
50+
- [Throws](#throws) ← (if applicable)
51+
- [Error Conditions](#error-conditions) ← (if applicable)
52+
- [Remarks](#remarks) ← (if applicable)
5053
- [See Also](#see-also)
5154
```
5255

@@ -56,9 +59,10 @@ are included only when the algorithm has the relevant feature.
5659
Components has 3 algorithms): Replace the single Signature/Parameters
5760
sections with per-algorithm subsections under an `## Algorithms` or
5861
named `## Kruskal's Algorithm` / `## Prim's Algorithm` pattern.
59-
- **Visitor Events**: Include this section only for algorithms that accept a
60-
visitor (currently: Dijkstra, Bellman-Ford, BFS, DFS).
61-
- **Notes**: Include when there are important behavioral details that don't
62+
- **Visitor Events**: Include this section for any algorithm whose signature
63+
accepts a `Visitor` parameter. Check the actual header; do not rely on a
64+
fixed list of algorithm names.
65+
- **Remarks**: Include when there are important behavioral details that don't
6266
fit in Preconditions (e.g., self-loop handling differences, in-place
6367
modification warnings, convergence properties).
6468

@@ -98,8 +102,11 @@ are included only when the algorithm has the relevant feature.
98102
- Show all public overloads in a single fenced C++ code block.
99103
- Include `constexpr`, `[[nodiscard]]`, and template constraints if present in
100104
the actual header.
101-
- After the code block, document the **return type** in bold if non-void
102-
(e.g., "**Returns** `std::pair<EV, size_t>` — total weight and component count.").
105+
- After the code block, document the **return type and return value semantics**
106+
in bold if non-void: state the type, its value category, and what it
107+
represents, including any sentinel values (e.g., "**Returns**
108+
`std::pair<EV, size_t>` — the total MST edge weight and the number of edges
109+
included. Returns `{EV{}, 0}` if the graph has no edges.").
103110
- Use "Signature" (singular) if there is only one overload; "Signatures" (plural)
104111
if there are multiple.
105112

@@ -110,6 +117,9 @@ are included only when the algorithm has the relevant feature.
110117
- Note default values inline (e.g., "Default: `std::less<>{}`").
111118
- For output parameters, state the sizing requirement
112119
(e.g., "Random-access range sized to `num_vertices(g)`").
120+
- For template parameters, document the concept requirements (e.g.,
121+
"`G` must satisfy `index_adjacency_list<G>`; `WF` must be callable as
122+
`WF(edge_reference_t<G>) -> EV`").
113123

114124
### Visitor Events (if applicable)
115125

@@ -119,7 +129,10 @@ are included only when the algorithm has the relevant feature.
119129

120130
### Examples
121131

122-
**Quantity**: At minimum 5 examples per page. More is acceptable and
132+
**Quantity**: At minimum 5 examples per page. This minimum ensures coverage
133+
of: the basic happy path, at least one additional overload or mode, a
134+
topology-specific case that illuminates algorithm properties, an advanced
135+
feature, and one edge case or real-world scenario. More is acceptable and
123136
encouraged when the algorithm has multiple overloads, modes, or edge cases.
124137

125138
**Progressive complexity**: Order examples from simplest to most advanced:
@@ -178,6 +191,18 @@ One-sentence explanation of what this example demonstrates and *why* it matters.
178191

179192
### Preconditions
180193

194+
This section covers **three kinds of requirements** that the C++ standard
195+
distinguishes separately, presented here as a unified list for users:
196+
197+
- *Constraints* — template conditions enforced silently at overload resolution
198+
(the function is simply not viable if unsatisfied).
199+
- *Mandates* — conditions whose violation makes the program ill-formed
200+
(`static_assert` or similar; a compiler diagnostic is issued).
201+
- *Preconditions* — runtime conditions whose violation causes undefined behavior.
202+
203+
Document all three as a single bullet list; users need to know what must hold
204+
before calling the function, regardless of which category applies.
205+
181206
- Bullet list of every requirement the caller must satisfy.
182207
- Always include the `index_adjacency_list<G>` requirement.
183208
- For undirected graph algorithms, state: "For undirected graphs, **both
@@ -186,7 +211,50 @@ One-sentence explanation of what this example demonstrates and *why* it matters.
186211
- Mention self-loop behavior, valid vertex ID ranges, and sizing requirements
187212
for output containers.
188213

189-
### Notes (if applicable)
214+
### Postconditions (if applicable)
215+
216+
Include this section when the algorithm writes results into caller-supplied
217+
output ranges or produces a return value whose state needs precise
218+
specification beyond a single sentence in Signatures.
219+
220+
- Bullet list of conditions established by the function upon successful return.
221+
- Focus on output ranges: state what every element contains after the call
222+
(e.g., "`distances[v]` holds the shortest-path distance from `source` to `v`,
223+
or `numeric_limits<EV>::max()` if `v` is unreachable.").
224+
- State the postcondition for the return value here if it is too detailed for
225+
the Signatures section.
226+
- Omit this section if postconditions are fully captured by the Returns
227+
description and output-parameter notes in Parameters.
228+
229+
### Throws (if applicable)
230+
231+
Include this section when the algorithm can throw exceptions.
232+
233+
- Bullet list of exception types and the conditions that cause each one.
234+
- Always state the exception guarantee: **strong** (no observable effects on
235+
failure), **basic** (output is in a valid but unspecified state), or **none**.
236+
- If the algorithm is `noexcept` or only propagates exceptions from
237+
user-supplied callables, state that explicitly (e.g., "Does not throw
238+
directly; exceptions from `wf` or `visitor` callbacks are propagated
239+
unchanged. No partial results are written (strong guarantee).").
240+
241+
### Error Conditions (if applicable)
242+
243+
Include this section only for algorithms that report errors via
244+
`std::error_code` or `std::expected` rather than (or in addition to)
245+
exceptions.
246+
247+
- Bullet list of `std::errc` constants (or domain-specific codes) the
248+
algorithm can set, with a brief explanation of each condition.
249+
- Note whether errors are reported via a return value or an output parameter.
250+
- Omit this section entirely if the algorithm never reports errors by error
251+
code.
252+
253+
### Remarks (if applicable)
254+
255+
This section uses the term **Remarks** from the C++ standard function-semantics
256+
vocabulary: additional semantic constraints or behavioral details that don't
257+
belong in Preconditions, Postconditions, or Throws.
190258

191259
- Bullet list of behavioral details, caveats, or design decisions.
192260
- Good candidates: in-place modification warnings, self-loop counting behavior
@@ -246,8 +314,11 @@ When creating a documentation page for a new algorithm:
246314
- Template constraints and concepts
247315
- `constexpr`, `[[nodiscard]]`, and other attributes
248316
- Default parameter values
249-
- Return types
317+
- Return types and return value semantics (including sentinel values)
250318
- Visitor event names (if any)
319+
- `noexcept` specifiers and any documented exception types
320+
- Error codes reported via `std::error_code` or `std::expected` (if any)
321+
- Postconditions on output ranges (from comments or contracts, if present)
251322

252323
2. **Read the test file** (`tests/algorithms/test_xxx.cpp`) to identify:
253324
- Graph topologies tested (star, path, cycle, complete, disconnected, etc.)
@@ -273,9 +344,15 @@ When creating a documentation page for a new algorithm:
273344
- The `index_adjacency_list<G>` requirement is stated in Overview and
274345
Preconditions.
275346
- All cross-links resolve (test by checking file paths).
276-
- At least 5 examples are provided.
347+
- At least 5 examples are provided, covering each overload and at least one
348+
edge case.
277349
- Examples progress from simple to advanced.
278350
- Expected output values are shown in comments for every example.
351+
- Throws section is present if the algorithm can throw, and states the
352+
exception guarantee; absent (or noted as `noexcept`) otherwise.
353+
- Postconditions section is present if output-range postconditions are not
354+
fully covered by the Parameters and Returns descriptions.
355+
- Error Conditions section is present if the algorithm uses `std::error_code`.
279356

280357
---
281358

@@ -284,16 +361,16 @@ When creating a documentation page for a new algorithm:
284361
Use these as models. The pages vary slightly based on algorithm features but
285362
all follow the structure above.
286363

287-
| Page | Notable features to model |
288-
|------|---------------------------|
289-
| `dijkstra.md` | Multiple overloads, visitor events, `constexpr` signatures, `_id` variant examples, error handling note |
290-
| `bellman_ford.md` | `[[nodiscard]]` attribute, `find_negative_cycle` helper, unique visitor events (`on_edge_minimized`) |
291-
| `dfs.md` | Richest visitor events (9), single-source limitation note, subtree computation example |
292-
| `connected_components.md` | Multi-algorithm structure (3 sub-algorithms), `compress()` helper, per-algorithm selection guidance |
293-
| `mst.md` | Two distinct algorithms (Kruskal + Prim) with separate signatures, `inplace_kruskal` modification warning, cross-validation example |
294-
| `label_propagation.md` | RNG parameter, convergence notes, self-loop counting behavior, reproducibility example |
295-
| `triangle_count.md` | Additional concept requirement (`ordered_vertex_edges`), pre-sorting workaround example |
296-
| `mis.md` | Seed sensitivity, maximal vs. maximum distinction, self-loop exclusion |
364+
| Page | Notable features to model |
365+
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
366+
| `dijkstra.md` | Multiple overloads, visitor events, `constexpr` signatures, `_id` variant examples, error handling note |
367+
| `bellman_ford.md` | `[[nodiscard]]` attribute, `find_negative_cycle` helper, unique visitor events (`on_edge_minimized`) |
368+
| `dfs.md` | Richest visitor events (9), single-source limitation note, subtree computation example |
369+
| `connected_components.md` | Multi-algorithm structure (3 sub-algorithms), `compress()` helper, per-algorithm selection guidance |
370+
| `mst.md` | Two distinct algorithms (Kruskal + Prim) with separate signatures, `inplace_kruskal` modification warning, cross-validation example |
371+
| `label_propagation.md` | RNG parameter, convergence notes, self-loop counting behavior, reproducibility example |
372+
| `triangle_count.md` | Additional concept requirement (`ordered_vertex_edges`), pre-sorting workaround example |
373+
| `mis.md` | Seed sensitivity, maximal vs. maximum distinction, self-loop exclusion |
297374

298375
---
299376

@@ -315,3 +392,10 @@ all follow the structure above.
315392
assume based on other algorithms.
316393
- **Don't forget to update the catalog** — the landing page at
317394
`docs/user-guide/algorithms.md` must list every algorithm with complexity.
395+
- **Don't omit Throws** — if an algorithm can throw, document it with the
396+
exception guarantee; if it is `noexcept` or only propagates user-callable
397+
exceptions, state that explicitly.
398+
- **Don't confuse Preconditions and Postconditions** — Preconditions are what
399+
must hold *before* the call; Postconditions describe the output state *after*.
400+
- **Don't omit Error Conditions** — if the algorithm returns `std::error_code`
401+
or uses `std::expected`, document the error codes in their own section.

0 commit comments

Comments
 (0)