Python api performance improvement#1615
Conversation
Reduce model refresh and solution-population overhead independently of solver session persistence. Signed-off-by: Ishika Roy <iroy@ipp1-3302.aselab.nvidia.com>
Reuse cached model structures for value-only changes and avoid redundant solution invalidation across batched updates.
📝 WalkthroughWalkthroughChangesCache-aware linear programming and benchmark
Estimated code review effort: 4 (Complex) | ~60 minutes Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
script_perf_eval.py (1)
210-218: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winAvoid materializing the dense diagonal matrix.
np.diag(info["D_diag"])allocates an n×n dense array (n≈5000 ⇒ ~200 MB) on every objective evaluation just to computex @ D @ x. Use the elementwise form.♻️ Elementwise diagonal quadratic term
y = info["F"].T @ x_np z = np.abs(x_np - info["x0"]) - d_matrix = np.diag(info["D_diag"]) return ( -info["mu"] @ x_np + info["gamma"] - * (x_np @ d_matrix @ x_np + y @ info["Omega"] @ y) + * (x_np @ (info["D_diag"] * x_np) + y @ info["Omega"] @ y) + info["tc_rate"] * np.sum(z) )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@script_perf_eval.py` around lines 210 - 218, Update the objective calculation around the `d_matrix` expression to avoid constructing `np.diag(info["D_diag"])`; compute the diagonal quadratic term elementwise as the sum of `info["D_diag"]` multiplied by `x_np` squared, while preserving the existing objective value and remaining terms.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@python/cuopt/cuopt/linear_programming/problem.py`:
- Around line 2450-2457: Update Problem.solve to accept the session argument
used by script_perf_eval.py and pass it through to solver.Solve, preserving
existing settings behavior; alternatively, remove the session keyword from that
caller so the signatures remain aligned.
In `@script_perf_eval.py`:
- Line 778: Update the objective-record comparison loop over
baseline["objective_records"] and session["objective_records"] to use strict zip
semantics, ensuring differing record counts raise an error instead of silently
truncating. Preserve the existing per-record comparison logic.
- Around line 110-130: Update _capture_solver_output to drain the stderr pipe
concurrently while the yielded solve runs, using a reader thread or equivalent
that continuously consumes and stores output. Ensure cleanup restores fd 2,
waits for the reader to finish, closes descriptors, and preserves captured
output forwarding to sys.stderr.
- Around line 385-386: Initialize prob._session before the session-handling
logic in the relevant baseline/cold-session flow, ensuring it exists before
session_after_cold or any other read. Preserve the existing use_session behavior
that clears the session when enabled, and use a safe default of None for
uninitialized sessions.
- Around line 481-482: Update the Problem.solve invocation in the
_capture_solver_output block to pass only settings, removing the conditional
session keyword argument. Preserve the surrounding solver-output capture and
solution assignment behavior.
---
Nitpick comments:
In `@script_perf_eval.py`:
- Around line 210-218: Update the objective calculation around the `d_matrix`
expression to avoid constructing `np.diag(info["D_diag"])`; compute the diagonal
quadratic term elementwise as the sum of `info["D_diag"]` multiplied by `x_np`
squared, while preserving the existing objective value and remaining terms.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: c3b79d8a-3433-4ba3-bd5c-d4c71b4790c7
📒 Files selected for processing (2)
python/cuopt/cuopt/linear_programming/problem.pyscript_perf_eval.py
| if ( | ||
| self.model is None | ||
| or self.constraint_csr_matrix is None | ||
| or self._stale["structure"] | ||
| ): | ||
| self._to_data_model() | ||
| else: | ||
| self._refresh_data_model_values() |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find solve() definitions and all call sites passing `session=`
ast-grep run --pattern 'def solve($$$):' --lang python python/cuopt/cuopt/linear_programming/problem.py
rg -nP '\.solve\s*\(' --type=py -g '!**/tests/**' -C1
rg -nP '\bsession\b' --type=py python/cuopt/cuopt/linear_programming/problem.pyRepository: NVIDIA/cuopt
Length of output: 150
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the solve signature and nearby implementation.
ast-grep outline python/cuopt/cuopt/linear_programming/problem.py --view expanded | sed -n '1,220p'
printf '\n--- solve signature/implementation ---\n'
rg -n "^\s*def solve\b|session\b|Solve\(" python/cuopt/cuopt/linear_programming/problem.py -n -C 3
printf '\n--- solve call sites with session kwarg ---\n'
rg -nP '\.solve\s*\(.*session\s*=' -g '!**/tests/**' -t py .
printf '\n--- _solve_one_objective definition ---\n'
rg -n "_solve_one_objective|session=" -g '!**/tests/**' -t py .Repository: NVIDIA/cuopt
Length of output: 7291
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the benchmark caller and inspect its invocation.
fd -a "script_perf_eval.py|problem.py" .
rg -n "_solve_one_objective|prob\.solve\(" -g 'script_perf_eval.py' -g 'python/cuopt/cuopt/linear_programming/problem.py' -C 4 .Repository: NVIDIA/cuopt
Length of output: 4821
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import re
problem = Path("python/cuopt/cuopt/linear_programming/problem.py")
text = problem.read_text()
print("solve definitions:")
for m in re.finditer(r'^\s*def\s+solve\s*\(([^)]*)\)\s*:', text, re.M):
start = text.count("\n", 0, m.start()) + 1
print(start, m.group(1))
print("\nlines around solve:")
for i, line in enumerate(text.splitlines(), 1):
if 2438 <= i <= 2470:
print(f"{i}:{line}")
print("\ncall sites with session kwarg:")
for p in Path(".").rglob("*.py"):
if "tests" in p.parts:
continue
s = p.read_text(errors="ignore")
if ".solve(" in s and "session=" in s:
for m in re.finditer(r'\.solve\s*\(([^)]*session\s*=)', s, re.S):
ln = s.count("\n", 0, m.start()) + 1
print(f"{p}:{ln}")
PYRepository: NVIDIA/cuopt
Length of output: 1231
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find the benchmark caller and any solve invocations with session kwarg.
rg -n "_solve_one_objective|prob\.solve\(|session=" -g '*.py' .Repository: NVIDIA/cuopt
Length of output: 3155
Align Problem.solve with its session caller.
Problem.solve still only accepts settings, but script_perf_eval.py calls it with session=..., which will raise TypeError at that path. Either add the session parameter and thread it through to solver.Solve, or drop the kwarg at the call site.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@python/cuopt/cuopt/linear_programming/problem.py` around lines 2450 - 2457,
Update Problem.solve to accept the session argument used by script_perf_eval.py
and pass it through to solver.Solve, preserving existing settings behavior;
alternatively, remove the session keyword from that caller so the signatures
remain aligned.
| @contextmanager | ||
| def _capture_solver_output(): | ||
| """Capture C++ solver logs written directly to stderr (fd 2).""" | ||
| read_fd, write_fd = os.pipe() | ||
| saved_stderr = os.dup(2) | ||
| capture = io.StringIO() | ||
| try: | ||
| os.dup2(write_fd, 2) | ||
| os.close(write_fd) | ||
| yield capture | ||
| finally: | ||
| os.dup2(saved_stderr, 2) | ||
| os.close(saved_stderr) | ||
| with os.fdopen(read_fd, "r", encoding="utf-8", errors="replace") as reader: | ||
| text = reader.read() | ||
| capture.write(text) | ||
| capture.seek(0) | ||
| if text: | ||
| sys.stderr.write(text) | ||
| sys.stderr.flush() | ||
|
|
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path('script_perf_eval.py')
lines = p.read_text().splitlines()
for start, end in [(1, 170), (360, 520)]:
print(f"\n--- {p}:{start}-{end} ---")
for i, line in enumerate(lines[start-1:end], start):
print(f"{i:4d}: {line}")
PYRepository: NVIDIA/cuopt
Length of output: 13226
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path('script_perf_eval.py')
lines = p.read_text().splitlines()
# quick structural checks
for needle in ["import threading", "_capture_solver_output", "prob.solve(", "CUOPT_CACHE_PROFILE", "_session"]:
print(f"\n== {needle} ==")
for i, line in enumerate(lines, 1):
if needle in line:
print(f"{i}: {line}")
PYRepository: NVIDIA/cuopt
Length of output: 2710
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path('script_perf_eval.py')
lines = p.read_text().splitlines()
print("Imports of interest:")
for needle in ["import threading", "from threading", "_capture_solver_output", "prob.solve(", "CUOPT_CACHE_PROFILE", "_session"]:
matches = [f"{i}: {line}" for i, line in enumerate(lines, 1) if needle in line]
if matches:
print(f"\n{needle}")
print("\n".join(matches))
PYRepository: NVIDIA/cuopt
Length of output: 2683
Drain solver stderr while the solve is running. script_perf_eval.py:110-130 only reads the pipe after yield, so a verbose prob.solve() can fill the buffer, block on write(2), and hang this benchmark. Use a concurrent reader instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@script_perf_eval.py` around lines 110 - 130, Update _capture_solver_output to
drain the stderr pipe concurrently while the yielded solve runs, using a reader
thread or equivalent that continuously consumes and stores output. Ensure
cleanup restores fd 2, waits for the reader to finish, closes descriptors, and
preserves captured output forwarding to sys.stderr.
| if use_session: | ||
| prob._session = None |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm Problem initializes a `_session` attribute
fd -e py problem.py --full-path 'linear_programming' \
| xargs rg -nP '_session' -C2Repository: NVIDIA/cuopt
Length of output: 7174
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the portfolio problem builder and the Problem class definition that may initialize `_session`.
rg -n "def build_cuopt_portfolio_problem|class Problem|_session" script_perf_eval.py . -g '!**/.git/**' -g '!**/__pycache__/**' | sed -n '1,220p'Repository: NVIDIA/cuopt
Length of output: 4679
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the relevant sections around run_cache_benchmark and the helper that constructs `prob`.
sed -n '340,470p' script_perf_eval.pyRepository: NVIDIA/cuopt
Length of output: 5112
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Search the repository for any `_session` initialization on the portfolio problem path.
fd -a . . | sed -n '1,200p'Repository: NVIDIA/cuopt
Length of output: 11899
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find the file that defines `build_cuopt_portfolio_problem` and inspect `_session` handling nearby.
file=$(rg -l "def build_cuopt_portfolio_problem" . -g '!**/.git/**' -g '!**/__pycache__/**' | head -n 1)
echo "FILE=$file"
if [ -n "${file:-}" ]; then
rg -n "_session|class Problem|def build_cuopt_portfolio_problem" "$file" -C3
fiRepository: NVIDIA/cuopt
Length of output: 6402
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Search for `_session` initialization in the repository, especially on portfolio-related objects.
rg -n "self\._session|_session\s*=|def build_cuopt_portfolio_problem|class Problem" . -g '!**/.git/**' -g '!**/__pycache__/**' | sed -n '1,240p'Repository: NVIDIA/cuopt
Length of output: 1121
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the Problem class definition and any `_session` usage in the Python wrapper.
problem_file=python/cuopt/cuopt/linear_programming/problem.py
sed -n '1403,1565p' "$problem_file"
echo
rg -n "_session|session" "$problem_file" -C2Repository: NVIDIA/cuopt
Length of output: 5758
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Look for `Problem.__init__` details and whether attributes are initialized there.
problem_file=python/cuopt/cuopt/linear_programming/problem.py
rg -n "def __init__|self\._session|session" "$problem_file" -C4Repository: NVIDIA/cuopt
Length of output: 1853
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the top of the class methods around initialization without loading the full file.
problem_file=python/cuopt/cuopt/linear_programming/problem.py
sed -n '1403,1495p' "$problem_file"Repository: NVIDIA/cuopt
Length of output: 3073
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the beginning of `Problem` for attribute initialization and constructor behavior.
problem_file=python/cuopt/cuopt/linear_programming/problem.py
sed -n '1403,1515p' "$problem_file"Repository: NVIDIA/cuopt
Length of output: 3741
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Search for any `_session` attribute initialization on `Problem` or its base classes.
rg -n "self\._session|_session\s*=|__slots__" python/cuopt/cuopt/linear_programming -g '*.py' -g '*.pyx' -g '*.pxd' -C3Repository: NVIDIA/cuopt
Length of output: 150
Initialize _session before reading it script_perf_eval.py:385-445 Baseline mode never assigns _session, and Problem.__init__() doesn’t create it, so session_after_cold can raise AttributeError here.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@script_perf_eval.py` around lines 385 - 386, Initialize prob._session before
the session-handling logic in the relevant baseline/cold-session flow, ensuring
it exists before session_after_cold or any other read. Preserve the existing
use_session behavior that clears the session when enabled, and use a safe
default of None for uninitialized sessions.
| with _capture_solver_output(): | ||
| solution = prob.solve(settings, session=session if use_session else None) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Inspect the current solve() signature
fd -e py problem.py --full-path 'linear_programming' \
| xargs ast-grep run --pattern 'def solve($$$):' --lang pythonRepository: NVIDIA/cuopt
Length of output: 260
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Files:\n'
git ls-files | rg '(^|/)script_perf_eval\.py$|(^|/)problem\.py$'
printf '\n--- script_perf_eval.py around the cited lines ---\n'
sed -n '460,500p' script_perf_eval.py
printf '\n--- problem.py solve definitions ---\n'
ast-grep outline python/cuopt/cuopt/linear_programming/problem.py --view expanded || true
printf '\n--- solve signatures in problem.py ---\n'
ast-grep run --pattern 'def solve($$$):' --lang python python/cuopt/cuopt/linear_programming/problem.py || true
printf '\n--- text search for session usage in problem.py ---\n'
rg -n 'session' python/cuopt/cuopt/linear_programming/problem.py || trueRepository: NVIDIA/cuopt
Length of output: 6809
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Broaden search in case the file lives elsewhere or the path differs.
git ls-files | rg 'problem\.py$|script_perf_eval\.py$' || true
# Read only the relevant file sections if present.
for f in script_perf_eval.py python/cuopt/cuopt/linear_programming/problem.py; do
if [ -f "$f" ]; then
printf '\n### %s ###\n' "$f"
wc -l "$f"
if [ "$f" = "script_perf_eval.py" ]; then
sed -n '470,490p' "$f"
else
sed -n '1,260p' "$f"
fi
fi
doneRepository: NVIDIA/cuopt
Length of output: 7819
🌐 Web query:
site:github.com NVIDIA cuopt "class Problem" solve session cuopt/linear_programming/problem.py
💡 Result:
The file cuopt/linear_programming/problem.py is a core component of the NVIDIA cuOpt Python API for numerical optimization [1][2][3]. It defines the Problem class, which serves as the primary interface for modeling and solving linear programming (LP), quadratic programming (QP), and mixed-integer linear programming (MILP) problems [4][5][6][7]. Key functionalities provided by the Problem class and managed within this file include: Modeling: Users can construct models by adding variables (addVariable) [5], defining constraints (addConstraint) [5], and setting objectives (setObjective) [5]. The API supports algebraic modeling, allowing for intuitive definitions of constraints and objectives [4][6]. Solver Interaction: The solve method triggers the underlying GPU-accelerated optimization engine [5][6]. After solving, results can be accessed through object attributes or utility functions like getIncumbentValues [8][5][9]. File I/O: The class provides methods for reading problem files (such as those in MPS format) via ParseProblem and the read method, which has been updated to handle various file formats efficiently [3][10]. Internal Helpers: The file contains internal utility logic for algebraic representation (e.g., str and repr for model visualization), formatting expressions, and handling parameter updates (such as allowing zero-valued updates for constraints and objectives) [2][4]. For those looking to use this module, it is recommended to follow the official Python API usage patterns: from cuopt.linear_programming.problem import Problem, CONTINUOUS, MAXIMIZE from cuopt.linear_programming.solver_settings import SolverSettings # Initialize and build model problem = Problem("MyProblem") x = problem.addVariable(lb=0, vtype=CONTINUOUS, name="x") problem.addConstraint(2x <= 10, name="c1") problem.setObjective(5x, sense=MAXIMIZE) # Solve settings = SolverSettings problem.solve(settings) If you encounter issues, the NVIDIA cuOpt GitHub repository serves as the primary source for documentation, issue tracking, and examples [7][11]. Specific tasks like retrieving solutions after a solve or using callbacks are addressed within the issue tracker and pull request discussions linked to this module [8][9].
Citations:
- 1: https://github.com/nvidia/cuopt/blob/main/skills/cuopt-numerical-optimization-api/references/python_api.md
- 2: Allow zero-valued LP Python model updates #1421
- 3: Follow-up for LP format #1251
- 4: Add algebraic __str__ and detailed __repr__ to Python LP API classes #1400
- 5: https://github.com/NVIDIA/cuopt/blob/main/skills/cuopt-lp-milp-api-python/SKILL.md
- 6: https://github.com/NVIDIA/cuopt/blob/main/README.md
- 7: https://github.com/nvidia/cuopt
- 8: [QST] How do I get the values of the solution after calling .solve() #932
- 9: update doc for usage of incumbent utility function #947
- 10: Update LP/QP/MILP docs to cover 26.06 API additions #1339
- 11: https://github.com/NVIDIA/cuopt-examples
🌐 Web query:
cuOpt linear_programming Problem.solve session parameter python cuopt problem.py
💡 Result:
In the NVIDIA cuOpt Python API for linear programming, you do not directly pass a session parameter to the Problem.solve method. Instead, you use the cuopt.linear_programming.solver_settings.SolverSettings class to configure solver parameters and then pass that object to the solve method [1][2][3]. To configure and solve a problem, follow this standard pattern: 1. Import the necessary classes [2][3]. 2. Instantiate the SolverSettings object [2][3]. 3. Use the set_parameter(name, value) method on your settings object to define specific solver configurations (such as time_limit or mip_relative_gap) [1][2]. 4. Pass this settings object to the problem.solve method [1][4][3]. Example usage: from cuopt.linear_programming.problem import Problem from cuopt.linear_programming.solver_settings import SolverSettings # Create your problem instance problem = Problem("MyProblem") #... define variables and constraints... # Configure solver settings settings = SolverSettings settings.set_parameter("time_limit", 60) settings.set_parameter("mip_relative_gap", 0.01) # Solve the problem with the configured settings problem.solve(settings) When working with these parameters, note that if you are using the Server Thin client or CLI, you generally remove the CUOPT_ prefix from parameter names and convert them to lowercase (e.g., CUOPT_TIME_LIMIT becomes time_limit) [5][6][7]. For a complete list of available parameters and their valid ranges, refer to the official cuOpt documentation under the Solver Settings section [1][7].
Citations:
- 1: https://docs.nvidia.com/cuopt/user-guide/26.02.00/cuopt-python/lp-qp-milp/lp-qp-milp-api.html
- 2: https://github.com/nvidia/skills/blob/HEAD/skills/cuopt-numerical-optimization-api/references/python_api.md
- 3: https://github.com/NVIDIA/cuopt/blob/main/skills/cuopt-lp-milp-api-python/SKILL.md
- 4: https://docs.nvidia.com/cuopt/user-guide/latest/cuopt-python/lp-qp-milp/lp-qp-milp-api.html
- 5: https://docs.nvidia.com/cuopt/user-guide/latest/lp-milp-settings.html
- 6: https://docs.nvidia.com/cuopt/user-guide/26.02.00/lp-qp-milp-settings.html
- 7: https://docs.nvidia.com/cuopt/user-guide/26.04.00/lp-qp-milp-settings.html
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the exact solve method definition and body around it.
sed -n '2428,2488p' python/cuopt/cuopt/linear_programming/problem.py
printf '\n--- any other solve defs in the file ---\n'
rg -n '^(\s*)def solve\(' python/cuopt/cuopt/linear_programming/problem.py
printf '\n--- any kwargs passthrough near solve ---\n'
rg -n 'kwargs|session|lp_solve_session|_session' python/cuopt/cuopt/linear_programming/problem.pyRepository: NVIDIA/cuopt
Length of output: 1538
Remove the session= keyword here. Problem.solve only accepts settings, so this call will raise TypeError whenever use_session is true.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@script_perf_eval.py` around lines 481 - 482, Update the Problem.solve
invocation in the _capture_solver_output block to pass only settings, removing
the conditional session keyword argument. Preserve the surrounding solver-output
capture and solution assignment behavior.
| print("Cross-process objective check (baseline vs session)") | ||
| print("=" * 50) | ||
| all_ok = True | ||
| for b_rec, s_rec in zip(baseline["objective_records"], session["objective_records"]): |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add strict=True to catch record-count mismatch.
If the two processes emit a different number of objective_records, zip silently truncates and the missing entries are never compared, defeating the cross-process check. strict=True surfaces the discrepancy.
💚 Proposed fix
- for b_rec, s_rec in zip(baseline["objective_records"], session["objective_records"]):
+ for b_rec, s_rec in zip(
+ baseline["objective_records"], session["objective_records"], strict=True
+ ):📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for b_rec, s_rec in zip(baseline["objective_records"], session["objective_records"]): | |
| for b_rec, s_rec in zip( | |
| baseline["objective_records"], session["objective_records"], strict=True | |
| ): |
🧰 Tools
🪛 Ruff (0.15.21)
[warning] 778-778: zip() without an explicit strict= parameter
Add explicit value for parameter strict=
(B905)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@script_perf_eval.py` at line 778, Update the objective-record comparison loop
over baseline["objective_records"] and session["objective_records"] to use
strict zip semantics, ensuring differing record counts raise an error instead of
silently truncating. Preserve the existing per-record comparison logic.
Source: Linters/SAST tools
Description
The 100ms shave off helps in consecutive solves of portfolio problems which solve in 300-500ms.
Issue
Checklist