diff --git a/.clang-format b/.clang-format index 0c05436e9..fb28c7939 100644 --- a/.clang-format +++ b/.clang-format @@ -15,7 +15,7 @@ AlignTrailingComments: true AllowAllArgumentsOnNextLine: true AllowAllConstructorInitializersOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: true +AllowShortBlocksOnASingleLine: true AllowShortCaseLabelsOnASingleLine: true AllowShortEnumsOnASingleLine: true AllowShortFunctionsOnASingleLine: All @@ -27,7 +27,7 @@ AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: false +BinPackArguments: false BinPackParameters: false BraceWrapping: AfterClass: false diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index ec90bb2ff..9e493f77b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -20,7 +20,7 @@ A clear and concise description of what you expected to happen. - Environment location: [Bare-metal, Docker, Cloud(specify cloud provider)] - Method of cuOpt install: [conda, Docker, or from source] - If method of install is [Docker], provide `docker pull` & `docker run` commands used - + **Additional context** Add any other context about the problem here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 91749dc9c..8f9ae2102 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -19,12 +19,12 @@ Note: The pull request title will be included in the CHANGELOG. ## Checklist - [ ] I am familiar with the [Contributing Guidelines](https://github.com/NVIDIA/cuopt/blob/HEAD/CONTRIBUTING.md). -- Testing +- Testing - [ ] New or existing tests cover these changes - [ ] Added tests - [ ] Created an issue to follow-up - [ ] NA - Documentation - [ ] The documentation is up to date with these changes - - [ ] Added new documentation + - [ ] Added new documentation - [ ] NA diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index dfede9601..97a2e8dad 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -75,5 +75,3 @@ jobs: -f sha=${SHA} \ -f date=${DATE} \ -f build_type=nightly - - diff --git a/.github/workflows/service_nightly.yaml b/.github/workflows/service_nightly.yaml index 5d398ecf0..94071d1bf 100644 --- a/.github/workflows/service_nightly.yaml +++ b/.github/workflows/service_nightly.yaml @@ -1,5 +1,5 @@ name: Build Managed service docker, deploy and test - + on: workflow_dispatch: inputs: @@ -33,7 +33,7 @@ permissions: jobs: managed-service-nightly-amd: - name: Managed service nightly build for AMD64 architecture + name: Managed service nightly build for AMD64 architecture env: GH_TOKEN: ${{ github.token }} RAPIDS_BUILD_TYPE: ${{ inputs.build_type }} @@ -117,7 +117,7 @@ jobs: docker push nvcr.io/0616513341838337/cuopt:25.08 managed-service-nightly-arm: - name: Managed service nightly build for ARM architecture + name: Managed service nightly build for ARM architecture env: GH_TOKEN: ${{ github.token }} RAPIDS_BUILD_TYPE: ${{ inputs.build_type }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 82ed616e4..c218b4470 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,6 +14,19 @@ # limitations under the License. repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: 'v5.0.0' + hooks: + - id: end-of-file-fixer + files: \.(mps|json|yaml|yml|txt)$ + exclude: ^datasets/.*\.(mps|json|yaml|yml|txt)$ + - id: trailing-whitespace + files: \.(mps|json|yaml|yml|txt)$ + exclude: ^datasets/.*\.(mps|json|yaml|yml|txt)$ + - id: check-builtin-literals + - id: check-executables-have-shebangs + - id: check-json + - id: check-yaml - repo: https://github.com/PyCQA/isort rev: 5.12.0 hooks: @@ -54,19 +67,6 @@ repos: docs| notebooks ) - - repo: https://github.com/rapidsai/pre-commit-hooks - rev: v0.6.0 - hooks: - - id: verify-copyright - files: | - (?x) - [.](cmake|cpp|cu|cuh|h|hpp|sh|pxd|py|pyx)$| - CMakeLists[.]txt$| - meta[.]yaml$ - exclude: | - (?x)^( - ^cpp/tests/utilities/cxxopts.hpp - ) - repo: https://github.com/pre-commit/mirrors-clang-format rev: v20.1.4 hooks: @@ -84,6 +84,20 @@ repos: hooks: - id: shellcheck args: ["--severity=warning"] + - repo: https://github.com/rapidsai/pre-commit-hooks + rev: v0.6.0 + hooks: + - id: verify-copyright + files: | + (?x) + [.](cmake|cpp|cu|cuh|h|hpp|sh|pxd|py|pyx)$| + CMakeLists[.]txt$| + recipe[.]yaml$ + exclude: | + (?x)^( + ^cpp/tests/utilities/cxxopts.hpp + ) + default_language_version: python: python3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e1cf03aa..3129e7190 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -227,7 +227,7 @@ This will add the device debug symbols for this object file in `libcuopt.so`. Y ## Adding dependencies Please refer to the [dependencies.yaml](dependencies.yaml) file for details on how to add new dependencies. -Add any new dependencies in the `dependencies.yaml` file. It takes care of conda, requirements (pip based dependencies) and pyproject. +Add any new dependencies in the `dependencies.yaml` file. It takes care of conda, requirements (pip based dependencies) and pyproject. Please don't try to add dependencies directly to environment.yaml files under `conda/environments` directory and pyproject.toml files under `python` directories. ## Code Formatting @@ -314,5 +314,5 @@ You can skip these checks with `git commit --no-verify` or with the short versio (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. ``` - + diff --git a/benchmarks/linear_programming/utils/get_datasets.py b/benchmarks/linear_programming/utils/get_datasets.py index 54eaa80bc..2879cff2b 100644 --- a/benchmarks/linear_programming/utils/get_datasets.py +++ b/benchmarks/linear_programming/utils/get_datasets.py @@ -155,11 +155,11 @@ "netlib" ], "dlr1" : [ - "http://plato.asu.edu/ftp/lptestset/dlr1.mps.bz2", + "http://plato.asu.edu/ftp/lptestset/dlr1.mps.bz2", "mps" ], "dlr2" : [ - "http://plato.asu.edu/ftp/lptestset/dlr2.mps.bz2", + "http://plato.asu.edu/ftp/lptestset/dlr2.mps.bz2", "mps" ], "energy1" : ["", "mps"], # Kept secret by Mittlemman diff --git a/conda/README.md b/conda/README.md index 8188d0a7d..585707d0a 100644 --- a/conda/README.md +++ b/conda/README.md @@ -1,4 +1,4 @@ -# Conda Recipes and Environment +# Conda Recipes and Environment This directory contains the conda recipes for the cuOpt packages which are used to build the conda packages in CI. diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index df4d9b526..2286bd6dc 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -312,7 +312,7 @@ target_compile_options(cuopt_cli ) target_include_directories(cuopt_cli - PRIVATE + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" PUBLIC "$" @@ -327,7 +327,7 @@ target_link_libraries(cuopt_cli ) set_property(TARGET cuopt_cli PROPERTY INSTALL_RPATH "$ORIGIN/../${lib_dir}") -# FIXME:: Is this the right way? +# FIXME:: Is this the right way? install(TARGETS cuopt_cli DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/cpp/README.md b/cpp/README.md index 974f22cc7..87be904e2 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -57,5 +57,5 @@ cpp/ The MPS parser is a standalone module that parses MPS files and converts them into a format that can be used by the cuOpt library. -It is located in the `libmps_parser` directory. This also contains the `CMakeLists.txt` file to build the module. +It is located in the `libmps_parser` directory. This also contains the `CMakeLists.txt` file to build the module. diff --git a/cpp/cmake/thirdparty/cccl_override.json b/cpp/cmake/thirdparty/cccl_override.json index 11b0f392a..d3f0d4e5b 100644 --- a/cpp/cmake/thirdparty/cccl_override.json +++ b/cpp/cmake/thirdparty/cccl_override.json @@ -4,4 +4,4 @@ "version" : "2.8.2" } } -} \ No newline at end of file +} diff --git a/cpp/docs/DEVELOPER_GUIDE.md b/cpp/docs/DEVELOPER_GUIDE.md index 33ebd0412..716248b24 100644 --- a/cpp/docs/DEVELOPER_GUIDE.md +++ b/cpp/docs/DEVELOPER_GUIDE.md @@ -1,6 +1,6 @@ # cuOpt C++ Developer Guide -This document serves as a guide for contributors to cuOpt C++ code. Developers should also refer +This document serves as a guide for contributors to cuOpt C++ code. Developers should also refer to these additional files for further documentation of cuOpt best practices. * [Documentation Guide](TODO) for guidelines on documenting cuOpt code. @@ -18,12 +18,12 @@ This section defines terminology used within cuOpt # Directory Structure and File Naming -External/public cuOpt APIs are grouped into an appropriately titled -header file in `cuopt/cpp/include/cuopt`. For example, `cuopt/cpp/include/cuopt/routing/data_model_view.hpp` -contains the definition of the routing data model object. Note the `.hpp` +External/public cuOpt APIs are grouped into an appropriately titled +header file in `cuopt/cpp/include/cuopt`. For example, `cuopt/cpp/include/cuopt/routing/data_model_view.hpp` +contains the definition of the routing data model object. Note the `.hpp` file extension used to indicate a C++ header file. -Header files should use the `#pragma once` include guard. +Header files should use the `#pragma once` include guard. ## File extensions @@ -41,8 +41,8 @@ algorithm APIs with a device execution policy (always `rmm::exec_policy` in cuOp ## Code and Documentation Style and Formatting -cuOpt code uses [snake_case](https://en.wikipedia.org/wiki/Snake_case) for all names except in a -few cases: unit tests and test case names may use Pascal case, aka +cuOpt code uses [snake_case](https://en.wikipedia.org/wiki/Snake_case) for all names except in a +few cases: unit tests and test case names may use Pascal case, aka [UpperCamelCase](https://en.wikipedia.org/wiki/Camel_case). We do not use [Hungarian notation](https://en.wikipedia.org/wiki/Hungarian_notation), except for the following examples: * device data variables should be prefaced by d_ if it makes the intent clearer @@ -61,9 +61,9 @@ class locations_t } ``` -C++ formatting is enforced using `clang-format`. You should configure `clang-format` on your -machine to use the `cuopt/cpp/.clang-format` configuration file, and run `clang-format` on all -changed code before committing it. The easiest way to do this is to configure your editor to +C++ formatting is enforced using `clang-format`. You should configure `clang-format` on your +machine to use the `cuopt/cpp/.clang-format` configuration file, and run `clang-format` on all +changed code before committing it. The easiest way to do this is to configure your editor to "format on save". Aspects of code style not discussed in this document and not automatically enforceable are typically @@ -71,10 +71,10 @@ caught during code review, or not enforced. ### C++ Guidelines -In general, we recommend following -[C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines). We also -recommend watching Sean Parent's [C++ Seasoning talk](https://www.youtube.com/watch?v=W2tWOdzgXHA), -and we try to follow his rules: "No raw loops. No raw pointers. No raw synchronization primitives." +In general, we recommend following +[C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines). We also +recommend watching Sean Parent's [C++ Seasoning talk](https://www.youtube.com/watch?v=W2tWOdzgXHA), +and we try to follow his rules: "No raw loops. No raw pointers. No raw synchronization primitives." * Prefer algorithms from STL and Thrust to raw loops. * Prefer cuopt and RMM to raw pointers and raw memory allocation. @@ -84,35 +84,35 @@ and we try to follow his rules: "No raw loops. No raw pointers. No raw synchroni The following guidelines apply to organizing `#include` lines. - * Group includes by library (e.g. cuOpt, RMM, Thrust, STL). `clang-format` will respect the + * Group includes by library (e.g. cuOpt, RMM, Thrust, STL). `clang-format` will respect the groupings and sort the individual includes within a group lexicographically. * Separate groups by a blank line. - * Order the groups from "nearest" to "farthest". In other words, local includes, then includes - from other RAPIDS libraries, then includes from related libraries, like ``, then - includes from dependencies installed with cuOpt, and then standard headers (for example ``, + * Order the groups from "nearest" to "farthest". In other words, local includes, then includes + from other RAPIDS libraries, then includes from related libraries, like ``, then + includes from dependencies installed with cuOpt, and then standard headers (for example ``, ``). * Use <> instead of "" unless the header is in the same directory as the source file. * Tools like `clangd` often auto-insert includes when they can, but they usually get the grouping and brackets wrong. - * Always check that includes are only necessary for the file in which they are included. - Try to avoid excessive including especially in header files. Double check this when you remove + * Always check that includes are only necessary for the file in which they are included. + Try to avoid excessive including especially in header files. Double check this when you remove code. # cuOpt Data Structures -Application data in cuOpt is contained in 3 objects for routing : data model, solver, and assignment. +Application data in cuOpt is contained in 3 objects for routing : data model, solver, and assignment. There are a variety of other data structures you will use when developing cuOpt code. ## Views and Ownership -Resource ownership is an essential concept in cuOpt. In short, an "owning" object owns a -resource (such as device memory). It acquires that resource during construction and releases the +Resource ownership is an essential concept in cuOpt. In short, an "owning" object owns a +resource (such as device memory). It acquires that resource during construction and releases the resource in destruction ([RAII](https://en.cppreference.com/w/cpp/language/raii)). A "non-owning" object does not own resources. Any class in cuOpt with the `*_view` suffix is non-owning. ## `rmm::device_memory_resource` -cuOpt allocates all device memory via RMM memory resources (MR). See the +cuOpt allocates all device memory via RMM memory resources (MR). See the [RMM documentation](https://github.com/rapidsai/rmm/blob/main/README.md) for details. ## Streams @@ -133,7 +133,7 @@ Similar to a `rmm::device_vector`, allocates a contiguous set of elements in dev key differences: - As an optimization, elements are uninitialized and no synchronization occurs at construction. This limits the types `T` to trivially copyable types. -- All operations are stream ordered (i.e., they accept a `cuda_stream_view` specifying the stream +- All operations are stream ordered (i.e., they accept a `cuda_stream_view` specifying the stream on which the operation is performed). ## Namespaces @@ -148,12 +148,12 @@ namespace cuopt{ ### Internal -Many functions are not meant for public use, so place them in either the `detail` or an *anonymous* +Many functions are not meant for public use, so place them in either the `detail` or an *anonymous* namespace, depending on the situation. #### `detail` namespace -Functions or objects that will be used across *multiple* translation units (i.e., source files), +Functions or objects that will be used across *multiple* translation units (i.e., source files), should be exposed in an internal header file and placed in the `detail` namespace. Example: ```c++ @@ -167,7 +167,7 @@ void reusable_helper_function(...); #### Anonymous namespace -Functions or objects that will only be used in a *single* translation unit should be defined in an +Functions or objects that will only be used in a *single* translation unit should be defined in an *anonymous* namespace in the source file where it is used. Example: ```c++ @@ -177,12 +177,12 @@ void isolated_helper_function(...); } // anonymous namespace ``` -[**Anonymous namespaces should *never* be used in a header file.**](https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL59-CPP.+Do+not+define+an+unnamed+namespace+in+a+header+file) +[**Anonymous namespaces should *never* be used in a header file.**](https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL59-CPP.+Do+not+define+an+unnamed+namespace+in+a+header+file) # Error Handling -cuOpt follows conventions (and provides utilities) enforcing compile-time and run-time -conditions and detecting and handling CUDA errors. Communication of errors is always via C++ +cuOpt follows conventions (and provides utilities) enforcing compile-time and run-time +conditions and detecting and handling CUDA errors. Communication of errors is always via C++ exceptions. ## Runtime Conditions @@ -194,13 +194,13 @@ Example usage: CUOPT_EXPECTS(lhs.type() == rhs.type(), "Column type mismatch"); ``` -The first argument is the conditional expression expected to resolve to `true` under normal -conditions. If the conditional evaluates to `false`, then an error has occurred and an instance of `cuopt::logic_error` is thrown. The second argument to `CUOPT_EXPECTS` is a short description of the -error that has occurred and is used for the exception's `what()` message. +The first argument is the conditional expression expected to resolve to `true` under normal +conditions. If the conditional evaluates to `false`, then an error has occurred and an instance of `cuopt::logic_error` is thrown. The second argument to `CUOPT_EXPECTS` is a short description of the +error that has occurred and is used for the exception's `what()` message. -There are times where a particular code path, if reached, should indicate an error no matter what. -For example, often the `default` case of a `switch` statement represents an invalid alternative. -Use the `CUOPT_FAIL` macro for such errors. This is effectively the same as calling +There are times where a particular code path, if reached, should indicate an error no matter what. +For example, often the `default` case of a `switch` statement represents an invalid alternative. +Use the `CUOPT_FAIL` macro for such errors. This is effectively the same as calling `CUOPT_EXPECTS(false, reason)`. Example: @@ -210,8 +210,8 @@ CUOPT_FAIL("This code path should not be reached."); ### CUDA Error Checking -Use the `RAFT_CUDA_TRY` macro to check for the successful completion of CUDA runtime API functions. This -macro throws a `cuopt::cuda_error` exception if the CUDA API return value is not `cudaSuccess`. The +Use the `RAFT_CUDA_TRY` macro to check for the successful completion of CUDA runtime API functions. This +macro throws a `cuopt::cuda_error` exception if the CUDA API return value is not `cudaSuccess`. The thrown exception includes a description of the CUDA error code in it's `what()` message. Example: diff --git a/cpp/doxygen/Doxyfile b/cpp/doxygen/Doxyfile index 2b4a68439..85ac84f11 100644 --- a/cpp/doxygen/Doxyfile +++ b/cpp/doxygen/Doxyfile @@ -44,7 +44,7 @@ PROJECT_NUMBER = 25.08 # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "NVIDIA® cuOpt™ is a GPU-accelerated optimization engine that excels in mixed integer programming (MIP), linear programming (LP), and vehicle routing problems (VRP). It enables near real-time solutions for large-scale challenges with millions of variables and constraints, offering easy integration into existing solvers and seamless deployment across hybrid and multi-cloud environments." +PROJECT_BRIEF = "NVIDIA® cuOpt™ is a GPU-accelerated optimization engine that excels in mixed integer programming (MIP), linear programming (LP), and vehicle routing problems (VRP). It enables near real-time solutions for large-scale challenges with millions of variables and constraints, offering easy integration into existing solvers and seamless deployment across hybrid and multi-cloud environments." # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 diff --git a/cpp/src/math_optimization/CMakeLists.txt b/cpp/src/math_optimization/CMakeLists.txt index 170ec18de..ad6626c55 100644 --- a/cpp/src/math_optimization/CMakeLists.txt +++ b/cpp/src/math_optimization/CMakeLists.txt @@ -20,5 +20,5 @@ list(PREPEND ${CMAKE_CURRENT_SOURCE_DIR}/solution_writer.cu ) -set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} +set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${MATH_OPT_SRC_FILES} PARENT_SCOPE) diff --git a/cpp/src/mip/CMakeLists.txt b/cpp/src/mip/CMakeLists.txt index 7b4440276..d3bdf3cf8 100644 --- a/cpp/src/mip/CMakeLists.txt +++ b/cpp/src/mip/CMakeLists.txt @@ -46,5 +46,5 @@ list(PREPEND ${CMAKE_CURRENT_SOURCE_DIR}/feasibility_jump/feasibility_jump_kernels.cu ${CMAKE_CURRENT_SOURCE_DIR}/solution/solution.cu) -set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} +set(CUOPT_SRC_FILES ${CUOPT_SRC_FILES} ${MIP_SRC_FILES} PARENT_SCOPE) diff --git a/cpp/src/routing/CMakeLists.txt b/cpp/src/routing/CMakeLists.txt index d4035d352..cfb976431 100644 --- a/cpp/src/routing/CMakeLists.txt +++ b/cpp/src/routing/CMakeLists.txt @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -set(ROUTING_SRC_FILES +set(ROUTING_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/local_search/compute_insertions.cu ${CMAKE_CURRENT_SOURCE_DIR}/ges/squeeze.cu ${CMAKE_CURRENT_SOURCE_DIR}/local_search/sliding_window.cu diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 3c90ec75a..50323dc7e 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -89,4 +89,4 @@ add_subdirectory(dual_simplex) add_subdirectory(examples) add_subdirectory(utilities) -enable_testing() \ No newline at end of file +enable_testing() diff --git a/cpp/tests/examples/CMakeLists.txt b/cpp/tests/examples/CMakeLists.txt index 40af81b06..ff4c66cca 100644 --- a/cpp/tests/examples/CMakeLists.txt +++ b/cpp/tests/examples/CMakeLists.txt @@ -13,4 +13,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -add_subdirectory(routing) +add_subdirectory(routing) diff --git a/cpp/tests/examples/routing/CMakeLists.txt b/cpp/tests/examples/routing/CMakeLists.txt index 6046deca7..52bc3e682 100644 --- a/cpp/tests/examples/routing/CMakeLists.txt +++ b/cpp/tests/examples/routing/CMakeLists.txt @@ -49,4 +49,4 @@ foreach(target cuopttestutils OpenMP::OpenMP_CXX ) -endforeach() +endforeach() diff --git a/cpp/tests/examples/routing/README.md b/cpp/tests/examples/routing/README.md index f1cd775f7..e08ab3946 100644 --- a/cpp/tests/examples/routing/README.md +++ b/cpp/tests/examples/routing/README.md @@ -1,7 +1,7 @@ # C++ example using Routing APIs -This C++ example demonstrates using Routing APIs to construct a -data model and pass it to the cuOpt solver for optimization and +This C++ example demonstrates using Routing APIs to construct a +data model and pass it to the cuOpt solver for optimization and get back the routing solution. diff --git a/cpp/tests/mip/CMakeLists.txt b/cpp/tests/mip/CMakeLists.txt index ef3b16d95..9fc2e3f88 100644 --- a/cpp/tests/mip/CMakeLists.txt +++ b/cpp/tests/mip/CMakeLists.txt @@ -48,4 +48,4 @@ ConfigureTest(FEASIBILITY_JUMP_TEST ) ConfigureTest(MIP_TERMINATION_STATUS_TEST ${CMAKE_CURRENT_SOURCE_DIR}/termination_test.cu -) \ No newline at end of file +) diff --git a/cpp/tests/utilities/CMakeLists.txt b/cpp/tests/utilities/CMakeLists.txt index 76ded1782..e893345c0 100644 --- a/cpp/tests/utilities/CMakeLists.txt +++ b/cpp/tests/utilities/CMakeLists.txt @@ -14,4 +14,4 @@ # limitations under the License. # Add CLI end-to-end test -ConfigureTest(CLI_TEST test_cli.cpp) \ No newline at end of file +ConfigureTest(CLI_TEST test_cli.cpp) diff --git a/datasets/mip/sudoku.mps b/datasets/mip/sudoku.mps old mode 100755 new mode 100644 diff --git a/docs/cuopt/README.md b/docs/cuopt/README.md index 435224424..a6570eb1a 100644 --- a/docs/cuopt/README.md +++ b/docs/cuopt/README.md @@ -3,7 +3,7 @@ Documentation dependencies are installed while installing the Conda environment, please refer to the [Build and Test](../../CONTRIBUTING.md#building-with-a-conda-environment) for more details. Assuming you have set-up the Conda environment, you can build the documentation along with all the cuOpt libraries by running: ```bash -./build.sh +./build.sh ``` In subsequent runs where there are no changes to the cuOpt libraries, documentation can be built by running: diff --git a/docs/cuopt/source/conf.py b/docs/cuopt/source/conf.py index 32c04ec36..586dce5c3 100644 --- a/docs/cuopt/source/conf.py +++ b/docs/cuopt/source/conf.py @@ -284,7 +284,7 @@ ("py:obj", "cuopt.routing.DataModel.add_order_precedence"), ("py:obj", "cuopt_sh_client.SolverMethod.denominator"), ("py:obj", "cuopt_sh_client.SolverMethod.imag"), - ("py:obj", "cuopt_sh_client.SolverMethod.numerator"), + ("py:obj", "cuopt_sh_client.SolverMethod.numerator"), ("py:obj", "cuopt_sh_client.SolverMethod.real"), ("py:obj", "cuopt_sh_client.SolverMethod.as_integer_ratio"), ("py:obj", "cuopt_sh_client.SolverMethod.bit_count"), diff --git a/docs/cuopt/source/cuopt-c/lp-milp/lp-example.rst b/docs/cuopt/source/cuopt-c/lp-milp/lp-example.rst index 4bbe62922..c828cf30b 100644 --- a/docs/cuopt/source/cuopt-c/lp-milp/lp-example.rst +++ b/docs/cuopt/source/cuopt-c/lp-milp/lp-example.rst @@ -63,7 +63,7 @@ Copy the code below into a file called ``lp_example.c``: cuopt_int_t num_variables = 2; cuopt_int_t num_constraints = 2; cuopt_int_t nnz = 4; - + // CSR format constraint matrix // https://docs.nvidia.com/nvpl/latest/sparse/storage_format/sparse_matrix.html#compressed-sparse-row-csr // From the constraints: @@ -72,31 +72,31 @@ Copy the code below into a file called ``lp_example.c``: cuopt_int_t row_offsets[] = {0, 2, 4}; cuopt_int_t column_indices[] = {0, 1, 0, 1}; cuopt_float_t values[] = {3.0, 4.0, 2.7, 10.1}; - + // Objective coefficients // From the objective function: minimize -0.2*x1 + 0.1*x2 // -0.2 is the coefficient of x1 // 0.1 is the coefficient of x2 cuopt_float_t objective_coefficients[] = {-0.2, 0.1}; - + // Constraint bounds // From the constraints: // 3.0*x1 + 4.0*x2 <= 5.4 // 2.7*x1 + 10.1*x2 <= 4.9 cuopt_float_t constraint_upper_bounds[] = {5.4, 4.9}; cuopt_float_t constraint_lower_bounds[] = {-CUOPT_INFINITY, -CUOPT_INFINITY}; - + // Variable bounds // From the constraints: // x1, x2 >= 0 cuopt_float_t var_lower_bounds[] = {0.0, 0.0}; cuopt_float_t var_upper_bounds[] = {CUOPT_INFINITY, CUOPT_INFINITY}; - + // Variable types (continuous) // From the constraints: // x1, x2 >= 0 char variable_types[] = {CUOPT_CONTINUOUS, CUOPT_CONTINUOUS}; - + cuopt_int_t status; cuopt_float_t time; cuopt_int_t termination_status; @@ -197,7 +197,7 @@ Copy the code below into a file called ``lp_example.c``: int main() { // Run the test cuopt_int_t status = test_simple_lp(); - + if (status == CUOPT_SUCCESS) { printf("\nTest completed successfully!\n"); return 0; @@ -219,7 +219,7 @@ If you have built it locally, libcuopt.so will be in the build directory ``cpp/b INCLUDE_PATH=$(find / -name "cuopt_c.h" -path "*/linear_programming/*" -printf "%h\n" | sed 's/\/linear_programming//' 2>/dev/null) # Find the libcuopt library and assign to LIBCUOPT_LIBRARY_PATH LIBCUOPT_LIBRARY_PATH=$(find / -name "libcuopt.so" 2>/dev/null) - + Build and run the example @@ -255,7 +255,7 @@ You should see the following output: Solve time: 0.000013 seconds Objective value: -0.360000 - Primal Solution: Solution variables + Primal Solution: Solution variables x1 = 1.800000 x2 = 0.000000 @@ -412,7 +412,7 @@ Copy the code below into a file called ``lp_example_mps.c``: // Run the solver cuopt_int_t status = solve_mps_file(argv[1]); - + if (status == CUOPT_SUCCESS) { printf("\nSolver completed successfully!\n"); return 0; diff --git a/docs/cuopt/source/cuopt-c/lp-milp/milp-examples.rst b/docs/cuopt/source/cuopt-c/lp-milp/milp-examples.rst index da08c0509..0dbfdcb71 100644 --- a/docs/cuopt/source/cuopt-c/lp-milp/milp-examples.rst +++ b/docs/cuopt/source/cuopt-c/lp-milp/milp-examples.rst @@ -65,7 +65,7 @@ Copy the code below into a file called ``milp_example.c``: cuopt_int_t num_variables = 2; cuopt_int_t num_constraints = 2; cuopt_int_t nnz = 4; - + // CSR format constraint matrix // https://docs.nvidia.com/nvpl/latest/sparse/storage_format/sparse_matrix.html#compressed-sparse-row-csr // From the constraints: @@ -74,33 +74,33 @@ Copy the code below into a file called ``milp_example.c``: cuopt_int_t row_offsets[] = {0, 2, 4}; cuopt_int_t column_indices[] = {0, 1, 0, 1}; cuopt_float_t values[] = {3.0, 4.0, 2.7, 10.1}; - + // Objective coefficients // From the objective function: minimize 0.2*x1 + 0.1*x2 // -0.2 is the coefficient of x1 // 0.1 is the coefficient of x2 cuopt_float_t objective_coefficients[] = {-0.2, 0.1}; - + // Constraint bounds // From the constraints: // 3.0*x1 + 4.0*x2 <= 5.4 // 2.7*x1 + 10.1*x2 <= 4.9 cuopt_float_t constraint_upper_bounds[] = {5.4, 4.9}; cuopt_float_t constraint_lower_bounds[] = {-CUOPT_INFINITY, -CUOPT_INFINITY}; - + // Variable bounds // From the constraints: // x1, x2 >= 0 cuopt_float_t var_lower_bounds[] = {0.0, 0.0}; cuopt_float_t var_upper_bounds[] = {CUOPT_INFINITY, CUOPT_INFINITY}; - + // Variable types (continuous) // From the constraints: // x1, x2 >= 0 // x1 is integer // x2 is continuous char variable_types[] = {CUOPT_INTEGER, CUOPT_CONTINUOUS}; - + cuopt_int_t status; cuopt_float_t time; cuopt_int_t termination_status; @@ -201,7 +201,7 @@ Copy the code below into a file called ``milp_example.c``: int main() { // Run the test cuopt_int_t status = test_simple_milp(); - + if (status == CUOPT_SUCCESS) { printf("\nTest completed successfully!\n"); return 0; @@ -223,7 +223,7 @@ If you have built it locally, libcuopt.so will be in the build directory ``cpp/b INCLUDE_PATH=$(find / -name "cuopt_c.h" -path "*/linear_programming/*" -printf "%h\n" | sed 's/\/linear_programming//' 2>/dev/null) # Find the libcuopt library and assign to LIBCUOPT_LIBRARY_PATH LIBCUOPT_LIBRARY_PATH=$(find / -name "libcuopt.so" 2>/dev/null) - + Build and run the example @@ -267,7 +267,7 @@ You should see the following output: Solve time: 0.000000 seconds Objective value: -0.200000 - Solution: + Solution: x1 = 1.000000 x2 = 0.000000 @@ -421,7 +421,7 @@ Copy the code below into a file called ``milp_example_mps.c``: // Run the solver cuopt_int_t status = solve_mps_file(argv[1]); - + if (status == CUOPT_SUCCESS) { printf("\nSolver completed successfully!\n"); return 0; @@ -505,7 +505,7 @@ You should see the following output: Root relaxation objective -3.01818182e+01 Strong branching on 2 fractional variables - | Explored | Unexplored | Objective | Bound | Depth | Iter/Node | Gap | Time + | Explored | Unexplored | Objective | Bound | Depth | Iter/Node | Gap | Time 0 1 +inf -3.018182e+01 1 0.0e+00 - 0.00 B 3 1 -2.700000e+01 -2.980000e+01 2 6.7e-01 10.4% 0.00 B&B added a solution to population, solution queue size 0 with objective -27 @@ -524,7 +524,7 @@ You should see the following output: Solve time: 0.000000 seconds Objective value: -28.000000 - Solution: + Solution: x1 = 4.000000 x2 = 0.000000 diff --git a/docs/cuopt/source/cuopt-cli/cli-examples.rst b/docs/cuopt/source/cuopt-cli/cli-examples.rst index 43cc14790..3eb487287 100644 --- a/docs/cuopt/source/cuopt-cli/cli-examples.rst +++ b/docs/cuopt/source/cuopt-cli/cli-examples.rst @@ -23,7 +23,7 @@ To solve a simple LP problem using cuopt_cli: VAR1 COST -0.2 VAR1 ROW1 3.0 VAR1 ROW2 2.7 - VAR2 COST 0.1 + VAR2 COST 0.1 VAR2 ROW1 4.0 VAR2 ROW2 10.1 RHS @@ -113,7 +113,7 @@ This should produce output similar to: Root relaxation objective -3.01818182e+01 Strong branching on 2 fractional variables - | Explored | Unexplored | Objective | Bound | Depth | Iter/Node | Gap | Time + | Explored | Unexplored | Objective | Bound | Depth | Iter/Node | Gap | Time 0 1 +inf -3.018182e+01 1 0.0e+00 - 0.00 B 3 1 -2.700000e+01 -2.980000e+01 2 6.7e-01 10.4% 0.00 B&B added a solution to population, solution queue size 0 with objective -27 diff --git a/docs/cuopt/source/cuopt-server/client-api/sh-cli-build.rst b/docs/cuopt/source/cuopt-server/client-api/sh-cli-build.rst index a68c01a6b..f1ab6d1b3 100644 --- a/docs/cuopt/source/cuopt-server/client-api/sh-cli-build.rst +++ b/docs/cuopt/source/cuopt-server/client-api/sh-cli-build.rst @@ -28,7 +28,7 @@ Here we are sharing current directory as both data and result directory. ip="0.0.0.0" port=5000 - python -m cuopt_server.cuopt_service -d="$PWD" -r="$PWD" -i="$ip" -p="$port" + python -m cuopt_server.cuopt_service -d="$PWD" -r="$PWD" -i="$ip" -p="$port" Example with JSON data as a direct string: @@ -38,7 +38,7 @@ Example with JSON data as a direct string: ip="0.0.0.0" port=5000 - curl --location "http://$ip:$port/cuopt/request" --header 'Content-Type: application/json' -d '{ + curl --location "http://$ip:$port/cuopt/request" --header 'Content-Type: application/json' -d '{ "cost_matrix_data": {"data": {"0": [[0, 1], [1, 0]]}}, "task_data": {"task_locations": [1], "demand": [[1]], "task_time_windows": [[0, 10]], "service_times": [1]}, "fleet_data": {"vehicle_locations":[[0, 0]], "capacities": [[2]], "vehicle_time_windows":[[0, 20]] }, @@ -83,7 +83,7 @@ Polling for Request Status: The cuOpt service employs an asynchronous interface for invocation and result retrieval. When you make an invocation request, the system will submit your problem to the solver and return a request id. -Users can poll the request id for status with the help of ``/cuopt/request/{request-id}`` endpoint. +Users can poll the request id for status with the help of ``/cuopt/request/{request-id}`` endpoint. .. code-block:: bash :linenos: diff --git a/docs/cuopt/source/cuopt-server/csp-guides/index.rst b/docs/cuopt/source/cuopt-server/csp-guides/index.rst index 3a162b57c..7fd30baba 100644 --- a/docs/cuopt/source/cuopt-server/csp-guides/index.rst +++ b/docs/cuopt/source/cuopt-server/csp-guides/index.rst @@ -10,5 +10,5 @@ This section contains guides on how to use the cuOpt server in different cloud p :name: CSP Guides Overview :titlesonly: - csp-azure.rst + csp-azure.rst csp-aws.rst \ No newline at end of file diff --git a/docs/cuopt/source/cuopt-server/examples/index.rst b/docs/cuopt/source/cuopt-server/examples/index.rst index c7c04c8b1..6a97a902b 100644 --- a/docs/cuopt/source/cuopt-server/examples/index.rst +++ b/docs/cuopt/source/cuopt-server/examples/index.rst @@ -12,4 +12,4 @@ This section contains examples on how to use the cuOpt server using the client. lp-examples.rst milp-examples.rst - routing-examples.rst \ No newline at end of file + routing-examples.rst \ No newline at end of file diff --git a/docs/cuopt/source/cuopt-server/examples/lp-examples.rst b/docs/cuopt/source/cuopt-server/examples/lp-examples.rst index 6d5b780b6..005a0f0c1 100644 --- a/docs/cuopt/source/cuopt-server/examples/lp-examples.rst +++ b/docs/cuopt/source/cuopt-server/examples/lp-examples.rst @@ -64,9 +64,9 @@ Genric Example With Normal Mode and Batch Mode # Number of repoll requests to be carried out for a successful response repoll_tries = 500 - + def repoll(solution, repoll_tries): - # If solver is still busy solving, the job will be assigned a request id and response is sent back in the + # If solver is still busy solving, the job will be assigned a request id and response is sent back in the # following format {"reqId": }. # Solver needs to be re-polled for response using this . @@ -104,12 +104,12 @@ Genric Example With Normal Mode and Batch Mode print("---------- Batch mode ----------------- \n", json.dumps(solution, indent=4)) - + The response would be as follows: Normal mode response: -.. code-block:: json +.. code-block:: json :linenos: { @@ -282,13 +282,13 @@ Previously run solutions can be saved and be used as warm start for new requests ) print(json.dumps(solution, indent=4)) - + # Delete saved solution if not required to save space cuopt_service_client.delete(initial_solution["reqId"]) The response would be as follows: -.. code-block:: json +.. code-block:: json :linenos: { @@ -372,12 +372,12 @@ An example on using .mps files as input is shown below: ) ss = ThinClientSolverSettings() - + ss.set_parameter("time_limit", 5) ss.set_optimality_tolerance(0.00001) - + solution = cuopt_service_client.get_LP_solve(data, solver_config=ss, response_type="dict") - + print(json.dumps(solution, indent=4)) The response is: @@ -428,7 +428,7 @@ The response is: Generate Datamodel from MPS Parser ---------------------------------- -Use a datamodel generated from mps file as input; this yields a solution object in response. For more details please refer to `LP/MILP parameters <../../lp-milp-settings.html>`_. +Use a datamodel generated from mps file as input; this yields a solution object in response. For more details please refer to `LP/MILP parameters <../../lp-milp-settings.html>`_. .. code-block:: python :linenos: @@ -563,7 +563,7 @@ Example with DataModel is available in the `Examples Notebooks Repository `_. More details on the response can be found under the responses schema `request and solution API spec <../../open-api.html#/default/getrequest_cuopt_request__id__get>`_. -Aborting a Running Job in Thin Client +Aborting a Running Job in Thin Client ------------------------------------- Please refer to the `MILP Example on Aborting a Running Job in Thin Client `_ for more details. diff --git a/docs/cuopt/source/cuopt-server/examples/milp-examples.rst b/docs/cuopt/source/cuopt-server/examples/milp-examples.rst index be76fb97e..981bb3192 100644 --- a/docs/cuopt/source/cuopt-server/examples/milp-examples.rst +++ b/docs/cuopt/source/cuopt-server/examples/milp-examples.rst @@ -2,7 +2,7 @@ MILP Python Examples ======================================== -The major difference between this example and the LP example is that some of the variables are integers, so ``variable_types`` need to be shared. +The major difference between this example and the LP example is that some of the variables are integers, so ``variable_types`` need to be shared. The OpenAPI specification for the server is available in `open-api spec <../../open-api.html>`_. The example data is structured as per the OpenAPI specification for the server, please refer `LPData <../../open-api.html#/default/postrequest_cuopt_request_post>`_ under schema section. LP and MILP share same spec. Generic Example @@ -53,7 +53,7 @@ Generic Example ) def repoll(solution, repoll_tries): - # If solver is still busy solving, the job will be assigned a request id and response is sent back in the + # If solver is still busy solving, the job will be assigned a request id and response is sent back in the # following format {"reqId": }. # Solver needs to be re-polled for response using this . @@ -70,7 +70,7 @@ Generic Example return solution solution = cuopt_service_client.get_LP_solve(data, response_type="dict") - + # Number of repoll requests to be carried out for a successful response repoll_tries = 500 @@ -182,7 +182,7 @@ The incumbent solution can be retrieved using a callback function as follows: solution = cuopt_service_client.get_LP_solve( data, incumbent_callback=callback, response_type="dict", logging_callback=log_callback ) - + print(json.dumps(solution, indent=4)) Log the callback response: @@ -251,7 +251,7 @@ The ``data`` argument to ``get_LP_solve`` may be a dictionary of the format show They can be of different format as well, please check the documentation. -Aborting a Running Job in Thin Client +Aborting a Running Job in Thin Client ------------------------------------- .. code-block:: python diff --git a/docs/cuopt/source/cuopt-server/examples/routing-examples.rst b/docs/cuopt/source/cuopt-server/examples/routing-examples.rst index f66a58f9f..0c33c3046 100644 --- a/docs/cuopt/source/cuopt-server/examples/routing-examples.rst +++ b/docs/cuopt/source/cuopt-server/examples/routing-examples.rst @@ -31,7 +31,7 @@ Generic Example ) def repoll(solution, repoll_tries): - # If solver is still busy solving, the job will be assigned a request id and response is sent back in the + # If solver is still busy solving, the job will be assigned a request id and response is sent back in the # following format {"reqId": }. # Solver needs to be re-polled for response using this . @@ -133,7 +133,7 @@ Previously run solutions or uploaded solutions can be used as the initial soluti timeout_exception=False ) - # Get initial solution + # Get initial solution # Set delete_solution to false so it can be used in next request initial_solution = cuopt_service_client.get_optimized_routes( data, delete_solution=False @@ -288,13 +288,13 @@ To enable HTTPS: openssl req -newkey rsa:2048 -nodes -keyout server.key -subj "/C=CN/ST=GD/L=SZ/O=Acme, Inc./CN=*.example.com" -out server.csr openssl x509 -req -extfile <(printf "subjectAltName=DNS:example.com,DNS:www.example.com") -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt - + ``server.crt`` and ``server.key`` are meant for server, ``ca.crt`` is meant for client. More examples are available in the `Examples Notebooks Repository `_. -Aborting a Running Job in Thin Client +Aborting a Running Job in Thin Client ------------------------------------- Please refer to the `MILP Example on Aborting a Running Job in Thin Client `_ for more details. @@ -377,7 +377,7 @@ To enable HTTPS ---------------- * In the case of the server using public certificates, simply enable https. - + .. code-block:: shell cuopt_sh data.json -s -i $ip -p $port diff --git a/docs/cuopt/source/cuopt-server/index.rst b/docs/cuopt/source/cuopt-server/index.rst index f7b04a326..d10420ab5 100644 --- a/docs/cuopt/source/cuopt-server/index.rst +++ b/docs/cuopt/source/cuopt-server/index.rst @@ -1,7 +1,7 @@ Server ====== -NVIDIA cuOpt server is a REST API server that is built for the purpose of providing language agnostic access to the cuOpt optimization engine. Users can build their own clients in any language that supports HTTP requests or use cuopt-sh-client, a lightweight Python client, to communicate with the server. +NVIDIA cuOpt server is a REST API server that is built for the purpose of providing language agnostic access to the cuOpt optimization engine. Users can build their own clients in any language that supports HTTP requests or use cuopt-sh-client, a lightweight Python client, to communicate with the server. .. image:: images/cuOpt-self-hosted.png :width: 500 diff --git a/docs/cuopt/source/faq.rst b/docs/cuopt/source/faq.rst index c4db136b7..7a5e4666b 100644 --- a/docs/cuopt/source/faq.rst +++ b/docs/cuopt/source/faq.rst @@ -66,7 +66,7 @@ General FAQ 2. Try to locate the process that is using port 5000 and stop it if possible. A tool like ``netstat`` run as the root user can help identify ports mapped to processes, and ``docker ps -a`` will show running containers. - + 3. Alternatively, use port mapping to launch cuOpt on a different port such as 5001 (note the omission of ``–network=host`` flag): 4. If running locally, you can also use ``ps -aux | grep cuopt_server`` to find the process and kill it. @@ -85,7 +85,7 @@ General FAQ This error indicates that the cuOpt shared library is not found. Please check the following: - - The cuOpt is installed + - The cuOpt is installed - Use ``find / -name libcuopt.so`` to search for the library path from root directory. You might need to run this command as root user. - If the library is found, please add it to the ``LD_LIBRARY_PATH`` environment variable as shown below: @@ -107,18 +107,18 @@ General FAQ .. dropdown:: The cuOpt service is not responding: What to check? - 1. cuOpt microservice health check on the cuOpt host. - + 1. cuOpt microservice health check on the cuOpt host. + Perform a health-check locally on the host running cuOpt: .. code-block:: bash curl -s -o /dev/null -w '%{http_code}\\n' localhost:5000/cuopt/health 200 - + If this command returns 200, cuOpt is running and listening on the specified port. - + If this command returns something other than 200, check the following: - Check that a cuOpt container is running with ``docker -ps``. @@ -127,7 +127,7 @@ General FAQ - Restart cuOpt and see if that corrects the problem. 2. cuOpt microservice health-check from a remote host. - + If you are trying to reach cuOpt from a remote host, run the health check from the remote host and specify the IP address of the cuOpt host, for example: .. code-block:: bash @@ -230,7 +230,7 @@ Routing FAQ .. dropdown:: How to get partially feasible solutions to infeasible problems? - Use Prize collection, which associates each task with a prize and the solver will maximize the prize collected. This allows cuOpt to prioritize some tasks over others. + Use Prize collection, which associates each task with a prize and the solver will maximize the prize collected. This allows cuOpt to prioritize some tasks over others. .. dropdown:: What is a dimension mismatch error? @@ -257,7 +257,7 @@ Routing FAQ .. dropdown:: Do we need to normalize the data when creating a time window matrix? - The units can be whatever the customer wants them to be: minutes, seconds, milliseconds, hours, and so on. It is the user's responsibility to normalize the data across the complete problem, so all time-related constraints use the same unit. For example, if the travel time matrix is given in minutes, we want to make sure time windows and service times are also given in minutes. + The units can be whatever the customer wants them to be: minutes, seconds, milliseconds, hours, and so on. It is the user's responsibility to normalize the data across the complete problem, so all time-related constraints use the same unit. For example, if the travel time matrix is given in minutes, we want to make sure time windows and service times are also given in minutes. .. dropdown:: Is there a way to prevent vehicles from traveling along the same path in a waypoint graph, or is there a way to prevent more than one vehicle from visiting a location, or even that a location is only visited one time by a single vehicle? @@ -265,7 +265,7 @@ Routing FAQ .. dropdown:: Travel time deviation: When using the same dataset, the travel time varies by a couple of seconds in different runs, but the distance remains the same. How can travel time deviate in multiple runs on the same data and distance remains constant? - This is because travel time is not part of the objective, so we could have two solutions that are equivalent when picking the best solution. You can include total travel time (includes wait time) as part of the objective. + This is because travel time is not part of the objective, so we could have two solutions that are equivalent when picking the best solution. You can include total travel time (includes wait time) as part of the objective. .. dropdown:: There is no path between two locations, how do I input this information to the solver? @@ -305,7 +305,7 @@ Routing FAQ .. dropdown:: What are the limitations of the routing solver? #. The routing solver capabilities are based on few factors: - + - The available GPU memory - The size of the problem - Number of locations @@ -321,7 +321,7 @@ Routing FAQ Depending on these factors, the problems that can be solved can vary, for example: - On a H100 SXM with 80GB memory, the maximum number of locations that routing solver can handle is 10,000. - + At the same time, depending on complexity, the solver might be able to handle more or less than 10,000 locations. Linear Programming FAQs @@ -332,7 +332,7 @@ Linear Programming FAQs The batch mode allows solving many LPs in parallel to try to fully utilize the GPU when LP problems are too small. Using H100 SXM, the problem should be of at least 1K elements, and giving more than 100 LPs will usually not increase performance. .. dropdown:: Can the solver run on dense problems? - + Yes, but we usually see great results on very large and sparse problems. .. dropdown:: How large can the problem be? @@ -352,7 +352,7 @@ Linear Programming FAQs - Batch mode: In case you know upfront that you need to solve multiple LP problems, instead of solving them sequentially, you should use the batch mode which can solve multiple LPs in parallel. .. dropdown:: What solver mode should I choose? - + We cannot predict up-front which solver mode will work best for a particular problem. The only way to know is to test. Once you know a solver mode is good on a class of problems, it should also be good on other similar problems. .. dropdown:: What tolerance should I use? @@ -362,20 +362,20 @@ Linear Programming FAQs .. dropdown:: What are the limitations of the LP solver? #. There is no inherit limit imposed on the number of variables, number of constraints, or number of non-zeros you can have in a MILP or LP, except the restrictions due to the number of bits in an integer and the amount of memory in the CPU and GPU. - + Depending on these factors, the problems that can be solved can vary, for example: - On a H100 SXM with 80GB memory, here are few examples of the problems that can be solved: - - 10M rows/constraints, 10M columns/variables, and 2B non-zeros in the constraint matrix. + - 10M rows/constraints, 10M columns/variables, and 2B non-zeros in the constraint matrix. - 74.5M rows/constraints, 74.5M columns/variables, and 1.49B non-zeros in the constraint matrix. - + Mixed Integer Linear Programming FAQs -------------------------------------- .. dropdown:: What are the limitations of the MILP solver? #. There is no inherit limit imposed on the number of variables, number of constraints, or number of non-zeros you can have in a MILP or LP, except the restrictions due to the number of bits in integer and the amount of memory in the CPU and GPU. - + Depending on these factors, the problems that can be solved can vary, for example: - On a H100 SXM with 80GB memory, this is the biggest dataset that was tested: diff --git a/docs/cuopt/source/hidden/limitations.rst b/docs/cuopt/source/hidden/limitations.rst index f672646ec..7c319cdce 100644 --- a/docs/cuopt/source/hidden/limitations.rst +++ b/docs/cuopt/source/hidden/limitations.rst @@ -6,7 +6,7 @@ Routing ======= #. Number of tasks: - - For ``H100`` : ``Tasks <= 15000`` per solve request. + - For ``H100`` : ``Tasks <= 15000`` per solve request. - For ``A100`` : ``Tasks <= 10000`` per solve request. .. note:: @@ -30,7 +30,7 @@ Linear Programming - For ``H100``, - 10M rows/constraints 10M columns/variables and 2B non-zeros in the constraint matrix - - 74.5M rows/constraints 74.5M columns/variables and 1.49B non-zeros in the constraint matrix + - 74.5M rows/constraints 74.5M columns/variables and 1.49B non-zeros in the constraint matrix Mixed Integer Linear Programming ================================ diff --git a/docs/cuopt/source/index.rst b/docs/cuopt/source/index.rst index 38b585f3a..a9673ab27 100644 --- a/docs/cuopt/source/index.rst +++ b/docs/cuopt/source/index.rst @@ -68,7 +68,7 @@ Third-Party Modeling Languages :caption: Third-Party Modeling Languages :name: Third-Party Modeling Languages - thirdparty_modeling_languages/index.rst + thirdparty_modeling_languages/index.rst ============= Resources diff --git a/docs/cuopt/source/introduction.rst b/docs/cuopt/source/introduction.rst index 5eb537ce2..3ea9b91d4 100644 --- a/docs/cuopt/source/introduction.rst +++ b/docs/cuopt/source/introduction.rst @@ -12,7 +12,7 @@ As part of `NVIDIA AI Enterprise `__ for more information about the NVIDIA Developer Program. + Check out this `FAQ `__ for more information about the NVIDIA Developer Program. The core engine is built on C++ and all the APIs are built on top of it as wrappers. For example, cuOpt Python API uses Cython to wrap the C++ core engine and provide a Python interface. Similarly, other interfaces wrap different layers to communicate with the core engine. @@ -20,11 +20,11 @@ The core engine is built on C++ and all the APIs are built on top of it as wrapp Routing (TSP, VRP, and PDP) ============================= -The **Vehicle Routing Problem (VRP)** and **Pickup and Delivery Problems (PDP)** are derived from the **Traveling Salesperson Problem (TSP)**, which is one of the most studied problems in operations research and, more generally, in computer science. +The **Vehicle Routing Problem (VRP)** and **Pickup and Delivery Problems (PDP)** are derived from the **Traveling Salesperson Problem (TSP)**, which is one of the most studied problems in operations research and, more generally, in computer science. -TSP asks the following question: +TSP asks the following question: - - Given a list of destinations and a matrix of distances between each pair of destinations, what is the shortest possible route that visits each destination exactly one time and returns to the original location? + - Given a list of destinations and a matrix of distances between each pair of destinations, what is the shortest possible route that visits each destination exactly one time and returns to the original location? For example, the TSP has several applications in planning and logistics, where a good solution can save significant travel time and fuel costs in the transportation and delivery of goods. VRP and PDP are essentially extensions of TSP with additional complexity. @@ -66,7 +66,7 @@ This is a linear program. How cuOpt Solves the Linear Programming Problem ------------------------------------------------ -cuOpt includes an LP solver based on `PDLP `__, a new First-Order Method (FOM) used to solve large-scale LPs. This solver implements gradient descent, enhanced by heuristics, and performing massively parallel operations efficiently by leveraging the latest NVIDIA GPUs. +cuOpt includes an LP solver based on `PDLP `__, a new First-Order Method (FOM) used to solve large-scale LPs. This solver implements gradient descent, enhanced by heuristics, and performing massively parallel operations efficiently by leveraging the latest NVIDIA GPUs. In addition to PDLP, cuOpt includes a dual simplex solver that runs on the CPU. Both algorithms can be run concurrently on the GPU and CPU. @@ -85,7 +85,7 @@ For example, consider the following system of constraints: y >= 0 and y is continuous, -and suppose we wish to maximize the objective function +and suppose we wish to maximize the objective function f(x,y) = 5x + 3y. @@ -96,7 +96,7 @@ Although MILPs seems similar to a LPs, they require much more computation to sol How cuOpt Solves the Mixed-Integer Linear Programming Problem ------------------------------------------------------------- -The MILP solver is a hybrid GPU/CPU algorithm. Primal heuristics including local search, feasibility pump, and feasibility jump are performed on the GPU to improve the primal bound. Branch and bound is performed on the CPU to improve the dual bound. Integer feasible solutions are shared between both algorithms. +The MILP solver is a hybrid GPU/CPU algorithm. Primal heuristics including local search, feasibility pump, and feasibility jump are performed on the GPU to improve the primal bound. Branch and bound is performed on the CPU to improve the dual bound. Integer feasible solutions are shared between both algorithms. ============================= @@ -112,7 +112,7 @@ cuOpt supports the following APIs: - cuOpt is written in C++ and includes a native C++ API. However, we do not provide documentation for the C++ API at this time. We anticipate that the C++ API will change significantly in the future. Use it at your own risk. - Python support - `Routing (TSP, VRP, and PDP) - Python `_ - - Linear Programming (LP) and Mixed Integer Linear Programming (MILP) + - Linear Programming (LP) and Mixed Integer Linear Programming (MILP) - cuOpt includes a Python API that is used as the backend of the cuOpt server. However, we do not provide documentation for the Python API at this time. We suggest using cuOpt server to access cuOpt via Python. We anticipate that the Python API will change significantly in the future. Use it at your own risk. - Server support - `Linear Programming (LP) - Server `_ diff --git a/docs/cuopt/source/lp-features.rst b/docs/cuopt/source/lp-features.rst index 9fa3b3fd9..ae4abac25 100644 --- a/docs/cuopt/source/lp-features.rst +++ b/docs/cuopt/source/lp-features.rst @@ -11,7 +11,7 @@ The LP solver can be accessed in the following ways: Supported modeling languages: - AMPL - - PuLP + - PuLP - **C API**: A native C API that provides direct low-level access to cuOpt's LP capabilities, enabling integration into any application or system that can interface with C. diff --git a/docs/cuopt/source/milp-features.rst b/docs/cuopt/source/milp-features.rst index 9168047f2..28926bf2a 100644 --- a/docs/cuopt/source/milp-features.rst +++ b/docs/cuopt/source/milp-features.rst @@ -11,7 +11,7 @@ The MILP solver can be accessed in the following ways: Currently supported solvers: - AMPL - - PuLP + - PuLP - **C API**: A native C API that provides direct low-level access to cuOpt's MILP solver, enabling integration into any application or system that can interface with C. diff --git a/docs/cuopt/source/project.json b/docs/cuopt/source/project.json index 36ffc89ad..d7feee353 100644 --- a/docs/cuopt/source/project.json +++ b/docs/cuopt/source/project.json @@ -1 +1 @@ -{"name": "cuopt", "version": "25.08.00", "url": "https://github.com/nvidia/cuopt", "description": "Nvidia cuOpt is a optimization engine"} \ No newline at end of file +{"name": "cuopt", "version": "25.08.00", "url": "https://github.com/nvidia/cuopt", "description": "Nvidia cuOpt is a optimization engine"} diff --git a/docs/cuopt/source/release-notes.rst b/docs/cuopt/source/release-notes.rst index db2be4d58..9ce9363f0 100644 --- a/docs/cuopt/source/release-notes.rst +++ b/docs/cuopt/source/release-notes.rst @@ -12,28 +12,28 @@ New Features - Added concurrent mode that runs PDLP and Dual Simplex together - Added crossover from PDLP to Dual Simplex - Added a C API for LP and MILP -- PDLP: Faster iterations and new more robust default PDLPSolverMode Stable2 +- PDLP: Faster iterations and new more robust default PDLPSolverMode Stable2 - Added support for writing out mps file containing user problem. Useful for debugging Breaking Changes ---------------- -- NoTermination is now a NumericalError -- Split cuOpt as libcuopt and cuopt wheel +- NoTermination is now a NumericalError +- Split cuOpt as libcuopt and cuopt wheel Improvements ------------ - Hook up MILP Gap parameters and add info about number of nodes explored and simplex iterations -- FJ bug fixes, tests and improvements -- Allow no time limit in MILP -- Refactor routing -- Probing cache optimization +- FJ bug fixes, tests and improvements +- Allow no time limit in MILP +- Refactor routing +- Probing cache optimization - Diversity improvements for routing -- Enable more compile warnings and faster compile by bypassing rapids fetch -- Constraint prop based on load balanced bounds update -- Logger file handling and bug fixes on MILP -- Add shellcheck to pre-commit and fix warnings +- Enable more compile warnings and faster compile by bypassing rapids fetch +- Constraint prop based on load balanced bounds update +- Logger file handling and bug fixes on MILP +- Add shellcheck to pre-commit and fix warnings Bug Fixes --------- @@ -42,7 +42,7 @@ Bug Fixes - Fixed a bug using vehicle IDs in construct feasible solution algorithm. - FP recombiner probing bug fix. - Fix concurrent LP crashes. -- Fix print relative dual residual. +- Fix print relative dual residual. - Handle empty problems gracefully. - Improve breaks to allow dimensions at arbitrary places in the route. - Free var elimination with a substitute variable for each free variable. diff --git a/docs/cuopt/source/routing-features.rst b/docs/cuopt/source/routing-features.rst index 2cd5047ea..73b0a4318 100644 --- a/docs/cuopt/source/routing-features.rst +++ b/docs/cuopt/source/routing-features.rst @@ -21,7 +21,7 @@ In a Vehicle Routing Problem (VRP), enterprise customers may have a fleet that i Multiple Input Matrices ------------------------------ -A cost matrix needs to be a square matrix of some travel metric that is passed to the NVIDIA cuOpt solver. In many variations of the Traveling Salesman Problem (TSP), this includes travel time, distance, or another business cost. A cost matrix is a square matrix that represents the cost of traveling between each two pairs of locations in the problem. ``cost matrix`` can hold any cost matrix; the cost can be travel time, travel distance, dollar cost, or any weighted function of cost. If the cost matrix doesn't use travel time, ``travel time matrix`` should be used so that the cost matrix is used for optimization, while the travel time matrix is used for meeting time constraints. +A cost matrix needs to be a square matrix of some travel metric that is passed to the NVIDIA cuOpt solver. In many variations of the Traveling Salesman Problem (TSP), this includes travel time, distance, or another business cost. A cost matrix is a square matrix that represents the cost of traveling between each two pairs of locations in the problem. ``cost matrix`` can hold any cost matrix; the cost can be travel time, travel distance, dollar cost, or any weighted function of cost. If the cost matrix doesn't use travel time, ``travel time matrix`` should be used so that the cost matrix is used for optimization, while the travel time matrix is used for meeting time constraints. In the case of a heterogeneous fleet, different vehicle types may have different travel times. To support this, multiple ``cost matrix`` and ``travel time matrix`` can be provided such that each vehicle type has a corresponding matrix. @@ -80,7 +80,7 @@ Some use cases may include picking up an order from one location and delivering Precise Time Limits ------------------------------ -It is recommended to use the default time limit (which is ``10 + number_of_nodes/6``) seconds. If the time limit is set to X seconds, then solver continues to run for X seconds even when there is no improvement in the solution quality. +It is recommended to use the default time limit (which is ``10 + number_of_nodes/6``) seconds. If the time limit is set to X seconds, then solver continues to run for X seconds even when there is no improvement in the solution quality. .. note:: @@ -105,15 +105,15 @@ Fixed Cost per Vehicle ----------------------- Vehicles can have different fixed costs associated with them. This helps in scenarios where a single vehicle with a higher cost can be avoided if it can be done with two or more vehicles with lesser costs. This would be dependent on the objective function. -Mapping Orders to Vehicles, and Vehicles to Orders +Mapping Orders to Vehicles, and Vehicles to Orders --------------------------------------------------- -By default, cuOpt will assign orders to vehicles based on the optimal routes. However, in some cases, it makes sense to assign specific orders to specific vehicles, or, conversely, specific vehicles to specific orders. +By default, cuOpt will assign orders to vehicles based on the optimal routes. However, in some cases, it makes sense to assign specific orders to specific vehicles, or, conversely, specific vehicles to specific orders. -- ``order vehicle match`` allows assigning orders to vehicles. For example, a food distribution center wants to make shipments to grocery stores around the city. Say the fleet consists of refrigerated trucks, such that they can carry frozen food, and vans, which cannot. In this case, we want to assign the orders that contain frozen food to the trucks (rather than just any vehicle). +- ``order vehicle match`` allows assigning orders to vehicles. For example, a food distribution center wants to make shipments to grocery stores around the city. Say the fleet consists of refrigerated trucks, such that they can carry frozen food, and vans, which cannot. In this case, we want to assign the orders that contain frozen food to the trucks (rather than just any vehicle). - ``vehicle order match`` allows assigning vehicles to orders. For example, a maintenance company can have many employees (technicians) who can fulfil various tasks. When a customer requests a service, the company may dispatch any available technician to fulfill their request. However, if a customers request a service that only one technician can fulfill, those orders can be assigned to this one technician. -In cases where a set of orders need to be assigned to a set of vehicles, either constraint can be used as long as the mapping is done correctly. +In cases where a set of orders need to be assigned to a set of vehicles, either constraint can be used as long as the mapping is done correctly. Initial Solution ---------------- diff --git a/docs/cuopt/source/versions1.json b/docs/cuopt/source/versions1.json index a78cc6a87..89cbe1636 100644 --- a/docs/cuopt/source/versions1.json +++ b/docs/cuopt/source/versions1.json @@ -1,21 +1,20 @@ -[ +[ { "version": "25.08", "url": "../25.08/", "name": "latest", "preferred": true }, - { - "version": "25.05" + { + "version": "25.05", "url": "../25.05/" + }, + { + "version": "25.02", + "url": "../25.02/" + }, + { + "version": "24.11", + "url": "../24.11/" } - { - "version": "25.02" - "url": "../25.02/" - } - - { - "version": "24.11" - "url": "../24.11/" - } - ] + ] diff --git a/python/cuopt/CMakeLists.txt b/python/cuopt/CMakeLists.txt index 2aabad2a8..8ea79d784 100644 --- a/python/cuopt/CMakeLists.txt +++ b/python/cuopt/CMakeLists.txt @@ -38,4 +38,4 @@ include(rapids-cython-core) rapids_cython_init() add_subdirectory(cuopt) -add_subdirectory(cuopt/linear_programming/internals/) \ No newline at end of file +add_subdirectory(cuopt/linear_programming/internals/) diff --git a/python/cuopt/cuopt/routing/structure/routing_utilities.pxd b/python/cuopt/cuopt/routing/structure/routing_utilities.pxd index 548ffd295..52c87695b 100644 --- a/python/cuopt/cuopt/routing/structure/routing_utilities.pxd +++ b/python/cuopt/cuopt/routing/structure/routing_utilities.pxd @@ -43,7 +43,7 @@ cdef extern from "cuopt/error.hpp" namespace "cuopt": # noqa Success "cuopt::error_type_t::Success" # noqa ValidationError "cuopt::error_type_t::ValidationError" # noqa OutOfMemoryError "cuopt::error_type_t::OutOfMemoryError" # noqa - RuntimeError "cuopt::error_type_t::RuntimeError" # noqa + RuntimeError "cuopt::error_type_t::RuntimeError" # noqa cdef extern from "cuopt/routing/routing_structures.hpp" namespace "cuopt::routing": # noqa ctypedef enum objective_t "cuopt::routing::objective_t": diff --git a/python/cuopt_self_hosted/README.md b/python/cuopt_self_hosted/README.md index d5aab6735..f15f46693 100644 --- a/python/cuopt_self_hosted/README.md +++ b/python/cuopt_self_hosted/README.md @@ -47,7 +47,7 @@ Check the help with 'cuopt_sh -h' for more detailed information. -i: Host address of the cuOpt server (default 0.0.0.0) -p: Port of the cuOpt server (default 5000) -s: Use ssl (default False) - -c: Path to self signed certificates only, skip for standard certificates (default "") + -c: Path to self signed certificates only, skip for standard certificates (default "") -l: Log level (critical,error,warning,info,debug) -ov: If set, only validates input -v: Print client version and exit @@ -154,7 +154,7 @@ For more details see https://docs.nvidia.com/cuopt/user-guide/serv-api.html By default, the local file feature is not enabled in the cuOpt server. To configure the feature, set the environment variables described below in the server's container environment. ### Environment variables - + To enable reading of cuOpt data files from the local filesystem, set the following * CUOPT_DATA_DIR: the absolute path of a directory in the cuOpt server's container environment. Typically this path is the mount point for a volume that exists outside of the container. diff --git a/python/cuopt_server/cuopt_server/cuopt_service.py b/python/cuopt_server/cuopt_server/cuopt_service.py old mode 100755 new mode 100644 diff --git a/python/cuopt_server/cuopt_server/utils/job_queue.py b/python/cuopt_server/cuopt_server/utils/job_queue.py old mode 100755 new mode 100644