Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9cfe2d9
align service api with SDK (compat with deprecations)
tmckayus Jul 23, 2025
9146959
cuopt server add missing parameters to align with SDK
tmckayus Jul 23, 2025
c045f15
cuopt server get rid of lp_datamodel_compat for solver configs
tmckayus Jul 23, 2025
5c038a7
add missing parameters to service and solver_settings.py
tmckayus Jul 23, 2025
f3e680c
cuopt client fix up ThinClientSolverSettings
tmckayus Jul 24, 2025
edaeef7
cuopt client include deprecated parameters in ThinClientSolverSettings
tmckayus Jul 25, 2025
61bf06f
cuopt service resolve conflict with log_file parameter and callbacks
tmckayus Jul 25, 2025
6d4f724
docs change CUOPT_HEURISTICS_ONLY to CUOPT_MIP_HEURISTICS_ONLY
tmckayus Jul 25, 2025
2fe92ac
add test for solver_config parameter names
tmckayus Jul 25, 2025
e3d987c
Merge branch 'branch-25.08' into apisync
tmckayus Jul 28, 2025
ca66e24
cuopt docs add some clarity around logging and incumbents
tmckayus Jul 28, 2025
54a2e67
cuopt service add deprecation warnings for legacy solver_configs
tmckayus Jul 28, 2025
54f99d3
update transition guide for solver_configs changes
tmckayus Jul 28, 2025
cdabf66
fix style issues
rgsl888prabhu Jul 28, 2025
533e57c
Merge branch 'branch-25.08' of github.com:nvidia/cuopt into apisync
rgsl888prabhu Jul 28, 2025
6c89b66
tweak transition guide
tmckayus Jul 28, 2025
ebd3cf5
cuopt server add deprecated=True to solver_config fields
tmckayus Jul 28, 2025
6c14473
cuopt service disable solver config file options
tmckayus Jul 29, 2025
16499d4
cuopt service fix up docs related to log_file solver config
tmckayus Jul 29, 2025
09ad0ba
cuopt service fix up docs on log_file solver config
tmckayus Jul 29, 2025
c6336be
cuopt service additional doc and comment tweaks
tmckayus Jul 29, 2025
03966cf
cuopt service fix disable of log_file in batch LP mode
tmckayus Jul 29, 2025
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
4 changes: 4 additions & 0 deletions ci/test_self_hosted_service.sh
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ if [ "$doservertest" -eq 1 ]; then
# Test for message on absolute path, bad directory
run_cli_test "Absolute path '/nohay' does not exist" cuopt_sh -s -c "$CLIENT_CERT" -p $CUOPT_SERVER_PORT -f /nohay/nada

# Set all current and deprecated solver_config values and make sure the service does not reject the dataset
# This is a smoketest against parameter name misalignment
run_cli_test "'status': 'Optimal'" cuopt_sh -s -c $CLIENT_CERT -p $CUOPT_SERVER_PORT ../../datasets/cuopt_service_data/lpmip_configs.json

rapids-logger "Running cuopt_self_hosted Python tests"
pytest tests

Expand Down
103 changes: 103 additions & 0 deletions datasets/cuopt_service_data/lpmip_configs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{
"csr_constraint_matrix": {
"offsets": [
0,
2,
4
],
"indices": [
0,
1,
0,
1
],
"values": [
3.0,
4.0,
2.7,
10.1
]
},
"constraint_bounds": {
"bounds": [
5.4,
4.9
],
"upper_bounds": [
5.4,
4.9
],
"lower_bounds": [
"ninf",
"ninf"
]
},
"objective_data": {
"coefficients": [
0.2,
0.1
],
"scalability_factor": 1.0,
"offset": 0.0
},
"variable_bounds": {
"upper_bounds": [
"inf",
"inf"
],
"lower_bounds": [
0.0,
0.0
]
},
"maximize": false,
"solver_config": {
"tolerances": {
"optimality": 0.0001,
"absolute_primal_tolerance": 0.0001,
"absolute_dual_tolerance": 0.0001,
"absolute_gap_tolerance": 0.0001,
"relative_primal_tolerance": 0.0001,
"relative_dual_tolerance": 0.0001,
"relative_gap_tolerance": 0.0001,
"primal_infeasible_tolerance": 0.0001,
"dual_infeasible_tolerance": 0.0001,
"mip_integrality_tolerance": 0.0001,
"mip_absolute_gap": 0.0001,
"mip_relative_gap": 0.0001,
"mip_absolute_tolerance": 0.0001,
"mip_relative_tolerance": 0.0001,

"absolute_primal": 0.0001,
"absolute_dual": 0.0001,
"absolute_gap": 0.0001,
"relative_primal": 0.0001,
"relative_dual": 0.0001,
"relative_gap": 0.0001,
"primal_infeasible": 0.0001,
"dual_infeasible": 0.0001,
"integrality_tolerance": 0.0001,
"absolute_mip_gap": 0.0001,
"relative_mip_gap": 0.0001
},
"infeasibility_detection": true,
"time_limit": 5,
"iteration_limit": 100,
"pdlp_solver_mode": 2,
"method": 2,
"mip_scaling": true,
"mip_heuristics_only": true,
"num_cpu_threads": 100,
"crossover": true,
"log_to_console": false,
"strict_infeasibility": false,
"user_problem_file": "bob",
"per_constraint_residual": true,
"save_best_primal_so_far": true,
"first_primal_feasible": true,
"log_file": "bill",
"solution_file": "barry",
"solver_mode": 3,
"heuristics_only": false
}
}
14 changes: 11 additions & 3 deletions docs/cuopt/source/lp-features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,17 @@ Crossover
Crossover allows you to obtain a high-quality basic solution from the results of a PDLP solve. More details can be found :ref:`here <crossover>`.


Logging Callback
----------------
With logging callback, users can fetch server-side logs for additional debugs and to get details on solver process details. :ref:`Examples <generic-example-with-normal-and-batch-mode>` are shared on the self-hosted page.
Logging
-------

The CUOPT_LOG_FILE parameter can be set to write detailed solver logs for LP problems. This parameter is available in all APIs that allow setting solver parameters except the cuOpt service. For the service, see the logging callback below.

Logging Callback in the Service
-------------------------------

In the cuOpt service API, the ``log_file`` value in ``solver_configs`` is ignored.

If however you set the ``solver_logs`` flag on the ``/cuopt/request`` REST API call, users can fetch the log file content from the webserver at ``/cuopt/logs/{id}``. Using the logging callback feature through the cuOpt client is shown in :ref:`Examples <generic-example-with-normal-and-batch-mode>` on the self-hosted page.


Infeasibility Detection
Expand Down
14 changes: 7 additions & 7 deletions docs/cuopt/source/lp-milp-settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,19 @@ Log File
^^^^^^^^
``CUOPT_LOG_FILE`` controls the name of a log file where cuOpt should write information about the solve.

Note: the default value is ``""`` and no log file is written.
Note: the default value is ``""`` and no log file is written. This setting is ignored by the cuOpt service, use the log callback feature instead.

Solution File
^^^^^^^^^^^^^
``CUOPT_SOL_FILE`` controls the name of a file where cuOpt should write the solution.
``CUOPT_SOLUTION_FILE`` controls the name of a file where cuOpt should write the solution.

Note: the default value is ``""`` and no solution file is written.
Note: the default value is ``""`` and no solution file is written. This setting is ignored by the cuOpt service.

User Problem File
^^^^^^^^^^^^^^^^^
``CUOPT_USER_PROBLEM_FILE`` controls the name of a file where cuOpt should write the user problem.

Note: the default value is ``""`` and no user problem file is written.
Note: the default value is ``""`` and no user problem file is written. This setting is ignored by the cuOpt service.

Num CPU Threads
^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -257,7 +257,7 @@ We now describe parameter settings for the MILP solvers
Heuristics only
^^^^^^^^^^^^^^^

``CUOPT_HEURISTICS_ONLY`` controls if only the GPU heuristics should be run. When set to true, only the primal
``CUOPT_MIP_HEURISTICS_ONLY`` controls if only the GPU heuristics should be run for the MIP problem. When set to true, only the primal
bound is improved via the GPU. When set to false, both the GPU and CPU are used and
the dual bound is improved on the CPU.

Expand All @@ -275,14 +275,14 @@ Note: the defaulte value is true.
Absolute Tolerance
^^^^^^^^^^^^^^^^^^

``CUOPT_ABSOLUTE_TOLERANCE`` controls the MIP absolute tolerance.
``CUOPT_MIP_ABSOLUTE_TOLERANCE`` controls the MIP absolute tolerance.

