Skip to content

[BUG] Copy-out solution accessors cannot distinguish "no data" from "data is all zeros" #1706

Description

@ramakrishnap-nv

Describe the bug

Several C API copy-out accessors write into a caller-sized buffer and report no length. When the underlying data is empty, they copy nothing, return CUOPT_SUCCESS, and leave the caller's buffer at whatever it was initialised to. "Not available" is therefore indistinguishable from "all zeros".

cuOptGetDualSolution and cuOptGetReducedCosts are the clearest cases:

const auto reduced_cost_host = solution_and_stream_view->get_solution()->get_reduced_costs();
std::memcpy(reduced_cost_ptr, reduced_cost_host.data(),
            reduced_cost_host.size() * sizeof(cuopt_float_t));
return CUOPT_SUCCESS;

get_reduced_cost_host() returns an empty vector when the solve produced no reduced costs — an infeasible LP, for instance. The memcpy then copies zero bytes and the function still reports success.

Steps/Code to reproduce bug

Solve an infeasible LP, then:

cuopt_float_t reduced_costs[n];
for (int i = 0; i < n; ++i) reduced_costs[i] = 0.0;
cuOptGetReducedCosts(solution, reduced_costs);   /* CUOPT_SUCCESS, buffer untouched */

The caller cannot tell this from a solve whose reduced costs are genuinely all zero.

This was hit in practice in #1524. Moving the Java bindings onto cuOptGetReducedCosts turned "no reduced costs" into "all reduced costs are zero", which surfaced as a test failure (ProblemIntegrationTest.problemsBuildAndSolve[10]); the change had to be reverted and the bindings left on the internal C++ interface, which does report the real length.

Expected behavior

A caller should be able to tell "unavailable" from "available and zero" — either a length out-parameter, a separate size query, or a distinct status code when the data is absent.

Additional context

cuOptGetProblemStringArrayAttribute has a related shape problem in the other direction: it requires count to equal the stored name count exactly and returns CUOPT_INVALID_ARGUMENT otherwise, so a problem with no names set cannot be distinguished from a bad argument, and there is no size query to ask first.

Raised by @mlubin in #1703, where the point was correctly made that this is a C API behaviour issue to fix rather than a reason to give Java a special interface. Splitting it out of that issue so it can be fixed on its own terms.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions