Skip to content

make objective_scaling_factor optional for gRPC - #1600

Merged
rapids-bot[bot] merged 1 commit into
NVIDIA:mainfrom
tmckayus:fix/grpc-objective-scaling-presence
Jul 22, 2026
Merged

make objective_scaling_factor optional for gRPC#1600
rapids-bot[bot] merged 1 commit into
NVIDIA:mainfrom
tmckayus:fix/grpc-objective-scaling-presence

Conversation

@tmckayus

Copy link
Copy Markdown
Contributor

This coupled with a presence check adjusts for the proto3 default 0 on omission of non-optional fields, which differs from the cuopt default of 1.

Previously, omitted objective_scaling_factor fields would cause a remote solve to use objective_scaling_factor = 0, instead of the cuopt default "1". (If the field was not omitted, it would only be 0 if explicitly set. Zero is not a valid value in any case).

Found during a routine review of gRPC fields versus local solve.

@tmckayus
tmckayus requested a review from a team as a code owner July 21, 2026 20:22
@tmckayus
tmckayus requested review from mlubin and nguidotti July 21, 2026 20:22
@tmckayus tmckayus added bug Something isn't working non-breaking Introduces a non-breaking change labels Jul 21, 2026
@tmckayus tmckayus added this to the 26.08 milestone Jul 21, 2026
@tmckayus
tmckayus requested a review from ramakrishnap-nv July 21, 2026 20:24
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0d759be0-e4ae-405c-8bde-a1edb63a4541

📥 Commits

Reviewing files that changed from the base of the PR and between f3f25b4 and b3790ef.