Note: the default value is ``1e-4``.

Relative Tolerance
^^^^^^^^^^^^^^^^^^

``CUOPT_RELATIVE_TOLERANCE`` controls the MIP relative tolerance.
``CUOPT_MIP_RELATIVE_TOLERANCE`` controls the MIP relative tolerance.

Note: the default value is ``1e-6``.

Expand Down
20 changes: 14 additions & 6 deletions docs/cuopt/source/milp-features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,23 @@ There are two ways to specify constraints in cuOpt MILP:

Both forms are mathematically equivalent. The choice between them is a matter of convenience depending on your problem formulation.

Incumbent Solution Callback
---------------------------
Incumbent Solution Callback in the Service
------------------------------------------

User can provide a callback to receive new integer feasible solutions that improve the objective (called incumbents) while the solver is running. An :ref:`Incumbent Example <incumbent-and-logging-callback>` is shared on the self-hosted page.
When using the service, users can provide a callback to receive new integer feasible solutions that improve the objective (called incumbents) while the solver is running. An :ref:`Incumbent Example <incumbent-and-logging-callback>` is shared on the self-hosted page.

Logging Callback
----------------
Logging
-------

The CUOPT_LOG_FILE parameter can be set to write detailed solver logs for MILP problems. This parameter is available in all APIs that allow setting solver parameters except for the cuOpt service. For the service, see the logging callback below.

Logging Callback in the Service
-------------------------------

In the cuOpt service API, the ``log_file`` value in ``solver_configs`` is ignored.

If however you set the ``solver_logs`` flag on the ``/cuopt/request`` REST API call, users can fetch the log file content from the webserver at ``/cuopt/logs/{id}``. Using the logging callback feature through the cuOpt client is shown in :ref:`Logging Callback Example <incumbent-and-logging-callback>` on the self-hosted page.

A logging callback allows users to get additional information about how the solve is progressing. A :ref:`Logging Callback Example <incumbent-and-logging-callback>` is shared on the self-hosted page.

Time Limit
--------------
Expand Down
72 changes: 68 additions & 4 deletions docs/cuopt/source/transition.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
========================================
=======================================
Transition Guide for Change in Features
========================================
=======================================

In addition to the quality improvements, some new features were added, and some features were deprecated to improve user experience. For any questions, please reach out to the cuOpt team through github issues.

Expand All @@ -10,8 +10,72 @@ Parameter/option statuses are listed below, they express how each of these optio

**Update** - A change in definition of feature.

**Deprecated** - These are “no operation” options, they will be accepted by the server, but they will not be used anywhere. And the solver will also return a warning about them being deprecated.
**Deprecated** - These options will be accepted but will be removed in the future. In the case of the cuOpt service, the server will also return a warning noting that a feature is deprecated.

**Limited** - These options are limited with respect to the number of dimensions that can be provided.

**Removed** - These features were deprecated in previous release and completely removed in this one.
**Removed** - These features were deprecated in a previous release and completely removed in this one.

For all solver_configs fields, see the LP/MILP settings guide :doc:`lp-milp-settings` or the service openapi spec :doc:`open-api`.

Changes to solver_configs.tolerances
------------------------------------

The following fields are **Deprecated** in ``solver_configs.tolerances`` for the service:

- absolute_primal
- absolute_dual
- absolute_gap
- relative_primal
- relative_dual
- relative_gap
- primal_infeasible
- dual_infeasible
- integrality_tolerance
- absolute_mip_gap
- relative_mip_gap

The following fields are **New** in ``solver_configs.tolerances`` for the service and replace the deprecated fields above:

- absolute_primal_tolerance
- absolute_dual_tolerance
- absolute_gap_tolerance
- relative_primal_tolerance
- relative_dual_tolerance
- relative_gap_tolerance
- primal_infeasible_tolerance
- dual_infeasible_tolerance
- mip_integrality_tolerance
- mip_absolute_gap
- mip_relative_gap

The following fields are **New** in ``solver_configs.tolerances`` for the service but were available in the C API in 25.05

- mip_absolute_tolerance
- mip_relative_tolerance

Changes to solver_configs
-------------------------

The following fields are **Deprecated** in ``solver_configs`` for the service:

- solver_mode
- heuristics_only

The following fields are **New** in ``solver_configs`` for the service and replace the deprecated fields above:

- pdlp_solver_mode
- mip_heuristics_only

The following are **New** in ``solver_configs`` for the service but were available in the C API in 25.05

- strict_infeasibility
- user_problem_file
- per_constraint_residual
- save_best_primal_so_far
- first_primal_feasible
- log_file
- solution_file



9 changes: 3 additions & 6 deletions python/cuopt/cuopt/linear_programming/solver/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


@catch_cuopt_exception
def Solve(data_model, solver_settings=None, log_file=""):
def Solve(data_model, solver_settings=None):
"""
Solve the Linear Program passed as input and returns the solution.

Expand Down Expand Up @@ -92,13 +92,12 @@ def is_mip(var_types):
return solver_wrapper.Solve(
data_model,
solver_settings,
log_file,
mip=is_mip(data_model.get_variable_types()),
)


@catch_cuopt_exception
def BatchSolve(data_model_list, solver_settings=None, log_file=""):
def BatchSolve(data_model_list, solver_settings=None):
"""
Solve the list of Linear Programs passed as input and returns the solutions
and total solve time.
Expand Down Expand Up @@ -174,6 +173,4 @@ def BatchSolve(data_model_list, solver_settings=None, log_file=""):
if solver_settings is None:
solver_settings = SolverSettings()

return solver_wrapper.BatchSolve(
data_model_list, solver_settings, log_file
)
return solver_wrapper.BatchSolve(data_model_list, solver_settings)
17 changes: 4 additions & 13 deletions python/cuopt/cuopt/linear_programming/solver/solver_wrapper.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ from numba import cuda
import cudf
from cudf.core.buffer import as_buffer

from cuopt.linear_programming.solver.solver_parameters import CUOPT_LOG_FILE
from cuopt.linear_programming.solver_settings.solver_settings import (
PDLPSolverMode,
SolverSettings,
Expand Down Expand Up @@ -279,7 +278,6 @@ cdef set_data_model_view(DataModel data_model_obj):
cdef set_solver_setting(
unique_ptr[solver_settings_t[int, double]]& unique_solver_settings,
settings,
log_file,
DataModel data_model_obj=None,
mip=False):
cdef solver_settings_t[int, double]* c_solver_settings = (
Expand Down Expand Up @@ -425,13 +423,6 @@ cdef set_solver_setting(
settings.get_pdlp_warm_start_data().iterations_since_last_restart # noqa
)

# Common to LP and MIP

c_solver_settings.set_parameter_from_string(
CUOPT_LOG_FILE.encode('utf-8'),
log_file.encode('utf-8')
)

cdef create_solution(unique_ptr[solver_ret_t] sol_ret_ptr,
DataModel data_model_obj,
is_batch=False):
Expand Down Expand Up @@ -670,7 +661,7 @@ cdef create_solution(unique_ptr[solver_ret_t] sol_ret_ptr,
)


def Solve(py_data_model_obj, settings, str log_file, mip=False):
def Solve(py_data_model_obj, settings, mip=False):

cdef DataModel data_model_obj = <DataModel>py_data_model_obj
cdef unique_ptr[solver_settings_t[int, double]] unique_solver_settings
Expand All @@ -682,7 +673,7 @@ def Solve(py_data_model_obj, settings, str log_file, mip=False):
)

set_solver_setting(
unique_solver_settings, settings, log_file, data_model_obj, mip
unique_solver_settings, settings, data_model_obj, mip
)
set_data_model_view(data_model_obj)

Expand All @@ -697,13 +688,13 @@ cdef insert_vector(DataModel data_model_obj,
data_model_views.push_back(data_model_obj.c_data_model_view.get())


def BatchSolve(py_data_model_list, settings, str log_file):
def BatchSolve(py_data_model_list, settings):
cdef unique_ptr[solver_settings_t[int, double]] unique_solver_settings
unique_solver_settings.reset(new solver_settings_t[int, double]())

if settings.get_pdlp_warm_start_data() is not None: # noqa
raise Exception("Cannot use warmstart data with Batch Solve")
set_solver_setting(unique_solver_settings, settings, log_file)
set_solver_setting(unique_solver_settings, settings)

cdef vector[data_model_view_t[int, double] *] data_model_views

Expand Down
Loading