diff --git a/.github/workflows/main-arm64.yml b/.github/workflows/main-arm64.yml index 9b4810f..12ab3d1 100644 --- a/.github/workflows/main-arm64.yml +++ b/.github/workflows/main-arm64.yml @@ -4,7 +4,7 @@ on: push: # branches: [main] tags: - - '*' + - '*' # Run only when a new tag is pushed pull_request: workflow_dispatch: @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Install dependencies run: | @@ -29,12 +29,12 @@ jobs: python -m venv venvs/cu12 bash -c "source venvs/cu12/bin/activate && \ pip install --upgrade pip -qq && \ - pip install --pre --extra-index-url=https://pypi.nvidia.com cuopt-cu12==26.2.* -qq && + pip install --timeout=150 --extra-index-url=https://pypi.nvidia.com cuopt-cu12==26.4.* -qq && deactivate" python -m venv venvs/cu13 bash -c "source venvs/cu13/bin/activate && \ pip install --upgrade pip -qq && \ - pip install --pre --extra-index-url=https://pypi.nvidia.com cuopt-cu13==26.2.* -qq && + pip install --timeout=150 --extra-index-url=https://pypi.nvidia.com cuopt-cu13==26.4.* -qq && deactivate" # Get GAMS (ARM64 version) @@ -90,6 +90,9 @@ jobs: cp venvs/cu12/lib/python3.12/site-packages/nvidia/nvjitlink/lib/libnvJitLink.so.12 runtime-cu12/ cp venvs/cu12/lib/python3.12/site-packages/nvidia/curand/lib/libcurand.so.10 runtime-cu12/ cp venvs/cu12/lib/python3.12/site-packages/nvidia/cusparse/lib/libcusparse.so.12 runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libssl-*.so.1.1.1k runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libcares-*.so.2.2.0 runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libcrypto-*.so.1.1.1k runtime-cu12/ mkdir release-cu13 cp gmscuopt-cu13.out release-cu13/gmscuopt.out cp assets/* release-cu13/ @@ -109,28 +112,31 @@ jobs: cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcurand.so.10 runtime-cu13/ cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcusolver.so.12 runtime-cu13/ cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcusparse.so.12 runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libssl-*.so.1.1.1k runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libcares-*.so.2.2.0 runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libcrypto-*.so.1.1.1k runtime-cu13/ # Upload artifacts - name: Upload CUDA 12 link artifact to GitHub Actions (always) - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cuopt-link-cu12-arm64 path: release-cu12/ - name: Upload CUDA 12 runtime artifact to GitHub Actions (always) - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cu12-runtime-arm64 path: runtime-cu12/ - name: Upload CUDA 13 link artifact to GitHub Actions (always) - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cuopt-link-cu13-arm64 path: release-cu13/ - name: Upload CUDA 13 runtime artifact to GitHub Actions (always) - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cu13-runtime-arm64 path: runtime-cu13/ diff --git a/.github/workflows/main-x86_64.yml b/.github/workflows/main-x86_64.yml index c2e625d..29616f6 100644 --- a/.github/workflows/main-x86_64.yml +++ b/.github/workflows/main-x86_64.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Install dependencies run: | @@ -29,12 +29,12 @@ jobs: python -m venv venvs/cu12 bash -c "source venvs/cu12/bin/activate && \ pip install --upgrade pip -qq && \ - pip install --pre --extra-index-url=https://pypi.nvidia.com cuopt-cu12==26.2.* -qq && + pip install --timeout=150 --extra-index-url=https://pypi.nvidia.com cuopt-cu12==26.4.* -qq && deactivate" python -m venv venvs/cu13 bash -c "source venvs/cu13/bin/activate && \ pip install --upgrade pip -qq && \ - pip install --pre --extra-index-url=https://pypi.nvidia.com cuopt-cu13==26.2.* -qq && + pip install --timeout=150 --extra-index-url=https://pypi.nvidia.com cuopt-cu13==26.4.* -qq && deactivate" # Get GAMS @@ -90,6 +90,9 @@ jobs: cp venvs/cu12/lib/python3.12/site-packages/nvidia/nvjitlink/lib/libnvJitLink.so.12 runtime-cu12/ cp venvs/cu12/lib/python3.12/site-packages/nvidia/curand/lib/libcurand.so.10 runtime-cu12/ cp venvs/cu12/lib/python3.12/site-packages/nvidia/cusparse/lib/libcusparse.so.12 runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libssl-*.so.1.1.1k runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libcares-*.so.2.2.0 runtime-cu12/ + cp venvs/cu12/lib/python3.12/site-packages/libcuopt_cu12.libs/libcrypto-*.so.1.1.1k runtime-cu12/ mkdir release-cu13 cp gmscuopt-cu13.out release-cu13/gmscuopt.out cp assets/* release-cu13/ @@ -109,28 +112,31 @@ jobs: cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcurand.so.10 runtime-cu13/ cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcusolver.so.12 runtime-cu13/ cp venvs/cu13/lib/python3.12/site-packages/nvidia/cu13/lib/libcusparse.so.12 runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libssl-*.so.1.1.1k runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libcares-*.so.2.2.0 runtime-cu13/ + cp venvs/cu13/lib/python3.12/site-packages/libcuopt_cu13.libs/libcrypto-*.so.1.1.1k runtime-cu13/ # Upload artifacts - name: Upload CUDA 12 link artifact to GitHub Actions (always) - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cuopt-link-cu12 path: release-cu12/ - name: Upload CUDA 12 runtime artifact to GitHub Actions (always) - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cu12-runtime path: runtime-cu12/ - name: Upload CUDA 13 link artifact to GitHub Actions (always) - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cuopt-link-cu13 path: release-cu13/ - name: Upload CUDA 13 runtime artifact to GitHub Actions (always) - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: cu13-runtime path: runtime-cu13/ diff --git a/assets/optcuopt.def b/assets/optcuopt.def index b81a692..9582fb9 100644 --- a/assets/optcuopt.def +++ b/assets/optcuopt.def @@ -1,6 +1,7 @@ * * optcuopt.def * +* name type usermap default low high visible group num_cpu_threads integer 0 -1 -1 maxint 1 1 Controls the number of CPU threads used in the LP and MIP solvers (default GAMS Threads) num_gpus integer 0 1 1 2 1 2 Controls the number of GPUs to use for the solve. This setting is only relevant for LP problems that uses concurrent mode and supports up to 2 GPUs at the moment. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. presolve enumint 0 -1 1 1 Controls which presolver (if any) to use for presolve reductions. @@ -22,6 +23,11 @@ method enumint 0 0 1 2 Controls the method to solve the linear programming probl 1 1 pdlp Use the PDLP method. 2 1 dual_simplex Use the dual simplex method. 3 1 method_barrier Use the barrier (interior-point) method. +pdlp_precision enumint 0 -1 1 2 PDLP precision mode constants + -1 1 default By default, PDLP operates in the native precision of the problem type (FP64 for double-precision problems). + 0 1 single Run PDLP internally in FP32, with automatic conversion of inputs and outputs. FP32 uses half the memory and allows PDHG iterations to be on average twice as fast, but may require more iterations to converge. Compatible with crossover (solution is converted back to FP64 before crossover) and concurrent mode (PDLP runs in FP32 while other solvers run in FP64). + 1 1 double Explicitly run in FP64 (same as default for double-precision problems). + 2 1 mixed Use mixed precision SpMV during PDHG iterations. The constraint matrix is stored in FP32 while vectors and compute type remain in FP64, improving SpMV performance with limited impact on convergence. Convergence checking and restart logic always use the full FP64 matrix. iteration_limit integer 0 maxint 0 maxint 1 2 Controls the iteration limit after which the solver will stop and return the current solution (default GAMS IterLim) infeasibility_detection boolean 0 0 1 2 Controls whether PDLP should detect infeasibility strict_infeasibility boolean 0 0 1 2 Controls the strict infeasibility mode in PDLP @@ -62,7 +68,10 @@ dual_infeasible_tolerance double 0 1e-08 0 maxdouble 0 2 Unknown miptrace string 0 "" 1 3 filename of MIP trace file which logs the best found (incumbent) and best bound over time mipstart boolean -1 0 1 3 whether it should be tried to use the initial variable levels as initial MIP solution mip_heuristics_only boolean 0 0 1 3 Controls if only the GPU heuristics should be run -mip_scaling boolean 0 1 1 3 Controls if scaling should be applied to the MIP problem +mip_scaling enumint 0 1 1 3 Controls if scaling should be applied to the MIP problem + 0 1 no scaling + 1 1 full scaling (objective + row), default + 2 1 row scaling only (no objective scaling) mip_absolute_tolerance double 0 0.0001 0 maxdouble 1 3 Controls the MIP absolute tolerance mip_relative_tolerance double 0 0.0001 0 maxdouble 1 3 Controls the MIP relative tolerance mip_integrality_tolerance double 0 1e-05 0 maxdouble 1 3 Controls the MIP integrality tolerance @@ -73,10 +82,30 @@ mip_mixed_integer_rounding_cuts integer 0 -1 -1 1 1 3 Controls whether to use mi mip_mixed_integer_gomory_cuts integer 0 -1 -1 1 1 3 Controls whether to use mixed integer Gomory cuts mip_strong_chvatal_gomory_cuts integer 0 -1 -1 1 1 3 Controls whether to use strong Chvatal-Gomory cuts mip_knapsack_cuts integer 0 -1 -1 1 1 3 Controls whether to use knapsack cuts +mip_implied_bound_cuts integer 0 -1 -1 1 1 3 Controls whether to enable implied bound cuts (-1 auto/default, 0 off, >0 on) +mip_clique_cuts integer 0 -1 -1 1 1 3 Controls whether to enable clique cuts (-1 auto/default, 0 off, >0 on). mip_cut_change_threshold double 0 1e-03 0 maxdouble 1 3 Controls the threshold for the improvement in the dual bound per cut pass mip_cut_min_orthogonality double 0 0.5 0 maxdouble 1 3 Controls the minimum orthogonality required for a cut to be added to the LP relaxation mip_reduced_cost_strengthening integer 0 -1 -1 2 1 3 Controls whether to use reduced-cost strengthening mip_reliability_branching integer 0 -1 -1 maxint 1 3 Controls the reliablity branching mode +mip_strong_branching_simplex_iteration_limit integer 0 -1 -1 maxint 1 3 Controls the strong branching simplex iteration limit +mip_hyper_heuristic_population_size integer 0 32 0 maxint 1 3 Controls maximum number of solutions in pool +mip_hyper_heuristic_num_cpufj_threads integer 0 8 0 maxint 1 3 Controls parallel CPU FJ climbers +mip_hyper_heuristic_presolve_time_ratio double 0 0.1 0 1 1 3 Controls fraction of total time for presolve +mip_hyper_heuristic_presolve_max_time double 0 60 0 maxdouble 1 3 Controls the hard cap on presolve seconds +mip_hyper_heuristic_root_lp_time_ratio double 0 0.1 0 1 1 3 Controls fraction of total time for root LP +mip_hyper_heuristic_root_lp_max_time double 0 15 0 maxdouble 1 3 Controls the hard cap on root LP seconds +mip_hyper_heuristic_rins_time_limit double 0 3 0 maxdouble 1 3 Controls per-call RINS sub-MIP time +mip_hyper_heuristic_rins_max_time_limit double 0 20 0 maxdouble 1 3 Controls ceiling for RINS adaptive time budget +mip_hyper_heuristic_rins_fix_rate double 0 0.5 0 1 1 3 Controls RINS variable fix rate +mip_hyper_heuristic_stagnation_trigger integer 0 3 0 maxint 1 3 Controls FP loops w/o improvement before recombination +mip_hyper_heuristic_max_iterations_without_improvement integer 0 8 0 maxint 1 3 Controls diversity step depth after stagnation +mip_hyper_heuristic_initial_infeasibility_weight double 0 1000 0 maxdouble 1 3 Controls constraint violation penalty seed +mip_hyper_heuristic_n_of_minimums_for_exit integer 0 7000 0 maxint 1 3 Controls FJ baseline local-minima exit threshold +mip_hyper_heuristic_enabled_recombiners integer 0 15 0 maxint 1 3 Controls bitmask: 1=BP 2=FP 4=LS 8=SubMIP +mip_hyper_heuristic_cycle_detection_length integer 0 30 0 maxint 1 3 Controls FP assignment cycle ring buffer +mip_hyper_heuristic_relaxed_lp_time_limit double 0 1 0 maxdouble 1 3 Controls base relaxed LP time cap in heuristics +mip_hyper_heuristic_related_vars_time_limit double 0 30 0 maxdouble 1 3 Controls time for related-variable structure build * * Groups * diff --git a/gmscuopt.c b/gmscuopt.c index 3be82bc..86258a2 100644 --- a/gmscuopt.c +++ b/gmscuopt.c @@ -134,6 +134,7 @@ int main(int argc, char *argv[]) cuopt_int_t num_variables = gmoN(gmo); cuopt_int_t num_constraints = gmoM(gmo); cuopt_int_t nnz = gmoNZ(gmo); + //int64_t nnz = gmoNZ64(gmo); cuopt_int_t* constraint_matrix_row_offsets=NULL; cuopt_int_t* constraint_matrix_column_indices=NULL; @@ -511,38 +512,39 @@ int main(int argc, char *argv[]) gmoModelStatSet(gmo, gmoModelStat_NoSolutionReturned); if (!optGetDefinedStr(opt, "prob_read")) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: + case CUOPT_TERMINATION_STATUS_OPTIMAL: gmoModelStatSet(gmo, gmoModelStat_OptimalGlobal); break; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: + case CUOPT_TERMINATION_STATUS_INFEASIBLE: gmoModelStatSet(gmo, gmoModelStat_InfeasibleGlobal); break; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: + case CUOPT_TERMINATION_STATUS_UNBOUNDED: gmoModelStatSet(gmo, gmoModelStat_Unbounded); break; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: gmoSolveStatSet(gmo, gmoSolveStat_Iteration); break; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: gmoSolveStatSet(gmo, gmoSolveStat_Resource); break; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: gmoSolveStatSet(gmo, gmoSolveStat_SolverErr); break; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: if (gmoModelType(gmo) == gmoProc_mip && has_integer_vars) { gmoModelStatSet(gmo, gmoModelStat_Integer); } else { gmoModelStatSet(gmo, gmoModelStat_Feasible); } break; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: if (gmoModelType(gmo) == gmoProc_mip && has_integer_vars) { gmoModelStatSet(gmo, gmoModelStat_Integer); } else { gmoModelStatSet(gmo, gmoModelStat_Feasible); } break; + case CUOPT_TERMINATION_STATUS_UNBOUNDED_OR_INFEASIBLE: default: gmoSolveStatSet(gmo, gmoSolveStat_Solver); } @@ -751,21 +753,21 @@ t program for cuOpt linear programming solver const char* termination_status_to_string(cuopt_int_t termination_status) { switch (termination_status) { - case CUOPT_TERIMINATION_STATUS_OPTIMAL: + case CUOPT_TERMINATION_STATUS_OPTIMAL: return "Optimal"; - case CUOPT_TERIMINATION_STATUS_INFEASIBLE: + case CUOPT_TERMINATION_STATUS_INFEASIBLE: return "Infeasible"; - case CUOPT_TERIMINATION_STATUS_UNBOUNDED: + case CUOPT_TERMINATION_STATUS_UNBOUNDED: return "Unbounded"; - case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT: + case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT: return "Iteration limit"; - case CUOPT_TERIMINATION_STATUS_TIME_LIMIT: + case CUOPT_TERMINATION_STATUS_TIME_LIMIT: return "Time limit"; - case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR: + case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR: return "Numerical error"; - case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE: + case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE: return "Primal feasible"; - case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND: + case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND: return "Feasible found"; default: return "Unknown";