⛔ Files ignored due to path filters (3)
  • cpp/src/grpc/codegen/generated/cuopt_remote_data.proto is excluded by !**/generated/**
  • cpp/src/grpc/codegen/generated/generated_chunked_header_to_problem.inc is excluded by !**/generated/**
  • cpp/src/grpc/codegen/generated/generated_proto_to_problem.inc is excluded by !**/generated/**
📒 Files selected for processing (5)
  • cpp/src/grpc/codegen/FIELD_REGISTRY_REFERENCE.md
  • cpp/src/grpc/codegen/field_registry.yaml
  • cpp/src/grpc/codegen/generate_conversions.py
  • cpp/src/grpc/cuopt_remote_service.proto
  • cpp/tests/linear_programming/grpc/grpc_client_test.cpp
🚧 Files skipped from review as they are similar to previous changes (5)
  • cpp/src/grpc/cuopt_remote_service.proto
  • cpp/src/grpc/codegen/field_registry.yaml
  • cpp/src/grpc/codegen/generate_conversions.py
  • cpp/src/grpc/codegen/FIELD_REGISTRY_REFERENCE.md
  • cpp/tests/linear_programming/grpc/grpc_client_test.cpp

📝 Walkthrough

Walkthrough

The objective scaling factor now uses protobuf presence tracking across unary and chunked conversion paths, preserving the C++ default when omitted and validating explicit and absent values with round-trip tests.

Changes

Objective scaling factor presence

Layer / File(s) Summary
Define optional field presence
cpp/src/grpc/cuopt_remote_service.proto, cpp/src/grpc/codegen/field_registry.yaml, cpp/src/grpc/codegen/FIELD_REGISTRY_REFERENCE.md
The chunked protobuf field and registry entry now use optional presence semantics, with documentation describing the preserved C++ default.
Apply and validate presence checks
cpp/src/grpc/codegen/generate_conversions.py, cpp/tests/linear_programming/grpc/grpc_client_test.cpp
Generated chunked conversions use presence guards for optional fields, with round-trip tests covering absent and explicit values.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: ramakrishnap-nv, nguidotti

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: making objective_scaling_factor optional for gRPC.
Description check ✅ Passed The description matches the change and explains the default-preservation issue caused by omitted proto3 fields.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
cpp/src/grpc/codegen/field_registry.yaml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'


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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cpp/tests/linear_programming/grpc/grpc_client_test.cpp`:
- Around line 1860-1905: Extend UnaryProblemObjectiveScalingPresence and
ChunkedProblemObjectiveScalingPresence with explicit-zero cases: set
objective_scaling_factor to 0, verify the field is present, and assert mapping
follows the existing invalid-value behavior rather than defaulting to 1.0. Keep
the existing omission and 2.5 presence coverage unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b780aed9-f610-4ec1-b85c-cf49e8faf5fb

📥 Commits

Reviewing files that changed from the base of the PR and between d856342 and f3f25b4.

⛔ Files ignored due to path filters (3)
  • cpp/src/grpc/codegen/generated/cuopt_remote_data.proto is excluded by !**/generated/**
  • cpp/src/grpc/codegen/generated/generated_chunked_header_to_problem.inc is excluded by !**/generated/**
  • cpp/src/grpc/codegen/generated/generated_proto_to_problem.inc is excluded by !**/generated/**
📒 Files selected for processing (5)
  • cpp/src/grpc/codegen/FIELD_REGISTRY_REFERENCE.md
  • cpp/src/grpc/codegen/field_registry.yaml
  • cpp/src/grpc/codegen/generate_conversions.py
  • cpp/src/grpc/cuopt_remote_service.proto
  • cpp/tests/linear_programming/grpc/grpc_client_test.cpp

Comment on lines +1860 to +1905
TEST(MapperRoundtrip, UnaryProblemObjectiveScalingPresence)
{
cuopt::remote::OptimizationProblem omitted;
omitted.add_c(0.0);
omitted.add_variable_lower_bounds(0.0);
omitted.add_variable_upper_bounds(1.0);
ASSERT_FALSE(omitted.has_objective_scaling_factor());

cpu_optimization_problem_t<int32_t, double> restored_default;
map_proto_to_problem(omitted, restored_default);
EXPECT_DOUBLE_EQ(restored_default.get_objective_scaling_factor(), 1.0);

cpu_optimization_problem_t<int32_t, double> orig;
const std::vector<double> objective{0.0};
const std::vector<double> lower_bound{0.0};
const std::vector<double> upper_bound{1.0};
orig.set_objective_coefficients(objective.data(), objective.size());
orig.set_variable_lower_bounds(lower_bound.data(), lower_bound.size());
orig.set_variable_upper_bounds(upper_bound.data(), upper_bound.size());
orig.set_objective_scaling_factor(2.5);
cuopt::remote::OptimizationProblem present;
map_problem_to_proto(orig, &present);
ASSERT_TRUE(present.has_objective_scaling_factor());
EXPECT_DOUBLE_EQ(present.objective_scaling_factor(), 2.5);

cpu_optimization_problem_t<int32_t, double> restored_present;
map_proto_to_problem(present, restored_present);
EXPECT_DOUBLE_EQ(restored_present.get_objective_scaling_factor(), 2.5);
}

TEST(MapperRoundtrip, ChunkedProblemObjectiveScalingPresence)
{
cuopt::remote::ChunkedProblemHeader omitted;
ASSERT_FALSE(omitted.has_objective_scaling_factor());

cpu_optimization_problem_t<int32_t, double> restored_default;
map_chunked_header_to_problem(omitted, restored_default);
EXPECT_DOUBLE_EQ(restored_default.get_objective_scaling_factor(), 1.0);

omitted.set_objective_scaling_factor(2.5);
ASSERT_TRUE(omitted.has_objective_scaling_factor());

cpu_optimization_problem_t<int32_t, double> restored_present;
map_chunked_header_to_problem(omitted, restored_present);
EXPECT_DOUBLE_EQ(restored_present.get_objective_scaling_factor(), 2.5);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add regression coverage for an explicitly set zero.

These tests cover omission and 2.5, but not the required boundary case where objective_scaling_factor is explicitly set to 0; add unary and chunked assertions that this present value follows the existing invalid-value path rather than being treated as absent and defaulting to 1.0.

As per path instructions, mapper tests should cover negative cases and the specific bug-fix regression. The PR objective requires explicit 0 to remain invalid.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/tests/linear_programming/grpc/grpc_client_test.cpp` around lines 1860 -
1905, Extend UnaryProblemObjectiveScalingPresence and
ChunkedProblemObjectiveScalingPresence with explicit-zero cases: set
objective_scaling_factor to 0, verify the field is present, and assert mapping
follows the existing invalid-value behavior rather than defaulting to 1.0. Keep
the existing omission and 2.5 presence coverage unchanged.

Source: Path instructions

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown

CI Test Summary

✅ All 31 test job(s) passed.

This coupled with a presence check adjusts for
the proto3 default 0 on omission of non-optional fields,
which differs from the cuopt default of 1.
@tmckayus
tmckayus force-pushed the fix/grpc-objective-scaling-presence branch from f3f25b4 to b3790ef Compare July 22, 2026 15:09
@copy-pr-bot

copy-pr-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@tmckayus

Copy link
Copy Markdown
Contributor Author

/ok to test b3790ef

@tmckayus

Copy link
Copy Markdown
Contributor Author

/merge

@rapids-bot
rapids-bot Bot merged commit ac1fd96 into NVIDIA:main Jul 22, 2026
92 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants