Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
26a268c
Implement flow cover cuts
hlinsen Apr 6, 2026
f78db98
Merge branch 'main' of github.com:NVIDIA/cuopt into flow-cover-cuts
hlinsen Apr 20, 2026
b37aa78
Reuse existing knapsack code
hlinsen Apr 20, 2026
b8c22c6
Merge branch 'main' of github.com:NVIDIA/cuopt into flow-cover-cuts
hlinsen Apr 21, 2026
6404cf4
Fix compile errors
hlinsen Apr 22, 2026
fff82f0
Fix merge conflicts
hlinsen Apr 27, 2026
2715946
Implement 0-1 single node flow relaxation
hlinsen Apr 28, 2026
a2771c2
Implement variable bound extension
hlinsen Apr 29, 2026
79265a2
Use wolter 5.1 approximation for knapsack
hlinsen Apr 29, 2026
f490e33
Fix invalid cut generation
hlinsen Apr 30, 2026
6e7481b
Add asserts
hlinsen Apr 30, 2026
c44b30c
Clean up
hlinsen Apr 30, 2026
eaf947a
Fix merge conflicts
hlinsen Apr 30, 2026
5a88ab7
Merge branch 'main' of github.com:NVIDIA/cuopt into flow-cover-cuts
hlinsen May 1, 2026
ff56b94
Re add substitution
hlinsen May 5, 2026
070874a
Add comments
hlinsen May 5, 2026
b240a99
Add example
hlinsen May 5, 2026
e62eecd
Generate minimalist tests
hlinsen May 5, 2026
45bc405
Disable variable bound prop
hlinsen May 5, 2026
462b9a1
Merge branch 'main' of github.com:NVIDIA/cuopt into flow-cover-cuts
hlinsen May 5, 2026
2908d72
Fix compile errors
hlinsen May 6, 2026
af621c7
Merge branch 'main' of github.com:NVIDIA/cuopt into flow-cover-cuts
hlinsen May 11, 2026
393cff1
Fix indexing bug
hlinsen May 12, 2026
e0db214
Merge knapsack paths
hlinsen May 12, 2026
5eb449e
Fix regression on other cuts, use tolerance from settings
hlinsen May 12, 2026
013a1a8
Merge branch 'main' of github.com:NVIDIA/cuopt into flow-cover-cuts
hlinsen May 12, 2026
cbc8e38
Skip continuous vars in bounds subsitution
hlinsen May 12, 2026
1b16d12
Re add early exit
hlinsen May 12, 2026
5a2e8f0
Remove redundant checks
hlinsen May 12, 2026
96fe8a3
Drop unused param
hlinsen May 12, 2026
bea839a
Refactor
hlinsen May 12, 2026
e9714ea
Fix regression
hlinsen May 13, 2026
3907973
Merge branch 'main' of github.com:NVIDIA/cuopt into flow-cover-cuts
hlinsen May 13, 2026
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