Skip to content

Fix #288: [Model] LongestPath#734

Merged
isPANN merged 7 commits intomainfrom
issue-288
Mar 22, 2026
Merged

Fix #288: [Model] LongestPath#734
isPANN merged 7 commits intomainfrom
issue-288

Conversation

@GiggleLiu
Copy link
Copy Markdown
Contributor

Summary

Add the implementation plan and execution branch for LongestPath, including the model, ILP solver path, CLI/example wiring, and paper coverage.

Fixes #288

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 21, 2026

Codecov Report

❌ Patch coverage is 99.78992% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 97.60%. Comparing base (e770c59) to head (c9a088c).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/models/graph/longest_path.rs 99.40% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #734      +/-   ##
==========================================
+ Coverage   97.57%   97.60%   +0.02%     
==========================================
  Files         423      427       +4     
  Lines       52346    52822     +476     
==========================================
+ Hits        51077    51557     +480     
+ Misses       1269     1265       -4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@GiggleLiu
Copy link
Copy Markdown
Contributor Author

Implementation Summary

Changes

  • Added the LongestPath graph model in src/models/graph/longest_path.rs, registered it through the model exports, and supplied a canonical example plus dedicated model tests.
  • Added CLI creation support for LongestPath in problemreductions-cli/src/commands/create.rs and documented its flags in problemreductions-cli/src/cli.rs.
  • Added the LongestPath -> ILP reduction in src/rules/longestpath_ilp.rs with canonical rule example coverage and closed-loop ILP tests.
  • Added paper documentation for the new model and its ILP reduction in docs/paper/reductions.typ.

Deviations From Plan

  • The plan sketched an ILP<bool> target, but the implemented solver rule uses ILP<i32> because the reduction needs integer order variables to encode path positions and eliminate cycles.
  • The issue comments clarified the model should be the optimization version, so the implementation follows that maintainer guidance directly.

Open Questions

  • None.

@GiggleLiu
Copy link
Copy Markdown
Contributor Author

Agentic Review Report

Structural Check

Structural Review: model+rule LongestPath

Structural Completeness

# Check Status
M1 Model file exists PASS — src/models/graph/longest_path.rs present
M2 inventory::submit! present PASS
M3 Serialize/Deserialize derive present PASS
M4 Problem trait impl present PASS
M5 OptimizationProblem impl present PASS
M6 Test link present in model file PASS
M7 Model test file exists PASS — src/unit_tests/models/graph/longest_path.rs
M8 Model test count >= 3 PASS — 10 tests
M9 Registered in src/models/graph/mod.rs PASS
M10 Re-exported in src/models/mod.rs PASS
M11 declare_variants! entry exists PASS
M12 CLI name resolution support PASS — registry-backed resolution covers LongestPath
M13 CLI create support PASS
M14 Canonical model example registered PASS
M15 Paper display-name entry PASS
M16 Paper problem-def block PASS
R1 Rule file exists PASS — src/rules/longestpath_ilp.rs present
R2 #[reduction(...)] macro present PASS
R3 ReductionResult impl present PASS
R4 ReduceTo impl present PASS
R5 Test link present in rule file PASS
R6 Rule test file exists PASS — src/unit_tests/rules/longestpath_ilp.rs
R7 Closed-loop test present PASS
R8 Registered in src/rules/mod.rs PASS
R9 Canonical rule example registered PASS
R10 Example-db lookup tests exist in repo PASS — src/unit_tests/example_db.rs covers rule db/lookups
R11 Paper reduction-rule entry PASS
B1 No blacklisted autogenerated files committed PASS

Build Status

  • make test: PASS
  • make clippy: PASS

Semantic Review

  • LongestPath::evaluate(): OK — validates the config before summing edge lengths and returns SolutionSize::Invalid for infeasible selections.
  • LongestPath::dims(): OK — one binary variable per edge.
  • Size getters / metadata: OK — num_vertices and num_edges match the declared complexity and overhead fields.
  • Weight handling: OK — edge lengths are stored and validated through inherent methods, matching repo conventions.
  • Reduction correctness: OK — the flow-balance + degree + edge-exclusivity + MTZ order constraints encode exactly one simple directed s-t path, and extract_solution() correctly projects selected arcs back to undirected edge picks.
  • Overhead accuracy: OK — construction yields 2m + n variables and 5m + 4n + 1 constraints, matching the macro.
  • Example / paper proof quality: OK — the paper statement and proof sketch match the implemented formulation and the canonical witness is consistent with the code.

Issue Compliance

# Check Status
1 Problem name matches issue OK
2 Mathematical definition matches OK
3 Problem type (optimization) matches OK
4 Type parameters match OK
5 Configuration space matches OK
6 Feasibility check matches OK
7 Objective function matches OK
8 Complexity matches issue intent OK

Summary

  • 28/28 structural checks passed.
  • 8/8 issue-compliance checks passed.
  • No structural or mathematical issues found.

Quality Check

Quality Review

Design Principles

  • DRY: OK — the new model, reduction, CLI plumbing, and paper entry follow existing project patterns without obvious duplicated logic worth extracting.
  • KISS: OK — both the path validator and the ILP formulation are direct and easy to audit.
  • HC/LC: OK — responsibilities stay separated across model logic, reduction logic, CLI creation, and documentation.

HCI (if CLI/MCP changed)

  • Error messages: OK — pred create LongestPath reports missing/invalid flags with concrete usage examples.
  • Discoverability: ISSUE — the new ILP route is only discoverable as ILP/i32. pred show LongestPath reveals that, but bare pred path LongestPath ILP and pred reduce <instance> --to ILP both fail in the current worktree even though the feature is otherwise functional.
  • Consistency: ISSUE — pred solve <longest-path-instance> auto-selects the ILP route and reports "reduced_to": "ILP", but the equivalent explicit --to ILP commands are rejected.
  • Least surprise: ISSUE — users can reasonably infer from the solver output that ILP is an accepted explicit target, but it is not for this new route.
  • Feedback: OK — successful create / solve / reduce commands produce clear outputs and preserved evaluations.

Test Quality

  • Naive test detection: OK
    • Model tests cover construction, valid/invalid evaluation, brute-force optimality, serialization, and boundary checks.
    • Rule tests cover ILP shape, closed-loop solving, handcrafted extraction, and the source == target edge case.

Issues

Critical (Must Fix)

None.

Important (Should Fix)

  • The new LongestPath -> ILP feature is not reachable through the CLI’s bare canonical target name. Reproduced in the current worktree: pred path LongestPath ILP and pred reduce <instance> --to ILP fail, while pred path LongestPath ILP/i32, pred reduce ... --to ILP/i32, and pred solve <instance> all succeed. This is a user-facing discoverability/consistency gap around the new route introduced at src/rules/longestpath_ilp.rs:58.

Minor (Nice to Have)

None.

Summary

  • Design and test coverage are solid.
  • One confirmed CLI/HCI issue remains around explicit target selection for the new ILP route.

Agentic Feature Tests

Agentic Feature Test Report: LongestPath

Test Results

  • pred list: PASS — LongestPath/SimpleGraph/i32, LongestPath/SimpleGraph/One, ILP/bool, and ILP/i32 all appear in the catalog.
  • pred show LongestPath: PASS — model metadata renders correctly and the outgoing reduction is shown as ILP/i32.
  • pred create --example LongestPath -o longest-path.json: PASS — example instance was created successfully.
  • pred solve longest-path.json: PASS — returned Valid(20) with the expected optimal configuration.
  • pred path LongestPath ILP: FAIL — confirmed. CLI returns Error: No reduction path from LongestPath to ILP.
  • pred path LongestPath ILP/i32: PASS — one-step path shown.
  • pred reduce longest-path.json --to ILP/i32 -o bundle.json: PASS — reduction bundle written successfully.
  • pred solve bundle.json: PASS — intermediate ILP evaluates to Valid(20.0) and the extracted LongestPath solution evaluates to Valid(20).
  • pred reduce longest-path.json --to ILP: FAIL — confirmed. CLI returns Error: No reduction path from LongestPath to ILP.

Findings

  • Confirmed, Important: bare canonical target ILP does not work for the new reduction path; users must know to spell the non-default variant ILP/i32 even though pred solve reports the solver target generically as ILP.
    • Reproduction: current PR worktree.
    • Recommended fix: either let explicit canonical-target resolution pick the reachable ILP variant here, or emit a targeted hint suggesting ILP/i32 when canonical ILP fails.

Summary

  • Core functionality works end-to-end.
  • One confirmed discoverability/consistency issue remains for the explicit CLI route to ILP.

Generated by review-pipeline

@GiggleLiu
Copy link
Copy Markdown
Contributor Author

Agentic Review Report

Structural Check

Structural Review: model+rule LongestPath / longestpath_ilp

Structural Completeness

# Check Status
1 Model file exists PASS
2 inventory::submit! present PASS
3 Serialize / Deserialize derive on model struct PASS
4 Problem trait impl for LongestPath PASS
5 OptimizationProblem impl for LongestPath PASS
6 Model file links its unit test module PASS
7 Model test file exists PASS
8 Model test file has at least 3 tests PASS — 10 tests
9 Registered in src/models/graph/mod.rs PASS
10 Re-exported in src/models/mod.rs PASS
11 declare_variants! entry exists PASS
12 CLI name resolution supports the model PASS — registry-backed alias resolution is pass-through for canonical names
13 CLI create support exists PASS
14 Canonical model example registered PASS
15 Paper display-name entry exists PASS
16 Paper problem-def block exists PASS
17 Rule file exists PASS
18 #[reduction(...)] macro present PASS
19 ReductionResult impl present PASS
20 ReduceTo impl present PASS
21 Rule file links its unit test module PASS
22 Rule test file exists PASS
23 Closed-loop rule test present PASS
24 Registered in src/rules/mod.rs PASS
25 Canonical rule example registered PASS
26 Example-db lookup coverage exists PASS — generic example-db tests cover model/rule builders
27 Paper reduction-rule entry exists PASS
28 Blacklisted autogenerated files absent PASS

Build Status

  • make test: PASS
  • make clippy: PASS

Semantic Review

  • LongestPath::evaluate: OK — validity is checked before summing weights, invalid configs return Invalid, and the source == target empty-path edge case is covered.
  • LongestPath::dims: OK — one binary variable per edge, matching the issue’s configuration-space description.
  • Weight handling: OK — lengths are stored via inherent methods and converted through WeightElement::to_sum().
  • LongestPath -> ILP<i32> construction: OK — flow balance, in/out degree bounds, edge exclusivity, and MTZ-style order constraints encode exactly one simple directed s-t path.
  • Overhead expressions: OK — manual count matches 2m + n variables and 5m + 4n + 1 constraints.
  • extract_solution: OK — oriented arc selections are correctly projected back to one bit per undirected edge.
  • Paper proof sketch: OK — both directions are stated and the cycle-elimination argument is sound.

Issue Compliance (if linked issue found)

# Check Status
1 Problem name matches issue OK
2 Mathematical definition matches OK
3 Optimization framing matches linked-issue follow-up OK
4 Type parameters and schema fields match OK
5 Configuration space matches OK
6 Feasibility check matches OK
7 Objective function matches OK
8 Complexity metadata matches issue intent OK
9 ILP solver path requested in issue comments is implemented OK
10 Reduction construction matches the documented flow/order formulation OK
11 Solution extraction matches selected-edge semantics OK
12 Overhead formulas match the actual construction OK

