Skip to content

Main merge release/26.06 05 - #1318

Merged
ramakrishnap-nv merged 3 commits into
NVIDIA:mainfrom
ramakrishnap-nv:main-merge-release/26.06_05
May 28, 2026
Merged

Main merge release/26.06 05#1318
ramakrishnap-nv merged 3 commits into
NVIDIA:mainfrom
ramakrishnap-nv:main-merge-release/26.06_05

Conversation

@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator

For #1317

tmckayus and others added 3 commits May 28, 2026 15:32
This change adds a code generator written in Python which generates the protobuf specifications and the code to map between cuopt problem, solution, and settings structures and protobuf messages. The protoc compiler is still used to build the serialization/deserialziation code and the grpc interface -- only the high-level .proto files are generated from the yaml description.

The code generator reads a lightweight yaml file which describes the cuopt structures and generates mapping functions which are included in the grpc client and server implementations.

When a field is added/changed in the problem, solution, or settings structures, a developer updates the yaml file and re-runs the code generator, then reviews the updated code.

A README.md file in the codegen directory describes the yaml format, defaults, and conventions. As much as possible has been left to defaults or naming conventions to make the yaml easy to maintain.

Authors:
  - Trevor McKay (https://github.com/tmckayus)
  - Ramakrishnap (https://github.com/rgsl888prabhu)

Approvers:
  - Ramakrishnap (https://github.com/rgsl888prabhu)
  - Miles Lubin (https://github.com/mlubin)

URL: NVIDIA#1107
…ual bound using this info. (NVIDIA#1239)

This PR recognizes when the objective for a MIP can only move in discrete steps or increments. 

Integer variables can only move in steps of 1. You can then use equality constraints to try to find steps for continuous variables. And eventually show that an objective containing a mix of integer and continuous variables must also move in discrete steps.

Using this allows you to improve your lower bound and stop early. For example, let's say objective has to be a multiple of 1/2. You have an upper bound of 2 and a lower bound of 1.7. You can declare optimality already, since the next best objective is 1.5 and your lower bound is already better than that.

The computation is extremely fast. The longest problem in the MIPLIB benchmark, `roi5alpha10n8`,
only takes 157 ms. 

This structure appears in 15/240 MIPLIB benchmark problems. It produces a 2x speedup on `mzzv42z`

```
Model                  Step      Time w/   Time w/o  Speedup   Gap w/    Gap w/o   Gap ratio
------------------------------------------------------------------------------------------
leo1                   4         300.7s    300.8s    1.00x     2.13%     2.48%     1.16
leo2                   1         300.0s    302.2s    1.01x     2.22%     3.21%     1.45
mas74                  1e-05     35.8s     39.4s     1.10x     0.01%     0.01%     0.99
mzzv11                 2         300.0s    300.1s    1.00x     5.08%     4.63%     0.91
mzzv42z                2         113.2s    235.1s    2.08x     0.00%     0.00%     —
n2seq36q               200       305.1s    300.0s    0.98x     0.38%     0.38%     1.00
n3div36                200       300.6s    301.8s    1.00x     3.52%     3.55%     1.01
neos-2075418-temuka    250       300.0s    300.0s    1.00x     inf       inf       —
neos-4532248-waihi     0.1       300.2s    300.0s    1.00x     99.2%     99.9%     1.01
nu25-pr12              5         4.0s      3.7s      0.92x     0.01%     0.00%     0.20
nw04                   2         54.3s     52.9s     0.97x     0.00%     0.01%     —
qap10                  2         43.5s     34.2s     0.79x     0.00%     0.00%     —
sp97ar                 8         302.3s    302.7s    1.00x     1.50%     1.46%     0.97
sp98ar                 4         302.2s    302.8s    1.00x     0.41%     0.68%     1.66
supportcase33          5         300.1s    300.1s    1.00x     13.2%     16.1%     1.22
var-smallemery-m6j6    0.03125   301.6s    301.5s    1.00x     1.86%     1.81%     0.97
------------------------------------------------------------------------------------------
Geomean speedup:    1.03x  (N=15)
Geomean gap ratio:  1.14   (N=9, excluding solved/infeasible)
```

Authors:
  - Chris Maes (https://github.com/chris-maes)

Approvers:
  - Akif ÇÖRDÜK (https://github.com/akifcorduk)
  - Nicolas L. Guidotti (https://github.com/nguidotti)
  - Ramakrishnap (https://github.com/rgsl888prabhu)

URL: NVIDIA#1239
@ramakrishnap-nv
ramakrishnap-nv requested review from a team as code owners May 28, 2026 15:57
@ramakrishnap-nv ramakrishnap-nv added non-breaking Introduces a non-breaking change improvement Improves an existing functionality labels May 28, 2026
@ramakrishnap-nv
ramakrishnap-nv merged commit 8e534f1 into NVIDIA:main May 28, 2026
28 of 29 checks passed
@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds an objective-step lattice feature for MIP optimization and refactors gRPC code generation from hand-written mappers to a declarative YAML registry with auto-generated .inc includes. The objective-step feature enables the solver to snap optimization problems onto objective lattices; the gRPC changes centralize type mappings and reduce hand-written boilerplate.

Changes

Objective Step Lattice Feature

Layer / File(s) Summary
Objective Step Type System & Constants
cpp/src/dual_simplex/user_problem.hpp, cpp/include/cuopt/linear_programming/mip/solver_settings.hpp, cpp/include/cuopt/linear_programming/constants.h
Introduces objective_step_t<f_t> struct with step_size and bias fields, extends user_problem_t and mip_solver_settings_t with objective step storage, and adds CUOPT_MIP_OBJECTIVE_STEP parameter constant.
Rational Utilities & Lattice Propagation
cpp/src/cuts/rational.hpp, cpp/src/cuts/objective_step.hpp, cpp/src/cuts/objective_step.cpp, cpp/src/cuts/CMakeLists.txt
Implements continued-fraction rational approximation, rational128_t type with GCD operations, and core propagate_lattice() function that discovers per-variable lattice steps via equality/inequality constraint analysis; includes template instantiations for double and float.
Objective Step Integration in MIP & B&B
cpp/src/dual_simplex/presolve.hpp, cpp/src/dual_simplex/presolve.cpp, cpp/src/mip_heuristics/problem/problem.cuh, cpp/src/mip_heuristics/problem/problem.cu, cpp/src/mip_heuristics/solver.cu, cpp/src/branch_and_bound/branch_and_bound.cpp, cpp/src/math_optimization/solver_settings.cu, cpp/src/cuts/cuts.cpp
Adds objective_step member to lp_problem_t and problem_t classes; implements compute_objective_step() with fast lattice-known and slow propagation paths; updates branch-and-bound update_tree_impl and solve_node_lp to use objective-step lattice for lower-bound and LP cut-off calculations; registers parameter in solver settings with min/max bounds; consolidates rational-approximation logic from cuts.cpp to rational.hpp.
Host-Oriented Accessor for Quadratic Objective
cpp/include/cuopt/linear_programming/cpu_optimization_problem.hpp
Adds get_quadratic_objective_*_host() override methods that expose CPU-resident quadratic objective data.

gRPC Code Generation Refactoring

Layer / File(s) Summary
Build Infrastructure & Verification
build.sh, ci/test_cpp.sh, ci/verify_grpc_codegen.sh, cpp/CMakeLists.txt
Adds codegen build target to delete and regenerate gRPC outputs; creates verify_grpc_codegen.sh script that compares generated temp output against committed artifacts and reports mismatches/orphans; integrates verification as CI test gate; updates CMakeLists to explicitly path generated proto directory and generate separate cuopt_remote_data.proto step.
Field Registry, Proto Splitting & Dependencies
cpp/src/grpc/codegen/field_registry.yaml, cpp/src/grpc/cuopt_remote.proto, cpp/src/grpc/cuopt_remote_service.proto, conda/environments/*.yaml, dependencies.yaml
Introduces comprehensive 917-line YAML field registry defining enums, LP/MIP solutions, solver settings, and optimization problem schemas with field mappings, optional/sentinel markers, and code-generation directives; splits data-bearing types into generated cuopt_remote_data.proto; keeps protocol-level messages in cuopt_remote.proto; adds ResultArrayDescriptor and ChunkedResultHeader to generated data proto; updates conda and dependencies.yaml to include ruamel.yaml>=0.18 for YAML processing.
gRPC Code Generation & Interface Documentation
cpp/src/grpc/GRPC_CODE_GENERATION.md, cpp/src/grpc/GRPC_INTERFACE.md
Documents registry schema, enum/message/settings definitions, field allocation strategy, and how generated .inc files are consumed by mappers; specifies chunked transfer protocol flow, automatic size-based routing, and error handling for large problem/result handling.
gRPC Mapper Refactoring to Generated Includes
cpp/src/grpc/grpc_problem_mapper.cpp, cpp/src/grpc/grpc_settings_mapper.cpp, cpp/src/grpc/grpc_solution_mapper.cpp
Replaces large hand-written implementations of map_problem_to_proto, map_proto_to_problem, settings mappers, and solution mappers with generated .inc include blocks; consolidates chunking/byte-conversion helpers under anonymous namespaces; adds explicit post-decode sanitization for PDLP/MIP enum ranges and iteration_limit overflow protection; changes bytes_to_typed to throw std::invalid_argument on misaligned payload.
gRPC Solution Mapper Header & Helper Updates
cpp/src/grpc/grpc_solution_mapper.hpp, cpp/src/grpc/server/grpc_field_element_size.hpp, cpp/src/grpc/server/grpc_incumbent_proto.hpp
Removes termination-status protobuf conversion declarations; adds chunked-result support declarations for size estimation, header population, array collection, and solution reconstruction; replaces hand-written ArrayFieldId element-size switch with generated include; updates path reference in incumbent proto comment.

gRPC Tests & Test Infrastructure

Layer / File(s) Summary
Test CMakeLists & Parameter Support
cpp/tests/linear_programming/grpc/CMakeLists.txt, python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py
Adds generated proto codegen directory to gRPC test include paths; extends _non_default_solver_param_value to handle mip_objective_step by toggling between 0/1.
gRPC Mapper Roundtrip & Presence Tests
cpp/tests/linear_programming/grpc/grpc_client_test.cpp
Expands MIPSettingsAllFields to set/verify symmetry and heuristic parameters; adds MIPSettingsSymmetryClampsOutOfRange test for enum boundary handling; extends PDLPSettingsAllFields with additional solver config fields; introduces optional-field presence tests verifying C++ defaults are preserved when proto fields are omitted; adds comprehensive "default proto preserves C++ defaults" sanity tests for both PDLP and MIP settings.
Proto Serialization Test Updates
cpp/tests/linear_programming/grpc/grpc_pipe_serialization_test.cpp
Updates problem-category constant usage from fully-qualified cuopt::remote::LP/MIP to unqualified enum; changes MIP error-message field from set_mip_error_message() to set_error_message().

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


Possibly related PRs

  • NVIDIA/cuopt#1239: Parallel implementation of the objective step feature end-to-end for MIP optimization.
  • NVIDIA/cuopt#1103: Modifies branch-and-bound solve_node_lp cutoff logic; overlaps with objective-step lower-bound/cutoff changes in this PR.
  • NVIDIA/cuopt#1107: Earlier gRPC code-generation boilerplate setup; directly related to this PR's codegen verification and registry-driven refactoring.

Suggested labels

mip, grpc, code-generation


Suggested reviewers

  • Iroy30
  • chris-maes
  • tmckayus
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.05% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Main merge release/26.06 05' is vague and generic, using non-descriptive terms that don't clearly convey the main changes in the changeset. Revise the title to clearly summarize the primary changes, such as 'Add objective step tightening and gRPC code generation from YAML' or similar descriptive phrasing.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description references issue #1317 and the PR objectives provide clear context about the two main features: YAML-driven gRPC code generation and objective step tightening for MIP solvers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improves an existing functionality non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants