Skip to content
Merged
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
1 change: 1 addition & 0 deletions cpp/include/cuopt/linear_programming/solver_settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class solver_settings_t {
const std::vector<parameter_info_t<i_t>>& get_int_parameters() const;
const std::vector<parameter_info_t<bool>>& get_bool_parameters() const;
const std::vector<parameter_info_t<std::string>>& get_string_parameters() const;
const std::vector<std::string> get_parameter_names() const;

private:
pdlp_solver_settings_t<i_t, f_t> pdlp_settings;
Expand Down
19 changes: 19 additions & 0 deletions cpp/src/math_optimization/solver_settings.cu
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,25 @@ solver_settings_t<i_t, f_t>::get_string_parameters() const
return string_parameters;
}

template <typename i_t, typename f_t>
const std::vector<std::string> solver_settings_t<i_t, f_t>::get_parameter_names() const
{
std::vector<std::string> parameter_names;
for (auto& param : int_parameters) {
parameter_names.push_back(param.param_name);
}
for (auto& param : float_parameters) {
parameter_names.push_back(param.param_name);
}
for (auto& param : bool_parameters) {
parameter_names.push_back(param.param_name);
}
for (auto& param : string_parameters) {
parameter_names.push_back(param.param_name);
}
return parameter_names;
}

#if MIP_INSTANTIATE_FLOAT
template class solver_settings_t<int, float>;
template void solver_settings_t<int, float>::set_parameter(const std::string& name, int value);
Expand Down
2 changes: 2 additions & 0 deletions python/cuopt/cuopt/linear_programming/solver/solver.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ cdef extern from "cuopt/linear_programming/solver_settings.hpp" namespace "cuopt

string get_parameter_as_string(const string& name) except +

vector[string] get_parameter_names() except +

# LP settings
void set_initial_pdlp_primal_solution(
const f_t* initial_primal_solution,
Expand Down
104 changes: 19 additions & 85 deletions python/cuopt/cuopt/linear_programming/solver/solver_parameters.pyx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # noqa
# SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # noqa
# SPDX-License-Identifier: Apache-2.0


Expand All @@ -9,10 +9,10 @@

from libcpp.memory cimport unique_ptr
from libcpp.string cimport string
from libcpp.vector cimport vector

from cuopt.linear_programming.solver.solver cimport solver_settings_t


def get_solver_setting(name):
cdef unique_ptr[solver_settings_t[int, double]] unique_solver_settings

Expand All @@ -25,87 +25,21 @@ def get_solver_setting(name):
name.encode('utf-8')
).decode('utf-8')

# Get the C #defines from the constants.h file
cdef extern from "cuopt/linear_programming/constants.h": # noqa
cdef const char* c_CUOPT_ABSOLUTE_DUAL_TOLERANCE "CUOPT_ABSOLUTE_DUAL_TOLERANCE" # noqa
cdef const char* c_CUOPT_RELATIVE_DUAL_TOLERANCE "CUOPT_RELATIVE_DUAL_TOLERANCE" # noqa
cdef const char* c_CUOPT_ABSOLUTE_PRIMAL_TOLERANCE "CUOPT_ABSOLUTE_PRIMAL_TOLERANCE" # noqa
cdef const char* c_CUOPT_RELATIVE_PRIMAL_TOLERANCE "CUOPT_RELATIVE_PRIMAL_TOLERANCE" # noqa
cdef const char* c_CUOPT_ABSOLUTE_GAP_TOLERANCE "CUOPT_ABSOLUTE_GAP_TOLERANCE" # noqa
cdef const char* c_CUOPT_RELATIVE_GAP_TOLERANCE "CUOPT_RELATIVE_GAP_TOLERANCE" # noqa
cdef const char* c_CUOPT_INFEASIBILITY_DETECTION "CUOPT_INFEASIBILITY_DETECTION" # noqa
cdef const char* c_CUOPT_STRICT_INFEASIBILITY "CUOPT_STRICT_INFEASIBILITY" # noqa
cdef const char* c_CUOPT_PRIMAL_INFEASIBLE_TOLERANCE "CUOPT_PRIMAL_INFEASIBLE_TOLERANCE" # noqa
cdef const char* c_CUOPT_DUAL_INFEASIBLE_TOLERANCE "CUOPT_DUAL_INFEASIBLE_TOLERANCE" # noqa
cdef const char* c_CUOPT_ITERATION_LIMIT "CUOPT_ITERATION_LIMIT" # noqa
cdef const char* c_CUOPT_TIME_LIMIT "CUOPT_TIME_LIMIT" # noqa
cdef const char* c_CUOPT_PDLP_SOLVER_MODE "CUOPT_PDLP_SOLVER_MODE" # noqa
cdef const char* c_CUOPT_METHOD "CUOPT_METHOD" # noqa
cdef const char* c_CUOPT_PER_CONSTRAINT_RESIDUAL "CUOPT_PER_CONSTRAINT_RESIDUAL" # noqa
cdef const char* c_CUOPT_SAVE_BEST_PRIMAL_SO_FAR "CUOPT_SAVE_BEST_PRIMAL_SO_FAR" # noqa
cdef const char* c_CUOPT_FIRST_PRIMAL_FEASIBLE "CUOPT_FIRST_PRIMAL_FEASIBLE" # noqa
cdef const char* c_CUOPT_LOG_FILE "CUOPT_LOG_FILE" # noqa
cdef const char* c_CUOPT_LOG_TO_CONSOLE "CUOPT_LOG_TO_CONSOLE" # noqa
cdef const char* c_CUOPT_CROSSOVER "CUOPT_CROSSOVER" # noqa
cdef const char* c_CUOPT_PRESOLVE "CUOPT_PRESOLVE" # noqa
cdef const char* c_CUOPT_DUAL_POSTSOLVE "CUOPT_DUAL_POSTSOLVE" # noqa
cdef const char* c_CUOPT_NUM_GPUS "CUOPT_NUM_GPUS" # noqa
cdef const char* c_CUOPT_MIP_ABSOLUTE_TOLERANCE "CUOPT_MIP_ABSOLUTE_TOLERANCE" # noqa
cdef const char* c_CUOPT_MIP_RELATIVE_TOLERANCE "CUOPT_MIP_RELATIVE_TOLERANCE" # noqa
cdef const char* c_CUOPT_MIP_INTEGRALITY_TOLERANCE "CUOPT_MIP_INTEGRALITY_TOLERANCE" # noqa
cdef const char* c_CUOPT_MIP_ABSOLUTE_GAP "CUOPT_MIP_ABSOLUTE_GAP" # noqa
cdef const char* c_CUOPT_MIP_RELATIVE_GAP "CUOPT_MIP_RELATIVE_GAP" # noqa
cdef const char* c_CUOPT_MIP_HEURISTICS_ONLY "CUOPT_MIP_HEURISTICS_ONLY" # noqa
cdef const char* c_CUOPT_MIP_SCALING "CUOPT_MIP_SCALING" # noqa
cdef const char* c_CUOPT_SOLUTION_FILE "CUOPT_SOLUTION_FILE" # noqa
cdef const char* c_CUOPT_NUM_CPU_THREADS "CUOPT_NUM_CPU_THREADS" # noqa
cdef const char* c_CUOPT_USER_PROBLEM_FILE "CUOPT_USER_PROBLEM_FILE" # noqa
cdef const char* c_CUOPT_AUGMENTED "CUOPT_AUGMENTED"
cdef const char* c_CUOPT_FOLDING "CUOPT_FOLDING"
cdef const char* c_CUOPT_DUALIZE "CUOPT_DUALIZE"
cdef const char* c_CUOPT_ELIMINATE_DENSE_COLUMNS "CUOPT_ELIMINATE_DENSE_COLUMNS" # noqa
cdef const char* c_CUOPT_CUDSS_DETERMINISTIC "CUOPT_CUDSS_DETERMINISTIC" # noqa
cdef const char* c_CUOPT_ORDERING "CUOPT_ORDERING" # noqa
cdef const char* c_CUOPT_BARRIER_DUAL_INITIAL_POINT "CUOPT_BARRIER_DUAL_INITIAL_POINT" # noqa

# Create Python string constants from C string literals
CUOPT_ABSOLUTE_DUAL_TOLERANCE = c_CUOPT_ABSOLUTE_DUAL_TOLERANCE.decode('utf-8') # noqa
CUOPT_RELATIVE_DUAL_TOLERANCE = c_CUOPT_RELATIVE_DUAL_TOLERANCE.decode('utf-8') # noqa
CUOPT_ABSOLUTE_PRIMAL_TOLERANCE = c_CUOPT_ABSOLUTE_PRIMAL_TOLERANCE.decode('utf-8') # noqa
CUOPT_RELATIVE_PRIMAL_TOLERANCE = c_CUOPT_RELATIVE_PRIMAL_TOLERANCE.decode('utf-8') # noqa
CUOPT_ABSOLUTE_GAP_TOLERANCE = c_CUOPT_ABSOLUTE_GAP_TOLERANCE.decode('utf-8') # noqa
CUOPT_RELATIVE_GAP_TOLERANCE = c_CUOPT_RELATIVE_GAP_TOLERANCE.decode('utf-8') # noqa
CUOPT_INFEASIBILITY_DETECTION = c_CUOPT_INFEASIBILITY_DETECTION.decode('utf-8') # noqa
CUOPT_STRICT_INFEASIBILITY = c_CUOPT_STRICT_INFEASIBILITY.decode('utf-8') # noqa
CUOPT_PRIMAL_INFEASIBLE_TOLERANCE = c_CUOPT_PRIMAL_INFEASIBLE_TOLERANCE.decode('utf-8') # noqa
CUOPT_DUAL_INFEASIBLE_TOLERANCE = c_CUOPT_DUAL_INFEASIBLE_TOLERANCE.decode('utf-8') # noqa
CUOPT_ITERATION_LIMIT = c_CUOPT_ITERATION_LIMIT.decode('utf-8') # noqa
CUOPT_TIME_LIMIT = c_CUOPT_TIME_LIMIT.decode('utf-8') # noqa
CUOPT_PDLP_SOLVER_MODE = c_CUOPT_PDLP_SOLVER_MODE.decode('utf-8') # noqa
CUOPT_METHOD = c_CUOPT_METHOD.decode('utf-8') # noqa
CUOPT_PER_CONSTRAINT_RESIDUAL = c_CUOPT_PER_CONSTRAINT_RESIDUAL.decode('utf-8') # noqa
CUOPT_SAVE_BEST_PRIMAL_SO_FAR = c_CUOPT_SAVE_BEST_PRIMAL_SO_FAR.decode('utf-8') # noqa
CUOPT_FIRST_PRIMAL_FEASIBLE = c_CUOPT_FIRST_PRIMAL_FEASIBLE.decode('utf-8') # noqa
CUOPT_LOG_FILE = c_CUOPT_LOG_FILE.decode('utf-8') # noqa
CUOPT_LOG_TO_CONSOLE = c_CUOPT_LOG_TO_CONSOLE.decode('utf-8') # noqa
CUOPT_CROSSOVER = c_CUOPT_CROSSOVER.decode('utf-8') # noqa
CUOPT_PRESOLVE = c_CUOPT_PRESOLVE.decode('utf-8') # noqa
CUOPT_DUAL_POSTSOLVE = c_CUOPT_DUAL_POSTSOLVE.decode('utf-8') # noqa
CUOPT_NUM_GPUS = c_CUOPT_NUM_GPUS.decode('utf-8') # noqa
CUOPT_MIP_ABSOLUTE_TOLERANCE = c_CUOPT_MIP_ABSOLUTE_TOLERANCE.decode('utf-8') # noqa
CUOPT_MIP_RELATIVE_TOLERANCE = c_CUOPT_MIP_RELATIVE_TOLERANCE.decode('utf-8') # noqa
CUOPT_MIP_INTEGRALITY_TOLERANCE = c_CUOPT_MIP_INTEGRALITY_TOLERANCE.decode('utf-8') # noqa
CUOPT_MIP_ABSOLUTE_GAP = c_CUOPT_MIP_ABSOLUTE_GAP.decode('utf-8') # noqa
CUOPT_MIP_RELATIVE_GAP = c_CUOPT_MIP_RELATIVE_GAP.decode('utf-8') # noqa
CUOPT_MIP_HEURISTICS_ONLY = c_CUOPT_MIP_HEURISTICS_ONLY.decode('utf-8') # noqa
CUOPT_MIP_SCALING = c_CUOPT_MIP_SCALING.decode('utf-8') # noqa
CUOPT_SOLUTION_FILE = c_CUOPT_SOLUTION_FILE.decode('utf-8') # noqa
CUOPT_NUM_CPU_THREADS = c_CUOPT_NUM_CPU_THREADS.decode('utf-8') # noqa
CUOPT_USER_PROBLEM_FILE = c_CUOPT_USER_PROBLEM_FILE.decode('utf-8') # noqa
CUOPT_AUGMENTED = c_CUOPT_AUGMENTED.decode('utf-8') # noqa
CUOPT_FOLDING = c_CUOPT_FOLDING.decode('utf-8') # noqa
CUOPT_DUALIZE = c_CUOPT_DUALIZE.decode('utf-8') # noqa
CUOPT_ELIMINATE_DENSE_COLUMNS = c_CUOPT_ELIMINATE_DENSE_COLUMNS.decode('utf-8') # noqa
CUOPT_CUDSS_DETERMINISTIC = c_CUOPT_CUDSS_DETERMINISTIC.decode('utf-8') # noqa
CUOPT_ORDERING = c_CUOPT_ORDERING.decode('utf-8') # noqa
CUOPT_BARRIER_DUAL_INITIAL_POINT = c_CUOPT_BARRIER_DUAL_INITIAL_POINT.decode('utf-8') # noqa
cpdef get_solver_parameter_names():
cdef unique_ptr[solver_settings_t[int, double]] unique_solver_settings
unique_solver_settings.reset(new solver_settings_t[int, double]())
cdef solver_settings_t[int, double]* c_solver_settings = (
unique_solver_settings.get()
)
cdef vector[string] parameter_names = c_solver_settings.get_parameter_names()

cdef list py_parameter_names = []
cdef size_t i
for i in range(parameter_names.size()):
# std::string -> Python str
py_parameter_names.append(parameter_names[i].decode("utf-8"))
return py_parameter_names

solver_params = get_solver_parameter_names()
for param in solver_params: globals()["CUOPT_"+param.upper()] = param
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,7 @@
from enum import IntEnum, auto

from cuopt.linear_programming.solver.solver_parameters import (
CUOPT_ABSOLUTE_DUAL_TOLERANCE,
CUOPT_ABSOLUTE_GAP_TOLERANCE,
CUOPT_ABSOLUTE_PRIMAL_TOLERANCE,
CUOPT_AUGMENTED,
CUOPT_BARRIER_DUAL_INITIAL_POINT,
CUOPT_CROSSOVER,
CUOPT_CUDSS_DETERMINISTIC,
CUOPT_DUAL_INFEASIBLE_TOLERANCE,
CUOPT_DUAL_POSTSOLVE,
CUOPT_DUALIZE,
CUOPT_ELIMINATE_DENSE_COLUMNS,
CUOPT_FIRST_PRIMAL_FEASIBLE,
CUOPT_FOLDING,
CUOPT_INFEASIBILITY_DETECTION,
CUOPT_ITERATION_LIMIT,
CUOPT_LOG_FILE,
CUOPT_LOG_TO_CONSOLE,
CUOPT_METHOD,
CUOPT_MIP_ABSOLUTE_GAP,
CUOPT_MIP_ABSOLUTE_TOLERANCE,
CUOPT_MIP_HEURISTICS_ONLY,
CUOPT_MIP_INTEGRALITY_TOLERANCE,
CUOPT_MIP_RELATIVE_GAP,
CUOPT_MIP_RELATIVE_TOLERANCE,
CUOPT_MIP_SCALING,
CUOPT_NUM_CPU_THREADS,
CUOPT_NUM_GPUS,
CUOPT_ORDERING,
CUOPT_PDLP_SOLVER_MODE,
CUOPT_PER_CONSTRAINT_RESIDUAL,
CUOPT_PRESOLVE,
CUOPT_PRIMAL_INFEASIBLE_TOLERANCE,
CUOPT_RELATIVE_DUAL_TOLERANCE,
CUOPT_RELATIVE_GAP_TOLERANCE,
CUOPT_RELATIVE_PRIMAL_TOLERANCE,
CUOPT_SAVE_BEST_PRIMAL_SO_FAR,
CUOPT_SOLUTION_FILE,
CUOPT_STRICT_INFEASIBILITY,
CUOPT_TIME_LIMIT,
CUOPT_USER_PROBLEM_FILE,
solver_params,
get_solver_setting,
)

Expand Down Expand Up @@ -156,6 +117,8 @@ def get_parameter(self, name):
For a list of availabe parameters, their descriptions, default values,
and acceptable ranges, see the cuOpt documentation `parameter.rst`.
"""
if name not in solver_params:
raise ValueError("Invalid parameter. Please check documentation")
if name in self.settings_dict:
if isinstance(self.settings_dict[name], str):
return self.to_base_type(self.settings_dict[name])
Expand All @@ -179,7 +142,8 @@ def set_parameter(self, name, value):
For a list of availabe parameters, their descriptions, default values,
and acceptable ranges, see the cuOpt documentation `parameter.rst`.
"""

if name not in solver_params:
raise ValueError("Invalid parameter. Please check documentation")
self.settings_dict[name] = value

def set_optimality_tolerance(self, eps_optimal):
Expand Down Expand Up @@ -211,12 +175,10 @@ def set_optimality_tolerance(self, eps_optimal):
Default value is 1e-4.
To set each absolute and relative tolerance, use the provided setters.
"""
self.settings_dict["absolute_dual_tolerance"] = eps_optimal
self.settings_dict["relative_dual_tolerance"] = eps_optimal
self.settings_dict["absolute_primal_tolerance"] = eps_optimal
self.settings_dict["relative_primal_tolerance"] = eps_optimal
self.settings_dict["absolute_gap_tolerance"] = eps_optimal
self.settings_dict["relative_gap_tolerance"] = eps_optimal
for param in solver_params:
if param.endswith("tolerance"):
if not param.startswith("mip") and "infeasible" not in param:
self.settings_dict[param] = eps_optimal

def set_pdlp_warm_start_data(self, pdlp_warm_start_data):
"""
Expand Down Expand Up @@ -339,93 +301,15 @@ def get_pdlp_warm_start_data(self):
return self.pdlp_warm_start_data

def toDict(self):
time_limit = self.get_parameter(CUOPT_TIME_LIMIT)
if time_limit == float("inf"):
time_limit = None

solver_config = {
"tolerances": {
"absolute_dual_tolerance": self.get_parameter(
CUOPT_ABSOLUTE_DUAL_TOLERANCE
),
"relative_dual_tolerance": self.get_parameter(
CUOPT_RELATIVE_DUAL_TOLERANCE
),
"absolute_primal_tolerance": self.get_parameter(
CUOPT_ABSOLUTE_PRIMAL_TOLERANCE
),
"relative_primal_tolerance": self.get_parameter(
CUOPT_RELATIVE_PRIMAL_TOLERANCE
),
"absolute_gap_tolerance": self.get_parameter(
CUOPT_ABSOLUTE_GAP_TOLERANCE
),
"relative_gap_tolerance": self.get_parameter(
CUOPT_RELATIVE_GAP_TOLERANCE
),
"primal_infeasible_tolerance": self.get_parameter(
CUOPT_PRIMAL_INFEASIBLE_TOLERANCE
),
"dual_infeasible_tolerance": self.get_parameter(
CUOPT_DUAL_INFEASIBLE_TOLERANCE
),
"mip_integrality_tolerance": self.get_parameter(
CUOPT_MIP_INTEGRALITY_TOLERANCE
),
"mip_absolute_gap": self.get_parameter(CUOPT_MIP_ABSOLUTE_GAP),
"mip_relative_gap": self.get_parameter(CUOPT_MIP_RELATIVE_GAP),
"mip_absolute_tolerance": self.get_parameter(
CUOPT_MIP_ABSOLUTE_TOLERANCE
),
"mip_relative_tolerance": self.get_parameter(
CUOPT_MIP_RELATIVE_TOLERANCE
),
},
"infeasibility_detection": self.get_parameter(
CUOPT_INFEASIBILITY_DETECTION
),
"time_limit": time_limit,
"iteration_limit": self.get_parameter(CUOPT_ITERATION_LIMIT),
"pdlp_solver_mode": self.get_parameter(CUOPT_PDLP_SOLVER_MODE),
"method": self.get_parameter(CUOPT_METHOD),
"presolve": self.get_parameter(CUOPT_PRESOLVE),
"dual_postsolve": self.get_parameter(CUOPT_DUAL_POSTSOLVE),
"mip_scaling": self.get_parameter(CUOPT_MIP_SCALING),
"mip_heuristics_only": self.get_parameter(
CUOPT_MIP_HEURISTICS_ONLY
),
"num_cpu_threads": self.get_parameter(CUOPT_NUM_CPU_THREADS),
"num_gpus": self.get_parameter(CUOPT_NUM_GPUS),
"augmented": self.get_parameter(CUOPT_AUGMENTED),
"folding": self.get_parameter(CUOPT_FOLDING),
"dualize": self.get_parameter(CUOPT_DUALIZE),
"ordering": self.get_parameter(CUOPT_ORDERING),
"barrier_dual_initial_point": self.get_parameter(
CUOPT_BARRIER_DUAL_INITIAL_POINT
),
"eliminate_dense_columns": self.get_parameter(
CUOPT_ELIMINATE_DENSE_COLUMNS
),
"cudss_deterministic": self.get_parameter(
CUOPT_CUDSS_DETERMINISTIC
),
"crossover": self.get_parameter(CUOPT_CROSSOVER),
"log_to_console": self.get_parameter(CUOPT_LOG_TO_CONSOLE),
"first_primal_feasible": self.get_parameter(
CUOPT_FIRST_PRIMAL_FEASIBLE
),
"log_file": self.get_parameter(CUOPT_LOG_FILE),
"per_constraint_residual": self.get_parameter(
CUOPT_PER_CONSTRAINT_RESIDUAL
),
"save_best_primal_so_far": self.get_parameter(
CUOPT_SAVE_BEST_PRIMAL_SO_FAR
),
"solution_file": self.get_parameter(CUOPT_SOLUTION_FILE),
"strict_infeasibility": self.get_parameter(
CUOPT_STRICT_INFEASIBILITY
),
"user_problem_file": self.get_parameter(CUOPT_USER_PROBLEM_FILE),
}
solver_config = {}
solver_config["tolerances"] = {}
for param in solver_params:
if param.endswith("tolerance"):
solver_config["tolerances"][param] = self.get_parameter(param)
else:
param_value = self.get_parameter(param)
if param_value == float("inf"):
param_value = None
solver_config[param] = param_value

Comment on lines 303 to 314
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

toDict doesn't handle negative infinity.

Line 290 checks param_value == float("inf") and converts to None, but float("-inf") would pass through as-is, which may not serialize correctly (e.g., JSON doesn't support -Infinity). Consider checking with math.isinf(param_value) instead.

Suggested fix
+import math
+
 ...
-                if param_value == float("inf"):
+                if isinstance(param_value, float) and math.isinf(param_value):
                     param_value = None
📝 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.

Suggested change
def toDict(self):
time_limit = self.get_parameter(CUOPT_TIME_LIMIT)
if time_limit == float("inf"):
time_limit = None
solver_config = {
"tolerances": {
"absolute_dual_tolerance": self.get_parameter(
CUOPT_ABSOLUTE_DUAL_TOLERANCE
),
"relative_dual_tolerance": self.get_parameter(
CUOPT_RELATIVE_DUAL_TOLERANCE
),
"absolute_primal_tolerance": self.get_parameter(
CUOPT_ABSOLUTE_PRIMAL_TOLERANCE
),
"relative_primal_tolerance": self.get_parameter(
CUOPT_RELATIVE_PRIMAL_TOLERANCE
),
"absolute_gap_tolerance": self.get_parameter(
CUOPT_ABSOLUTE_GAP_TOLERANCE
),
"relative_gap_tolerance": self.get_parameter(
CUOPT_RELATIVE_GAP_TOLERANCE
),
"primal_infeasible_tolerance": self.get_parameter(
CUOPT_PRIMAL_INFEASIBLE_TOLERANCE
),
"dual_infeasible_tolerance": self.get_parameter(
CUOPT_DUAL_INFEASIBLE_TOLERANCE
),
"mip_integrality_tolerance": self.get_parameter(
CUOPT_MIP_INTEGRALITY_TOLERANCE
),
"mip_absolute_gap": self.get_parameter(CUOPT_MIP_ABSOLUTE_GAP),
"mip_relative_gap": self.get_parameter(CUOPT_MIP_RELATIVE_GAP),
"mip_absolute_tolerance": self.get_parameter(
CUOPT_MIP_ABSOLUTE_TOLERANCE
),
"mip_relative_tolerance": self.get_parameter(
CUOPT_MIP_RELATIVE_TOLERANCE
),
},
"infeasibility_detection": self.get_parameter(
CUOPT_INFEASIBILITY_DETECTION
),
"time_limit": time_limit,
"iteration_limit": self.get_parameter(CUOPT_ITERATION_LIMIT),
"pdlp_solver_mode": self.get_parameter(CUOPT_PDLP_SOLVER_MODE),
"method": self.get_parameter(CUOPT_METHOD),
"presolve": self.get_parameter(CUOPT_PRESOLVE),
"dual_postsolve": self.get_parameter(CUOPT_DUAL_POSTSOLVE),
"mip_scaling": self.get_parameter(CUOPT_MIP_SCALING),
"mip_heuristics_only": self.get_parameter(
CUOPT_MIP_HEURISTICS_ONLY
),
"num_cpu_threads": self.get_parameter(CUOPT_NUM_CPU_THREADS),
"num_gpus": self.get_parameter(CUOPT_NUM_GPUS),
"augmented": self.get_parameter(CUOPT_AUGMENTED),
"folding": self.get_parameter(CUOPT_FOLDING),
"dualize": self.get_parameter(CUOPT_DUALIZE),
"ordering": self.get_parameter(CUOPT_ORDERING),
"barrier_dual_initial_point": self.get_parameter(
CUOPT_BARRIER_DUAL_INITIAL_POINT
),
"eliminate_dense_columns": self.get_parameter(
CUOPT_ELIMINATE_DENSE_COLUMNS
),
"cudss_deterministic": self.get_parameter(
CUOPT_CUDSS_DETERMINISTIC
),
"crossover": self.get_parameter(CUOPT_CROSSOVER),
"log_to_console": self.get_parameter(CUOPT_LOG_TO_CONSOLE),
"first_primal_feasible": self.get_parameter(
CUOPT_FIRST_PRIMAL_FEASIBLE
),
"log_file": self.get_parameter(CUOPT_LOG_FILE),
"per_constraint_residual": self.get_parameter(
CUOPT_PER_CONSTRAINT_RESIDUAL
),
"save_best_primal_so_far": self.get_parameter(
CUOPT_SAVE_BEST_PRIMAL_SO_FAR
),
"solution_file": self.get_parameter(CUOPT_SOLUTION_FILE),
"strict_infeasibility": self.get_parameter(
CUOPT_STRICT_INFEASIBILITY
),
"user_problem_file": self.get_parameter(CUOPT_USER_PROBLEM_FILE),
}
solver_config = {}
solver_config["tolerances"] = {}
for param in solver_params:
if param.endswith("tolerance"):
solver_config["tolerances"][param] = self.get_parameter(param)
else:
param_value = self.get_parameter(param)
if param_value == float("inf"):
param_value = None
solver_config[param] = param_value
def toDict(self):
solver_config = {}
solver_config["tolerances"] = {}
for param in solver_params:
if param.endswith("tolerance"):
solver_config["tolerances"][param] = self.get_parameter(param)
else:
param_value = self.get_parameter(param)
if isinstance(param_value, float) and math.isinf(param_value):
param_value = None
solver_config[param] = param_value
🤖 Prompt for AI Agents
In `@python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.py`
around lines 282 - 293, The toDict method currently only converts positive
infinity to None (param_value == float("inf")), leaving float("-inf") unchanged;
update to detect any infinity by using math.isinf on values returned from
get_parameter and set param_value to None for both +inf and -inf (ensure to
import math), and guard the check so non-numeric parameter values don't
raise—apply this change inside the loop over solver_params where solver_config
and param_value are handled in toDict.

return solver_config
Loading