Summary

  • 28/28 structural checks passed
  • 12/12 issue compliance checks passed
  • No structural or mathematical correctness issues found

Quality Check

Quality Review

Design Principles

  • DRY: OK — the model and reduction mostly follow existing graph/ILP patterns without introducing duplicate core logic.
  • KISS: OK — the validity predicate and ILP construction are direct and proportional to the problem.
  • HC/LC: OK — problem logic, reduction logic, CLI wiring, and tests remain separated cleanly.

HCI (if CLI/MCP changed)

  • Error messages: OK — validation failures include concrete usage strings.
  • Discoverability: ISSUE — pred create LongestPath prints --edge-weights in its problem-specific help even though the implementation and examples require --edge-lengths. This happens because help_flag_name() still rewrites edge_lengths to edge-weights by default in problemreductions-cli/src/commands/create.rs:701, and there is no LongestPath-specific override alongside the existing special cases in problemreductions-cli/src/commands/create.rs:667.
  • Consistency: ISSUE — the global create help in problemreductions-cli/src/cli.rs says LongestPath uses --edge-lengths, but the per-problem help path contradicts it.
  • Least surprise: ISSUE — the most discoverable interactive help flow (pred create LongestPath) tells users to use a flag that the handler does not accept.
  • Feedback: OK — successful create/solve/reduce flows report outputs clearly.

Test Quality

  • Naive test detection: ISSUE
    • The new CLI tests in problemreductions-cli/src/commands/create.rs:5830 only cover serialization and argument-validation paths. They never exercise the zero-argument help flow (pred create LongestPath), so the incorrect help-flag mapping slips through. Existing global create-help coverage in problemreductions-cli/src/cli.rs:842 does not cover per-problem help rendering.

Issues

Critical (Must Fix)

None.

Important (Should Fix)

  • pred create LongestPath advertises the wrong flag in its problem-specific help. Repro: cargo run -p problemreductions-cli --bin pred --release -- create LongestPath. Current output shows --edge-weights for the edge-length field, while the implementation accepts --edge-lengths and the example line uses --edge-lengths. Root cause is the generic edge_lengths -> edge-weights mapping in problemreductions-cli/src/commands/create.rs:701 without a LongestPath override.

Minor (Nice to Have)

  • Add a regression test for the per-problem help output of LongestPath so future CLI help/schema mismatches fail fast.

Summary

  • Important: pred create LongestPath has a user-facing help/flag mismatch.
  • Minor: the added CLI tests miss the broken help path that would have caught this regression.

Agentic Feature Tests

Summary

Feature Discoverable Setup Works Expected Outcome Met Doc Quality
LongestPath model + LongestPath -> ILP/i32 flow partial yes yes, with one CLI help issue partial mostly good

Commands Exercised

  • pred list — PASS; LongestPath/SimpleGraph/i32 and LongestPath/SimpleGraph/One appear in the catalog.
  • pred show LongestPath — PASS; fields, complexity, and outgoing ILP/i32 reduction render correctly.
  • pred create --example LongestPath -o /tmp/longest-path-734.json — PASS; example instance serializes correctly.
  • pred solve /tmp/longest-path-734.json — PASS; returns Valid(20) with the expected optimal configuration.
  • pred reduce /tmp/longest-path-734.json --to ILP/i32 -o /tmp/longest-path-734-ilp.json — PASS.
  • pred solve /tmp/longest-path-734-ilp.json — PASS; the reduced ILP solves and extracts the original optimum.
  • pred create LongestPath — ISSUE confirmed; the problem-specific help path documents --edge-weights instead of --edge-lengths.

Findings

  • Confirmed issue: the interactive help flow for creating a LongestPath instance is misleading. The output currently includes:
Parameters:
  --graph            The underlying graph G=(V,E) (edge list: 0-1,1-2,2-3)
  --edge-weights     Positive edge lengths l: E -> ZZ_(> 0) (comma-separated: 1,2,3)
  --source-vertex    Source vertex s (integer)
  --target-vertex    Target vertex t (integer)

Severity: important.
Recommended fix: add a LongestPath-specific help_flag_name() override for edge_lengths, or correct the shared edge_lengths mapping so path-length fields render as --edge-lengths by default.

Reproduction / Classification

  • pred create LongestPath help mismatch — confirmed in the current PR worktree.
  • No additional functional issues were reproduced in the list/show/create-example/solve/reduce flow.

Generated by review-pipeline

@GiggleLiu
Copy link
Copy Markdown
Contributor Author

Agentic Review Report

Structural Check

Structural Review: model+rule LongestPath / longestpath_ilp

Structural Completeness

# Check Status
M1 Model file exists PASS — src/models/graph/longest_path.rs exists
M2 inventory::submit! present PASS — schema entry registered in src/models/graph/longest_path.rs
M3 Serialize / Deserialize derive PASS — LongestPath derives both
M4 Problem trait impl PASS — implemented in src/models/graph/longest_path.rs
M5 OptimizationProblem impl PASS — Direction::Maximize implemented
M6 #[cfg(test)] + #[path = ...] test link PASS — linked at src/models/graph/longest_path.rs:301
M7 Model test file exists PASS — src/unit_tests/models/graph/longest_path.rs exists
M8 Test file has >= 3 tests PASS — 11 tests present
M9 Registered in graph/mod.rs PASS — module/export/example-db registration present
M10 Re-exported in models/mod.rs PASS — LongestPath exported
M11 declare_variants! entry exists PASS — SimpleGraph/i32 and SimpleGraph/One declared
M12 CLI alias resolution entry PASS — canonical-name resolution is registry-backed; no hardcoded alias entry required
M13 CLI create support PASS — LongestPath parser branch and tests added in problemreductions-cli/src/commands/create.rs
M14 Canonical model example registered PASS — canonical_model_example_specs() added and wired through src/models/graph/mod.rs
M15 Paper display-name entry PASS — "LongestPath": [Longest Path] added
M16 Paper problem-def block PASS — problem-def("LongestPath") added
R1 Rule file exists PASS — src/rules/longestpath_ilp.rs exists
R2 #[reduction(...)] macro present PASS — reduction registered with overhead metadata
R3 ReductionResult impl present PASS — ReductionLongestPathToILP implements it
R4 ReduceTo impl present PASS — impl ReduceTo<ILP<i32>> for LongestPath<SimpleGraph, i32>
R5 #[cfg(test)] + #[path = ...] test link PASS — linked at src/rules/longestpath_ilp.rs:191
R6 Rule test file exists PASS — src/unit_tests/rules/longestpath_ilp.rs exists
R7 Closed-loop test present PASS — test_longestpath_to_ilp_closed_loop_on_issue_example
R8 Registered in rules/mod.rs PASS — module and example-db registration added under ilp-solver
R9 Canonical rule example registered PASS — canonical_rule_example_specs() added in src/rules/longestpath_ilp.rs
R10 Example-db lookup tests exist PASS — shared example-db consistency/lookup tests cover canonical rule/model spec inventories
R11 Paper reduction-rule entry PASS — reduction-rule("LongestPath", "ILP", ...) added
B1 Blacklisted autogenerated files committed PASS — none of the forbidden generated artifacts are in the diff

Build Status

  • make test: PASS
  • make clippy: PASS

Semantic Review

  • evaluate() correctness: OK — the model rejects wrong-length/non-binary configs, enforces the source/target degree pattern, checks connectivity/acyclicity via |E| = |V|-1, and only then sums edge lengths.
  • dims() correctness: OK — one binary variable per edge (vec![2; num_edges]) matches the issue and paper.
  • Weight handling: OK — lengths stay in inherent accessors/mutators and use WeightElement::to_sum() consistently.
  • reduce_to() correctness: OK — the ILP encodes one directed unit of flow from s to t, bounds indegree/outdegree by 1, forbids using both orientations of an undirected edge, and uses MTZ-style order constraints to eliminate detached cycles.
  • extract_solution() correctness: OK — it projects the two directed arc variables for each undirected edge back to the source edge-selection bitvector.
  • Overhead accuracy: OK — construction yields 2m + n variables and 2m + n + 3n + m + 2m + 1 = 5m + 4n + 1 constraints, matching the macro metadata.
  • Paper quality: OK — the proof sketch matches the actual encoding and the worked 3-vertex example is consistent with the implementation.

Issue Compliance

# Check Status
1 Problem name matches issue OK — implemented as LongestPath
2 Mathematical definition matches OK — simple undirected s-t path maximizing total edge length
3 Problem type matches OK — optimization problem with Direction::Maximize
4 Type parameters match OK — graph + weight variants implemented
5 Configuration space matches OK — one binary variable per edge
6 Feasibility check matches OK — valid iff selected edges form one simple s-t path
7 Objective function matches OK — valid solutions score by total selected edge length
8 Complexity matches OK — declared O(num_vertices * 2^num_vertices) aligns with the issue’s exact-DP framing
9 Source/target rule match issue intent OK — new solver path is LongestPath -> ILP
10 Reduction algorithm matches OK — flow + order-variable ILP is consistent with the issue discussion
11 Solution extraction matches OK — chosen undirected edges are recovered from selected directed arcs
12 Correctness preserved OK — closed-loop and manual trace both preserve the optimum on the reviewed instances
13 Overhead expressions match OK — manual counts match the declared formulas
14 Example matches OK — model and rule examples are internally consistent and build through example-db

Summary

  • 28/28 structural checks passed
  • 14/14 issue-compliance checks passed
  • No structural or semantic blockers found

Quality Check

Quality Review

Design Principles

  • DRY: OK — the implementation follows the existing graph-problem patterns without introducing new cross-file duplication beyond the repo’s normal per-model validation style.
  • KISS: OK — the model is minimal, and the rule uses the smallest standard ILP construction that can express path order and forbid cycles.
  • HC/LC: OK — model logic, reduction logic, CLI wiring, tests, and paper text remain separated cleanly.

HCI (if CLI/MCP changed)

  • Error messages: OK — pred create LongestPath ... rejects missing/misnamed flags with concrete usage examples.
  • Discoverability: ISSUE — the new rule is only registered as LongestPath -> ILP/i32 in src/rules/longestpath_ilp.rs:58, so a natural bare-target workflow fails: pred path LongestPath ILP and pred reduce longest-path.json --to ILP both report “No reduction path”, even though pred solve longest-path.json succeeds via ILP.
  • Consistency: ISSUE — pred show LongestPath advertises an outgoing reduction to ILP/i32, but pred solve reports "reduced_to": "ILP", which nudges users toward a target spelling that path/reduce then reject.
  • Least surprise: ISSUE — for a new feature whose only outgoing solver path is ILP, users reasonably expect bare ILP to resolve, especially because other commands accept bare canonical names.
  • Feedback: ISSUE — when pred reduce ... --to ILP fails, the CLI says there is no path instead of steering the user toward the only valid target spelling (ILP/i32) that pred show already knows about.

Test Quality

  • Naive test detection: ISSUE
    • src/unit_tests/rules/longestpath_ilp.rs:35 and src/unit_tests/rules/longestpath_ilp.rs:57 validate the rule in isolation, but there is no CLI/integration test covering the user-facing pred path / pred reduce flow for this ILP/i32-only reduction, so the variant-resolution gap above is currently untested.

Issues

Critical (Must Fix)

  • None.

