Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions benchmarks/linear_programming/run_mps_files.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
# --batch-num : Batch number. This allows to split the work across multiple batches uniformly when resources are limited.
# --n-batches : Number of batches
# --log-to-console : Log to console
# --recursive : Recursively search for .mps/.MPS/.SIF files under --path
# --cut-mode : Cut family configuration: default, no-cuts, flow-cover-only
#
# Examples:
# # Run all MPS files in /data/lp using 2 GPUs with 1 hour time limit
Expand Down Expand Up @@ -75,6 +77,8 @@ Optional Arguments:
--log-to-console Log to console
--model-list File containing a list of models to run
--pdlp-tolerances Tolerances for PDLP solver (default: 1e-4)
--recursive Recursively search for .mps/.MPS/.SIF files under --path
--cut-mode MODE Cut family configuration: default, no-cuts, flow-cover-only
-h, --help Show this help message and exit

Examples:
Expand Down Expand Up @@ -193,6 +197,16 @@ while [[ $# -gt 0 ]]; do
PDLP_TOLERANCES="$2"
shift 2
;;
--recursive)
echo "RECURSIVE: true"
RECURSIVE=true
shift
;;
--cut-mode)
echo "CUT_MODE: $2"
CUT_MODE="$2"
shift 2
;;
*)
echo "Unknown argument: $1"
print_help
Expand Down Expand Up @@ -221,13 +235,24 @@ N_BATCHES=${N_BATCHES:-1}
LOG_TO_CONSOLE=${LOG_TO_CONSOLE:-true}
MODEL_LIST=${MODEL_LIST:-}
PDLP_TOLERANCES=${PDLP_TOLERANCES:-1e-4}
RECURSIVE=${RECURSIVE:-false}
CUT_MODE=${CUT_MODE:-default}

# Validate GPUS_PER_INSTANCE
if [[ "$GPUS_PER_INSTANCE" != "1" && "$GPUS_PER_INSTANCE" != "2" ]]; then
echo "Error: --gpus-per-instance must be 1 or 2"
exit 1
fi

case "$CUT_MODE" in
default|no-cuts|flow-cover-only)
;;
*)
echo "Error: --cut-mode must be one of: default, no-cuts, flow-cover-only"
exit 1
;;
esac

# Determine GPU list
if [[ -n "$CUDA_VISIBLE_DEVICES" ]]; then
IFS=',' read -ra GPU_LIST <<< "$CUDA_VISIBLE_DEVICES"
Expand Down Expand Up @@ -331,8 +356,12 @@ if [[ -n "$MODEL_LIST" ]]; then
exit 1
fi
else
# Gather both .mps and .SIF files in the directory
mapfile -t mps_files < <(ls "$MPS_DIR"/*.mps "$MPS_DIR"/*.SIF 2>/dev/null)
if [ "$RECURSIVE" = true ]; then
mapfile -t mps_files < <(find "$MPS_DIR" -type f \( -name "*.mps" -o -name "*.MPS" -o -name "*.SIF" \) | sort)
else
# Gather .mps/.MPS and .SIF files in the directory
mapfile -t mps_files < <(ls "$MPS_DIR"/*.mps "$MPS_DIR"/*.MPS "$MPS_DIR"/*.SIF 2>/dev/null)
fi
Comment on lines +359 to +364
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Recursive mode can clobber per-model log files.

With --recursive, two models from different subdirectories can share the same basename, but the worker still writes logs to $(basename ...).log. The later run overwrites the earlier one, so benchmark results become incomplete whenever --write-log-file is enabled.

Suggested fix
-        if [ "$WRITE_LOG_FILE" = true ]; then
-            args="$args --log-file $OUTPUT_DIR/$(basename "${mps_file%.mps}").log"
-        fi
+        if [ "$WRITE_LOG_FILE" = true ]; then
+            rel_model_path="${mps_file#$MPS_DIR/}"
+            safe_model_name="${rel_model_path//\//__}"
+            safe_model_name="${safe_model_name%.mps}"
+            safe_model_name="${safe_model_name%.MPS}"
+            safe_model_name="${safe_model_name%.SIF}"
+            args="$args --log-file $OUTPUT_DIR/${safe_model_name}.log"
+        fi
🤖 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 `@benchmarks/linear_programming/run_mps_files.sh` around lines 359 - 364, The
recursive file collection can produce duplicate basenames that cause log files
to be overwritten; update the code that constructs per-model log filenames to
include a path-unique component (e.g., use the file's path relative to MPS_DIR
with slashes replaced by safe separators or use dirname+basename) so each entry
in mps_files yields a unique log name when RECURSIVE=true and --write-log-file
is enabled; locate where run_mps_files.sh iterates over the mps_files array and
replace uses of basename (or "$(basename "$file").log") with a deterministic
path-derived filename (for example "${file#$MPS_DIR/}" with non-alphanumerics
normalized) to avoid clobbering logs.


echo "Found ${#mps_files[@]} .mps and .SIF files in $MPS_DIR"
fi
Expand Down Expand Up @@ -420,6 +449,11 @@ worker() {
if [ -n "$METHOD" ]; then
args="$args --method $METHOD"
fi
if [ "$CUT_MODE" = "no-cuts" ]; then
args="$args --mip-mixed-integer-rounding-cuts 0 --mip-mixed-integer-gomory-cuts 0 --mip-knapsack-cuts 0 --mip-flow-cover-cuts 0 --mip-clique-cuts 0 --mip-implied-bound-cuts 0 --mip-strong-chvatal-gomory-cuts 0 --mip-reduced-cost-strengthening 0"
elif [ "$CUT_MODE" = "flow-cover-only" ]; then
args="$args --mip-mixed-integer-rounding-cuts 0 --mip-mixed-integer-gomory-cuts 0 --mip-knapsack-cuts 0 --mip-flow-cover-cuts 1 --mip-clique-cuts 0 --mip-implied-bound-cuts 0 --mip-strong-chvatal-gomory-cuts 0 --mip-reduced-cost-strengthening 0"
fi
if [ -n "$PDLP_TOLERANCES" ]; then
args="$args --absolute-primal-tolerance $PDLP_TOLERANCES --absolute-dual-tolerance $PDLP_TOLERANCES --relative-primal-tolerance $PDLP_TOLERANCES --relative-dual-tolerance $PDLP_TOLERANCES --absolute-gap-tolerance $PDLP_TOLERANCES --relative-gap-tolerance $PDLP_TOLERANCES"
fi
Expand Down
1 change: 1 addition & 0 deletions cpp/include/cuopt/linear_programming/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#define CUOPT_MIP_MIXED_INTEGER_ROUNDING_CUTS "mip_mixed_integer_rounding_cuts"
#define CUOPT_MIP_MIXED_INTEGER_GOMORY_CUTS "mip_mixed_integer_gomory_cuts"
#define CUOPT_MIP_KNAPSACK_CUTS "mip_knapsack_cuts"
#define CUOPT_MIP_FLOW_COVER_CUTS "mip_flow_cover_cuts"
#define CUOPT_MIP_IMPLIED_BOUND_CUTS "mip_implied_bound_cuts"
#define CUOPT_MIP_CLIQUE_CUTS "mip_clique_cuts"
#define CUOPT_MIP_STRONG_CHVATAL_GOMORY_CUTS "mip_strong_chvatal_gomory_cuts"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class mip_solver_settings_t {
i_t mir_cuts = -1;
i_t mixed_integer_gomory_cuts = -1;
i_t knapsack_cuts = -1;
i_t flow_cover_cuts = -1;
i_t clique_cuts = -1;
i_t implied_bound_cuts = -1;
i_t strong_chvatal_gomory_cuts = -1;
Expand Down
Loading
Loading