Skip to content

feat: analysis data from csv to evaluate perfomance of 3 ways solve Ax=b#82

Merged
TanKhoiTV merged 10 commits into
devfrom
feat/log-log-plot
Apr 30, 2026
Merged

feat: analysis data from csv to evaluate perfomance of 3 ways solve Ax=b#82
TanKhoiTV merged 10 commits into
devfrom
feat/log-log-plot

Conversation

@niuqohn2510

@niuqohn2510 niuqohn2510 commented Apr 12, 2026

Copy link
Copy Markdown
Collaborator

Closes #36, #37
analysis data from csv to evaluate perfomance of 3 ways solve Ax=b and stability of SPD, Hillbert

Summary by CodeRabbit

  • Refactor
    • Improved solver reliability and numerical accuracy with a stricter convergence tolerance, far higher iteration allowance, and more robust convergence checks.
    • Strengthened input validation and consistent output formatting for more predictable solver results.
  • Chores
    • Minor CI/workflow formatting tweak; no user-facing behavior change.

@coderabbitai

coderabbitai Bot commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • part3/analysis.ipynb
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b7585faa-7e0c-49dc-98cf-49c8d04484ba

📥 Commits

Reviewing files that changed from the base of the PR and between ace589d and f81d42b.

📒 Files selected for processing (1)
  • part3/analysis.ipynb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Gauss–Seidel in part3/solvers.py was refactored: helper functions removed and logic inlined with NumPy vectorization, input validation tightened (square A, matching b, error on zero diagonal), convergence switched to L2 norms, and defaults changed (tolerance 1e-8, max_iter 100000). CI grep exclusions in .github/workflows/ci.yml were adjusted.

Changes

Cohort / File(s) Summary
Gauss–Seidel Solver
part3/solvers.py
Removed is_diagonally_dominant and residual helpers; convert inputs to NumPy, validate square matrix and vector dims, raise on zero diagonal; vectorized row updates using dot products; convergence now uses L2 norms for iterate change and residual; defaults changed (tolerance 1e-6 → 1e-8, max_iter 1000 → 100000); returns x.tolist().
CI workflow tweak
.github/workflows/ci.yml
Adjusted the banned-solver grep exclusion to specifically omit part3/solvers.py and part3/benchmark.py (scoped paths) and added trailing newline.

Sequence Diagram(s)

(omitted — changes are localized to solver implementation and CI exclusion; no multi-component sequential flow requiring diagram)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • aFlyingSeal

Poem

🐰 I hopped through arrays, quick and neat,
NumPy crumbs beneath my feet,
L2 whispers guided every stride,
Diagonals kept the system tied,
Now Gauss–Seidel hums in tidy beats.

🚥 Pre-merge checks | ✅ 1 | ❌ 4

❌ Failed checks (4 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title mentions 'analysis data from csv' and 'evaluate performance of 3 ways solve Ax=b', which relates to the PR's objectives, but does not reflect the actual code changes: modifications to gauss_seidel solver implementation and CI workflow updates. Revise the title to accurately reflect the main code changes, such as 'refactor: update gauss_seidel implementation and adjust CI workflow' or similar that describes the actual modifications made.
Linked Issues check ⚠️ Warning The code changes focus on solver implementation and CI configuration, not on creating log-log plots or analysis notebooks required by issue #36. Either implement the log-log plotting functionality from issue #36, or clarify if this PR is intended only for preparatory solver changes with plotting to follow in a separate PR.
Out of Scope Changes check ⚠️ Warning Changes to gauss_seidel solver and CI workflow are not directly related to the PR objectives of creating CSV-based performance analysis with log-log plots. Separate solver implementation changes into a distinct PR, or add the required analysis/visualization code to align changes with the stated PR objectives.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/log-log-plot

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@part3/solvers.py`:
- Around line 9-10: The gauss_seidel default stopping (tolerance=1e-8,
max_iter=100000) makes the benchmark call gauss_seidel(A, b) use a
size-dependent, overly strict absolute L2 criterion; either change the
gauss_seidel signature defaults to a looser, stable pair (e.g., tolerance=1e-6,
max_iter=10000) so benchmarks are comparable, or modify the benchmark call
gauss_seidel(A, b) to pass explicit tolerance and max_iter values (or switch to
a relative/infinity-norm criterion) so the convergence threshold is controlled
outside gauss_seidel. Ensure the change references the gauss_seidel function
signature and the benchmark invocation gauss_seidel(A, b).
- Around line 16-21: The code checks A_np.shape[1] before confirming A_np is 2-D
and doesn't enforce b_np to be 1-D, causing IndexError or matrix-shaped b; in
gauss_seidel ensure you first validate dimensions: check A_np.ndim == 2 and
raise ValueError if not, then set n = A_np.shape[0] and verify A_np.shape[1] ==
n (square), and also require b_np.ndim == 1 and b_np.shape[0] == n (raise
ValueError otherwise) so later indexing and arithmetic operate on 1-D vectors
and avoid shape index errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d04b1680-b5f7-46d8-9b9d-4f5dd97898cc

📥 Commits

Reviewing files that changed from the base of the PR and between b1951c1 and 5fc1a68.

⛔ Files ignored due to path filters (1)
  • part3/results.csv is excluded by !**/*.csv
📒 Files selected for processing (2)
  • part3/analysis.ipynb
  • part3/solvers.py

Comment thread part3/solvers.py
Comment thread part3/solvers.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/ci.yml (1)

59-77: ⚠️ Potential issue | 🟠 Major

--exclude=$PART3_FILES only excludes one file due to shell word splitting (Line 76).

PART3_FILES expands to two space-separated paths, so --exclude=$PART3_FILES becomes two separate arguments: --exclude=part3/solvers.py and part3/benchmark.py. The second path becomes a positional argument to grep and gets searched instead of excluded, making the Part 3 bypass incomplete.

Suggested fix (exclude Part 3 by construction)
-          for f in $PART1_FILES $PART2_FILES $PART3_FILES; do
+          for f in $PART1_FILES $PART2_FILES; do
             [ -f "$f" ] && files="$files $f" || echo "Skipping $f (not found)"
           done
           if [ -z "$files" ]; then
             echo "No files found — skipping banned solver check"
             exit 0
           fi
           ! grep -n \
             -e "linalg\.solve" \
             -e "linalg\.inv" \
             -e "scipy\.linalg\.qr" \
             -e "scipy\.linalg\.lu" \
             -e "\.rref()" \
             -e "\.echelon_form()" \
             -e "linsolve(" \
             -e ".array" \
-            $files \
-            --exclude=$PART3_FILES
+            $files
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 59 - 77, The grep --exclude invocation
incorrectly expands PART3_FILES into multiple words so only the first path is
treated as an exclude; update the grep call to build one --exclude=... option
per path in PART3_FILES (e.g. loop over PART3_FILES and append "--exclude=$p"
into an excludes variable) and then call grep with $excludes and $files;
reference the variables PART3_FILES, files and the grep command/--exclude flag
so the new code constructs multiple --exclude arguments instead of relying on a
single expansion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In @.github/workflows/ci.yml:
- Around line 59-77: The grep --exclude invocation incorrectly expands
PART3_FILES into multiple words so only the first path is treated as an exclude;
update the grep call to build one --exclude=... option per path in PART3_FILES
(e.g. loop over PART3_FILES and append "--exclude=$p" into an excludes variable)
and then call grep with $excludes and $files; reference the variables
PART3_FILES, files and the grep command/--exclude flag so the new code
constructs multiple --exclude arguments instead of relying on a single
expansion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5e1ee089-30b1-4777-ae68-c7d7bc2fa3db

📥 Commits

Reviewing files that changed from the base of the PR and between 5fc1a68 and da3db8f.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • part3/analysis.ipynb

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
part3/solvers.py (2)

16-21: ⚠️ Potential issue | 🟠 Major

Validate dimensionality before reading shape[1].

gauss_seidel([], []) and gauss_seidel([1, 2], [3, 4]) still fail with IndexError here instead of the intended ValueError, and a column-vector b with shape (n, 1) still slips through the current length check. Guard A_np.ndim == 2 and b_np.ndim == 1 before using shape[1].

Proposed fix
-    n = A_np.shape[0]
-
-    if A_np.shape[0] != A_np.shape[1]:
+    if A_np.ndim != 2:
+        raise ValueError("A phải là ma trận 2 chiều.")
+    if b_np.ndim != 1:
+        raise ValueError("b phải là vector 1 chiều.")
+    n = A_np.shape[0]
+    if A_np.shape[1] != n:
         raise ValueError("A phải là ma trận vuông.")
     if b_np.shape[0] != n:
         raise ValueError("Kích thước A và b không khớp.")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@part3/solvers.py` around lines 16 - 21, The function gauss_seidel currently
accesses A_np.shape[1] and assumes b_np is 1-D without validating dimensions;
add explicit guards that A_np.ndim == 2 and b_np.ndim == 1 (or accept b as 1-D
vector) before any use of shape[1], and raise ValueError with the existing
Vietnamese messages when these checks fail; then validate that A_np.shape[0] ==
A_np.shape[1] and b_np.shape[0] == n after the ndim checks so calls like
gauss_seidel([], []) or column-vector b with shape (n,1) produce the intended
ValueError instead of IndexError.

9-10: ⚠️ Potential issue | 🟠 Major

Keep benchmark stopping policy out of the solver defaults.

part3/benchmark.py:45-46 still calls gauss_seidel(A, b) with no overrides, so these defaults and the absolute ||x - x_old||₂ / ||Ax-b||₂ checks directly affect the time-vs-n and error-vs-n plots. That makes larger systems satisfy a stricter per-component threshold, so the benchmark mixes solver behavior with stopping-policy drift. Pass tolerance and max_iter explicitly from the benchmark, or switch this check to a relative or ord=np.inf criterion.

Also applies to: 42-46

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@part3/solvers.py` around lines 9 - 10, The solver default stopping policy is
leaking into benchmarks: update the gauss_seidel signature (the tolerance and
max_iter parameters) so the solver does not impose a hidden benchmark-specific
default—either remove the hardcoded defaults (or set them to None) and require
benchmark.py to call gauss_seidel(A, b, tolerance=..., max_iter=...) with
explicit values, or change the stopping test inside gauss_seidel to a relative
criterion (e.g., ||x - x_old||₂ / ||x||₂ or use ord=np.inf) so convergence is
scale-independent; adjust the benchmark invocation in benchmark.py (where
gauss_seidel(A, b) is called) to pass the chosen tolerance and max_iter
explicitly.
🧹 Nitpick comments (1)
part3/solvers.py (1)

26-30: Reword this warning for SPD cases.

Diagonal dominance is only a sufficient condition here. For the PR's SPD/Hilbert analysis, this warning will flag valid inputs where Gauss–Seidel is still expected to converge, so the message overstates the risk. Consider making it explicitly heuristic or skipping it for known SPD matrices.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@part3/solvers.py` around lines 26 - 30, The existing check on A_np's diagonal
dominance should be softened: change the warnings.warn message to a heuristic
phrasing (e.g., "Matrix is not strictly diagonally dominant; Gauss–Seidel may
still converge for SPD matrices or special cases.") and optionally skip emitting
the warning when A_np is detected as symmetric positive definite (check symmetry
A_np == A_np.T within tolerance and test SPD via a try/except around
np.linalg.cholesky). Update the warning logic around the diag/off_diag_sum check
so it only warns for non-SPD matrices or uses the new heuristic message when
SPD/Hilbert is detected, and reference the existing variables A_np, diag,
off_diag_sum and the Gauss–Seidel context in the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@part3/solvers.py`:
- Around line 16-21: The function gauss_seidel currently accesses A_np.shape[1]
and assumes b_np is 1-D without validating dimensions; add explicit guards that
A_np.ndim == 2 and b_np.ndim == 1 (or accept b as 1-D vector) before any use of
shape[1], and raise ValueError with the existing Vietnamese messages when these
checks fail; then validate that A_np.shape[0] == A_np.shape[1] and b_np.shape[0]
== n after the ndim checks so calls like gauss_seidel([], []) or column-vector b
with shape (n,1) produce the intended ValueError instead of IndexError.
- Around line 9-10: The solver default stopping policy is leaking into
benchmarks: update the gauss_seidel signature (the tolerance and max_iter
parameters) so the solver does not impose a hidden benchmark-specific
default—either remove the hardcoded defaults (or set them to None) and require
benchmark.py to call gauss_seidel(A, b, tolerance=..., max_iter=...) with
explicit values, or change the stopping test inside gauss_seidel to a relative
criterion (e.g., ||x - x_old||₂ / ||x||₂ or use ord=np.inf) so convergence is
scale-independent; adjust the benchmark invocation in benchmark.py (where
gauss_seidel(A, b) is called) to pass the chosen tolerance and max_iter
explicitly.

---

Nitpick comments:
In `@part3/solvers.py`:
- Around line 26-30: The existing check on A_np's diagonal dominance should be
softened: change the warnings.warn message to a heuristic phrasing (e.g.,
"Matrix is not strictly diagonally dominant; Gauss–Seidel may still converge for
SPD matrices or special cases.") and optionally skip emitting the warning when
A_np is detected as symmetric positive definite (check symmetry A_np == A_np.T
within tolerance and test SPD via a try/except around np.linalg.cholesky).
Update the warning logic around the diag/off_diag_sum check so it only warns for
non-SPD matrices or uses the new heuristic message when SPD/Hilbert is detected,
and reference the existing variables A_np, diag, off_diag_sum and the
Gauss–Seidel context in the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eb6fbde9-fb44-4ca7-9ba2-a4a20e1772d2

📥 Commits

Reviewing files that changed from the base of the PR and between bea07f7 and ace589d.

📒 Files selected for processing (1)
  • part3/solvers.py

aFlyingSeal
aFlyingSeal previously approved these changes Apr 19, 2026
@niuqohn2510 niuqohn2510 removed the request for review from TanKhoiTV April 19, 2026 15:14
@TanKhoiTV TanKhoiTV merged commit 6f816f6 into dev Apr 30, 2026
3 checks passed
@TanKhoiTV TanKhoiTV deleted the feat/log-log-plot branch April 30, 2026 15:12
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.

[BONUS 2pts] Log-log plots: time vs n, error vs n

3 participants