Important (Should Fix)

  • The new LongestPath -> ILP rule is functionally correct, but the user-facing CLI flow is inconsistent for this feature: bare ILP fails for pred path / pred reduce, while pred solve succeeds by picking ILP/i32 under the hood. That leaves the new solver path partially undiscoverable unless users already know to spell the target as ILP/i32.
  • There is no integration coverage for the above CLI behavior, so the regression is currently invisible to the test suite.

Minor (Nice to Have)

  • None.

Summary

  • Important — LongestPath’s only new outgoing solver path is effectively hidden behind the non-default target spelling ILP/i32 for pred path and pred reduce.
  • Important — add a CLI-level test for the path/reduce UX so future ILP/i32-only reductions do not regress the same way.

Agentic Feature Tests

Agentic Feature Tests

Results

Check Result Notes
pred list PASS LongestPath/SimpleGraph/i32 appears as the default variant, with LongestPath/SimpleGraph/One also listed.
pred show LongestPath PASS Shows the correct fields, complexity, and one outgoing reduction to ILP/i32.
pred create --example LongestPath PASS Wrote a valid example JSON bundle.
pred solve longest-path.json PASS Returned the expected optimum Valid(20) using the ILP solver path.
pred path LongestPath ILP FAIL Confirmed: reports Error: No reduction path from LongestPath to ILP.
pred reduce longest-path.json --to ILP FAIL Confirmed: same error; no bundle is produced.
pred path LongestPath ILP/i32 PASS Works immediately; the 1-step path is visible when the variant is explicit.
pred reduce longest-path.json --to ILP/i32 PASS Produces a bundle that solves back to the same Valid(20) source optimum.

Findings

Finding Classification Severity Evidence Recommended fix
Bare ILP is not usable for the new LongestPath reduction path even though pred solve successfully uses ILP internally. confirmed Important pred path LongestPath ILP and pred reduce ... --to ILP both fail, while the same commands with ILP/i32 succeed. Either make bare target resolution consider reachable ILP variants for path/reduce (matching solve), or surface ILP/i32 much more explicitly in CLI feedback/docs for this feature.

Reproduction Notes

  • Confirmed working path: pred path LongestPath ILP/i32
  • Confirmed working reduction: pred reduce longest-path.json --to ILP/i32 -o bundle.json
  • Confirmed workaround result: solving the explicit ILP/i32 bundle returns the same source optimum Valid(20).

Generated by review-pipeline

@GiggleLiu
Copy link
Copy Markdown
Contributor Author

Agentic Review Report

Structural Check

Structural Review: model+rule LongestPath / longestpath_ilp

Structural Completeness

# Check Status
1 Model file exists PASS — [src/models/graph/longest_path.rs] is present and added in this PR.
2 inventory::submit! present PASS — schema registration is present in [src/models/graph/longest_path.rs].
3 Serialize/Deserialize derive on model struct PASS — LongestPath derives both traits.
4 Problem impl present PASS — impl Problem for LongestPath<G, W> is present.
5 Optimization or satisfaction trait impl present PASS — OptimizationProblem is implemented with Direction::Maximize.
6 Model test link present PASS — #[cfg(test)] + #[path = ...] is present in the model file.
7 Model test file exists PASS — [src/unit_tests/models/graph/longest_path.rs] exists.
8 Model test file has >= 3 tests PASS — the file contains broad coverage, including creation, evaluation, serialization, and edge cases.
9 Registered in graph/mod.rs PASS — module export and canonical example hook were added in [src/models/graph/mod.rs].
10 Re-exported in models/mod.rs PASS — LongestPath is re-exported in [src/models/mod.rs].
11 declare_variants! entry exists PASS — both SimpleGraph/i32 and SimpleGraph/One variants are declared.
12 CLI alias / catalog resolution support PASS — CLI resolution is registry-driven here; pred show LongestPath works in the review worktree without a manual alias entry.
13 CLI create support PASS — creation support was added in [problemreductions-cli/src/commands/create.rs].
14 Canonical model example registered PASS — the model contributes canonical specs via [src/models/graph/mod.rs].
15 Paper display-name entry PASS — LongestPath was added to the display-name table in [docs/paper/reductions.typ].
16 Paper problem-def block PASS — a full problem-def("LongestPath") entry was added to the paper.
17 Rule file exists PASS — [src/rules/longestpath_ilp.rs] is present and added in this PR.
18 #[reduction(...)] macro present PASS — the rule uses #[reduction(overhead = { ... })].
19 ReductionResult impl present PASS — ReductionLongestPathToILP implements ReductionResult.
20 ReduceTo impl present PASS — impl ReduceTo<ILP<i32>> for LongestPath<SimpleGraph, i32> is present.
21 Rule test link present PASS — #[cfg(test)] + #[path = ...] is present in the rule file.
22 Rule test file exists PASS — [src/unit_tests/rules/longestpath_ilp.rs] exists.
23 Closed-loop rule test present PASS — the test file contains a closed-loop optimum check on the issue example.
24 Registered in rules/mod.rs PASS — module registration and canonical example hook were added in [src/rules/mod.rs].
25 Canonical rule example registered PASS — the rule exports canonical specs through [src/rules/longestpath_ilp.rs] and [src/rules/mod.rs].
26 Example-db lookup tests exist PASS — existing example-db coverage is present in [src/unit_tests/example_db.rs].
27 Paper reduction-rule entry PASS — a reduction-rule("LongestPath", "ILP", ...) entry was added in [docs/paper/reductions.typ].
28 Blacklisted autogenerated files committed PASS — none of the forbidden generated files are present in the PR diff.

Build Status

  • make test: PASS
  • make clippy: PASS
  • make paper: PASS

Semantic Review

  • Model evaluate() correctness: OK — [src/models/graph/longest_path.rs] validates the configuration as a simple s-t path before summing weights, and returns Invalid for malformed configs.
  • Model edge cases: OK — invalid length/value vectors, branching/cycle configs, empty nontrivial selections, and the source == target empty-path case are covered in [src/unit_tests/models/graph/longest_path.rs].
  • Rule correctness: OK — [src/rules/longestpath_ilp.rs] correctly encodes one unit of directed flow from s to t, enforces degree bounds and edge exclusivity, and uses MTZ-style ordering constraints to eliminate detached cycles.
  • extract_solution correctness: OK — it projects the selected arc pair for each undirected edge back to the source edge-selection vector, and the closed-loop tests confirm the extracted source solution is valid and optimal on the canonical issue instance.
  • Overhead accuracy: OK — the implementation builds 2m + n variables and 2m + n + 3n + m + 2m + 1 = 5m + 4n + 1 constraints, matching the declared overhead formulas.
  • Paper proof sketch: OK — the proof in [docs/paper/reductions.typ] matches the implemented flow-plus-ordering construction and correctly argues that only a single directed s-t path can remain.

Issue Compliance (if linked issue found)

# Check Status
1 Problem name matches issue OK — the PR introduces LongestPath.
2 Mathematical definition matches OK — the model is an optimization s-t longest simple path with positive edge lengths.
3 Problem type (opt/sat) matches OK — this matches the linked issue’s corrected optimization framing.
4 Type parameters match OK — the implemented variants are graph + weight, with SimpleGraph and i32/One concrete registrations.
5 Configuration space matches OK — one binary choice per edge.
6 Feasibility check matches OK — only simple s-t paths are valid.
7 Objective function matches OK — valid solutions maximize summed edge length.
8 Complexity matches OK — the declared O(num_vertices * 2^num_vertices) bound is consistent with the issue’s subset-DP framing.

Summary

  • 28/28 structural checks passed
  • 8/8 issue compliance checks passed
  • No structural or semantic defects were found in the model, reduction, registrations, or paper build.

Quality Check

Quality Review

Design Principles

  • DRY: OK — the new model and rule follow existing project patterns without introducing duplicated helper logic beyond the problem-specific constraint construction.
  • KISS: OK — the LongestPath model logic is straightforward, and the ILP reduction uses the standard flow-plus-ordering formulation rather than a more complex bespoke encoding.
  • HC/LC: OK — problem logic stays in [src/models/graph/longest_path.rs], reduction logic stays in [src/rules/longestpath_ilp.rs], and CLI/paper wiring are kept separate.

HCI (if CLI/MCP changed)

  • Error messages: OK — pred create LongestPath emits actionable messages for missing flags and misused --weights.
  • Discoverability: ISSUE — the new solver path is implemented only for ILP/i32 in [src/rules/longestpath_ilp.rs:58], so the natural manual commands pred path LongestPath ILP and pred reduce ... --to ILP fail even though pred solve works and the feature is otherwise usable.
  • Consistency: ISSUE — this new ILP<i32> target exposes an existing CLI variant-resolution limitation more sharply than the typical ILP/bool reductions. Users have to know to spell the target as ILP/i32 instead of the generic ILP name.
  • Least surprise: ISSUE — pred show LongestPath advertises an outgoing reduction to ILP/i32, but the unsuffixed target name still resolves to the incompatible default ILP/bool, which is easy to miss during manual exploration.
  • Feedback: OK — once the correct ILP/i32 target is used, the CLI output and reduction path are clear.

Test Quality

  • Naive test detection: OK
    • The model tests cover valid, invalid, boundary, serialization, and brute-force cases.
    • The rule tests cover ILP shape, handcrafted extraction, closed-loop optimality on the issue instance, and the degenerate source == target case.

Issues

Critical (Must Fix)

  • None.

Important (Should Fix)

  • The manual CLI reduction workflow is inconsistent for this new feature: pred path LongestPath ILP and pred reduce <instance> --to ILP fail, while pred path LongestPath ILP/i32 and pred reduce <instance> --to ILP/i32 succeed. This is a user-facing discoverability problem exposed by the new ILP<i32> reduction target.

Minor (Nice to Have)

  • None.

Summary

  • Important: the new feature works end-to-end, but the unsuffixed ILP target name is misleading for manual path/reduce usage and should either resolve to the reachable integer variant or be documented more explicitly.

Agentic Feature Tests

Agentic Feature Tests

Summary

Feature Discoverable Setup Works Expected Outcome Met Doc Quality
LongestPath CLI/model/reduction flow partial yes partial partial missing variant-resolution guidance

Per-Feature Details

LongestPath

  • Role: downstream CLI user validating a newly added model and its solver path
  • Use Case: inspect the new model, create the canonical example, solve it, and manually explore the ILP reduction path
  • What they tried:
    • Built the CLI with cargo build -p problemreductions-cli --bin pred
    • Ran pred list, pred show LongestPath, pred create --example LongestPath
    • Solved the example with both pred solve ... --solver brute-force and default pred solve ...
    • Tried manual path/reduction commands with both ILP and ILP/i32
  • Discoverability: partial. pred list and pred show LongestPath work, but the natural generic target name ILP fails for path/reduce even though show advertises an outgoing reduction.
  • Setup: yes. CLI built and ran successfully in the PR worktree.
  • Functionality: partial.
    • pred list shows LongestPath/SimpleGraph/i32
    • pred show LongestPath displays the model correctly and lists an outgoing reduction to ILP/i32
    • pred create --example LongestPath succeeds
    • pred solve longest-path.json --solver brute-force returns Valid(20)
    • pred solve longest-path.json also succeeds via ILP and returns Valid(20)
    • pred path LongestPath ILP fails
    • pred reduce longest-path.json --to ILP fails
    • pred path LongestPath ILP/i32 succeeds
    • pred reduce longest-path.json --to ILP/i32 succeeds, and pred solve bundle-i32.json returns Valid(20)
  • Expected vs Actual Outcome: partially met. The model is usable and solvable, but the manual reduction workflow fails with the intuitive unsuffixed target name.
  • Blocked steps: none
  • Friction points: variant resolution is surprising. pred show LongestPath implies “reduce to ILP” is available, but pred path ... ILP selects ILP/bool and reports no path.
  • Doc suggestions: document that this reduction targets ILP/i32, or make path/reduce resolve generic ILP to a compatible reachable variant.

Findings

Important

  • Confirmed: pred path LongestPath ILP and pred reduce <example> --to ILP fail, despite pred show LongestPath listing an outgoing reduction to ILP/i32.
    • Reproduction:
      • ./target/debug/pred show LongestPath shows → ILP/i32
      • ./target/debug/pred path LongestPath ILP returns Error: No reduction path from LongestPath to ILP
      • ./target/debug/pred reduce /tmp/review734-feature.04eUEL/longest-path.json --to ILP returns the same path error
      • ./target/debug/pred path LongestPath ILP/i32 succeeds
    • Severity: medium
    • Recommended fix: either make generic ILP resolve to a reachable variant for path/reduce, or update CLI output/docs/help to direct users to ILP/i32 explicitly when only the integer variant is reachable.

Not Reproducible In Current Worktree

  • None.

Overall

The core feature is functional: creation, brute-force solving, default ILP solving, and explicit ILP/i32 reduction all work. The main user-facing issue is a CLI variant-resolution mismatch that blocks the natural manual path/reduce flow for LongestPath.


Generated by review-pipeline

@GiggleLiu
Copy link
Copy Markdown
Contributor Author

Agentic Review Report

Structural Check

Structural Review: model+rule LongestPath / longestpath_ilp

Structural Completeness

# Check Status
1 Model file exists PASS
2 inventory::submit! present PASS
3 Serialize / Deserialize derive on model PASS
4 Problem impl for LongestPath PASS
5 OptimizationProblem impl for LongestPath PASS
6 Model test link present PASS
7 Model test file exists PASS
8 Model test file has >= 3 tests PASS
9 Registered in src/models/graph/mod.rs PASS
10 Re-exported in src/models/mod.rs PASS
11 declare_variants! entry exists PASS
12 CLI alias resolution support PASS — resolver is registry-backed; no per-model match arm is needed in problem_name.rs
13 CLI create support PASS
14 Canonical model example registered PASS
15 Paper display-name entry PASS
16 Paper problem-def block PASS
17 Rule file exists PASS
18 #[reduction(...)] macro present PASS
19 ReductionResult impl present PASS
20 ReduceTo impl present PASS
21 Rule test link present PASS
22 Rule test file exists PASS
23 Closed-loop rule test present PASS
24 Registered in src/rules/mod.rs PASS
25 Canonical rule example registered PASS
26 Example-db lookup tests exist PASS
27 Paper reduction-rule entry PASS
28 Blacklisted autogenerated files committed PASS

Build Status

  • make test: PASS
  • make clippy: PASS

Semantic Review

  • evaluate() correctness: OK — is_simple_st_path() rejects non-binary configs, wrong lengths, disconnected selections, branching selections, and non-empty s=t witnesses before summing edge lengths; valid witnesses evaluate to the exact selected-length total.
  • dims() correctness: OK — one binary variable per edge via vec![2; num_edges].
  • Overhead accuracy: OK — the construction creates 2m + n variables and 2m + n + 3n + m + 2m + 1 = 5m + 4n + 1 constraints, matching the declared overhead exactly.
  • Reduction correctness: OK — tracing the 3-vertex example yields the advertised 7-variable ILP, objective 5, and extract_solution() maps the oriented-arc witness back to the original edge-selection witness.
  • Paper proof sketch: OK — for s != t, the flow, degree, exclusivity, and MTZ-style order constraints imply exactly one directed s-t path and exclude detached cycles.

Issue Compliance (linked issue #288)

# Check Status
1 Problem name matches issue OK
2 Mathematical definition matches OK
3 Problem type (optimization) matches OK
4 Type parameters match OK
5 Configuration space matches OK
6 Feasibility check matches OK
7 Objective function matches OK
8 Complexity matches ISSUE — src/models/graph/longest_path.rs:267 records num_vertices * 2^num_vertices as the catalog complexity, so pred show LongestPath reports that as the “Best Known Complexity”. The linked issue and repo convention for declare_variants! both point at best-known complexity metadata, and the issue explicitly cites O*(2^n) exact algorithms for general longest path.

Summary

  • 28/28 structural checks passed
  • 7/8 issue-compliance checks passed
  • ISSUE: complexity metadata is weaker than the linked issue’s cited best-known exact bound and is surfaced to users as “Best Known Complexity”.

Quality Check

Quality Review

Design Principles

  • DRY: OK — the model and rule follow existing graph-problem and ILP-reduction patterns without obvious copy-paste debt beyond normal example/test fixtures.
  • KISS: OK — the LongestPath evaluator and ILP construction are direct and local; there is no unnecessary abstraction.
  • HC/LC: OK — graph logic stays in the model/rule modules, while CLI wiring stays in the CLI crate.

HCI (CLI changed)

  • Error messages: ISSUE — the new reduction targets ILP/i32 (src/rules/longestpath_ilp.rs:58), but the generic CLI path/reduce errors still collapse the target to bare ILP (problemreductions-cli/src/commands/graph.rs:492, problemreductions-cli/src/commands/graph.rs:554, problemreductions-cli/src/commands/reduce.rs:111, problemreductions-cli/src/commands/reduce.rs:126). For this feature, pred path LongestPath ILP and pred reduce ... --to ILP both fail even though pred show LongestPath advertises an outgoing ILP/i32 reduction.
  • Discoverability: ISSUE — pred solve longest-path.json hardcodes "reduced_to": "ILP" for every non-ILP problem (problemreductions-cli/src/commands/solve.rs:116), so the successful solve output suggests that bare ILP should be reusable for path / reduce, but the actual working target is ILP/i32.
  • Consistency: ISSUE — show, path, reduce, and solve disagree on whether the target needs its explicit variant.
  • Least surprise: ISSUE — pred reduce longest-path.json --to ILP fails and its recovery hint tells users to run pred path LongestPath ILP, which fails for the same reason.
  • Feedback: ISSUE — the CLI never tells the user that the discovered ILP route is specifically the i32 variant.

Test Quality

  • Naive test detection: OK
    • Model tests cover valid, invalid, serialization, panic, brute-force, and s=t edge cases.
    • Rule tests cover ILP shape, handcrafted extraction, closed-loop optimality, and the s=t empty-path case.

Issues

Critical (Must Fix)

  • None.

Important (Should Fix)

  • The CLI does not present the explicit ILP/i32 target variant consistently for this new rule, so the natural pred path LongestPath ILP / pred reduce ... --to ILP workflows fail even though the feature is present.

Minor (Nice to Have)

  • None.

Summary

  • ISSUE: non-default ILP target variants are not surfaced consistently across show, solve, path, and reduce, which makes the new LongestPath -> ILP/i32 route harder to discover and reuse.

Agentic Feature Tests

Feature Test Report: problem-reductions

Date: 2026-03-22
Project type: CLI + library
Features tested: LongestPath model, LongestPath -> ILP/i32 reduction
Profile: ephemeral
Use Case: downstream user discovers the new model from the catalog, creates the canonical example, solves it, then tries to inspect and run the advertised ILP reduction from the CLI
Expected Outcome: the catalog and CLI should make the new model and its ILP reduction easy to discover and execute end to end
Verdict: fail
Critical Issues: 0

Summary

Feature Discoverable Setup Works Expected Outcome Met Doc Quality
LongestPath model + ILP reduction partial yes partial partial good

Per-Feature Details

LongestPath model + ILP reduction

  • Role: downstream CLI user validating a newly added model and solver path
  • Use Case: list the new feature, inspect it, create the shipped example, solve it, inspect the reduction path, and reduce it to ILP manually
  • What they tried:
    • target/debug/pred list
    • target/debug/pred show LongestPath
    • target/debug/pred create --example LongestPath -o longest-path.json
    • target/debug/pred solve longest-path.json
    • target/debug/pred path LongestPath ILP
    • target/debug/pred path LongestPath ILP/i32
    • target/debug/pred reduce longest-path.json --to ILP/i32 -o bundle-i32.json
    • target/debug/pred solve bundle-i32.json
    • target/debug/pred reduce longest-path.json --to ILP
  • Discoverability: partial — pred list and pred show LongestPath expose the new model and show an outgoing ILP/i32 reduction, but the rest of the CLI flow does not consistently preserve that variant information.
  • Setup: yes — no extra setup beyond the repo build; the prebuilt target/debug/pred binary worked.
  • Functionality: partial — create/solve/reduce all work when the user spells the target as ILP/i32; the bare ILP form fails.
  • Expected vs Actual Outcome: partial — expected the successful solve output ("reduced_to": "ILP") and the generic CLI hints to be reusable in path and reduce; actual behavior requires the user to know the hidden i32 target variant.
  • Blocked steps: none.
  • Friction points: the reduction exists, but the path/reduce UX around non-default ILP variants is misleading.
  • Doc suggestions: surface the exact target variant (ILP/i32) anywhere the CLI reports or hints at the reduction path for this feature.

Expected vs Actual Outcome

  • Expected: LongestPath appears in the catalog, its example solves, and the advertised ILP reduction can be followed through the normal pred path / pred reduce workflow.
  • Actual: the feature works end to end only when the user manually supplies ILP/i32; the bare ILP target shown in solve output and generic hints does not work.

Issues Found

  • Confirmed, important: pred path LongestPath ILP fails with No reduction path from LongestPath to ILP, while pred path LongestPath ILP/i32 succeeds.
  • Confirmed, important: pred reduce longest-path.json --to ILP fails, and its recovery hint suggests pred path LongestPath ILP, which also fails.
  • Confirmed, important: pred solve longest-path.json reports "reduced_to": "ILP" rather than ILP/i32, which causes the discoverability mismatch above.
  • Scope note: this looks like a pre-existing generic CLI limitation for non-default ILP/i32 targets, not a bug unique to LongestPath, but the new feature inherits it directly.

Suggestions

  • When a discovered reduction target is a non-default variant, print that exact variant in solve, path, and reduce messages and hints.
  • Consider teaching bare ILP resolution in path / reduce to prefer a reachable ILP variant when only one exists.

Generated by review-pipeline

@GiggleLiu
Copy link
Copy Markdown
Contributor Author

Additional review finding:

  • Important: pred create LongestPath's problem-specific help path still advertises --edge-weights instead of --edge-lengths. The new implementation branch correctly requires --edge-lengths in [problemreductions-cli/src/commands/create.rs:1213], but help_flag_name() still falls through to the generic edge_lengths -> edge-weights mapping in [problemreductions-cli/src/commands/create.rs:701], and there is no LongestPath override alongside the existing problem-specific help overrides in [problemreductions-cli/src/commands/create.rs:665]. That means pred create LongestPath (with no other flags) teaches the wrong flag even though the actual command path and examples use the right one.

isPANN and others added 2 commits March 22, 2026 03:55
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@isPANN isPANN mentioned this pull request Mar 21, 2026
3 tasks
@isPANN isPANN merged commit fa3e24b into main Mar 22, 2026
3 checks passed
@GiggleLiu GiggleLiu deleted the issue-288 branch April 12, 2026 00:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Model] LongestPath

2 participants