Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/cuopt/source/cuopt-grpc/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ See :doc:`python-async-client` for the full job API.
Limitations and Scope
=====================

* **Problem types** — **LP**, **MIP**, and **QP** are supported on the gRPC remote path. **Routing** (VRP, TSP, PDP) is **not** supported yet; use the :doc:`REST self-hosted server <../cuopt-server/index>` for remote routing until a future release adds routing over ``CuOptRemoteService``.
* **Problem types** — **LP**, **MIP**, and **QP** support both remote execution and gRPC clients. **Routing** (VRP, TSP, PDP) supports the explicit :doc:`VRP gRPC client <routing>` only; there is no ``CUOPT_REMOTE_HOST``/``CUOPT_REMOTE_PORT`` remote-execution path for routing yet, and the client has no log/incumbent streaming (see :ref:`Limitations and Roadmap <cuopt-grpc-routing-limitations>`). The :doc:`REST self-hosted server <../cuopt-server/index>` is also available for remote routing.
* **Message size** — Large problems use chunking; very large models can still hit gRPC max message / timeout limits. Tune ``CUOPT_CHUNK_SIZE``, ``CUOPT_MAX_MESSAGE_BYTES``, server ``--max-message-mb``, and solver ``time_limit`` as needed.
* **``CUOPT_GRPC_ARGS``** — Parsed on whitespace only; arguments containing spaces are awkward unless you invoke ``cuopt_grpc_server`` directly.
* **CRL / OCSP** — Not handled by the integrated gRPC TLS stack; use a private CA rotation strategy or a TLS-terminating proxy if you need revocation workflows.
Expand Down
13 changes: 9 additions & 4 deletions docs/cuopt/source/cuopt-grpc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,15 @@ Streaming and Callbacks
Messages and Constraints
========================

* **Problem types** — Wire categories are LP/QP or MIP. QP is submitted as
``lp_request`` (``SolveLPRequest``) with quadratic fields on
``OptimizationProblem``. **Routing** over this gRPC service is **not**
available yet (planned; use REST for remote routing today).
* **Problem types** — Wire categories are LP/QP, MIP, or VRP. QP is submitted
as ``lp_request`` (``SolveLPRequest``) with quadratic fields on
``OptimizationProblem``. **VRP** rides the same ``SubmitJob``/``GetResult``
RPCs as LP/MIP, as a ``vrp_request`` payload typed by
``cpp/src/grpc/routing/cuopt_routing.proto`` (problem) and
``cuopt_routing_solution.proto`` (result) -- not a separate service. There
is no ``CUOPT_REMOTE_HOST``/``CUOPT_REMOTE_PORT`` remote-execution path for
routing yet; use ``cuopt.grpc.routing.RoutingClient`` (:doc:`routing`) or
REST for remote routing today.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
* **Solver settings** — Carried as ``PDLPSolverSettings`` or ``MIPSolverSettings`` inside the request or chunked header, aligned with the NVIDIA cuOpt solver options documentation.
* **Errors** — Transport failures use gRPC status codes. Some outcomes use
``Status::OK`` with response fields: ``CheckStatus`` reports unknown jobs as
Expand Down
16 changes: 15 additions & 1 deletion docs/cuopt/source/cuopt-grpc/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ Add TLS or tuning variables from :doc:`advanced` if your deployment uses them.

.. note::

Routing solve over gRPC is not supported. For solving routing problems remotely today, use the HTTP/JSON :doc:`REST self-hosted server <../cuopt-server/index>` and :doc:`Examples <../cuopt-server/examples/index>`.
Routing has no remote-execution path over gRPC -- use the explicit
:ref:`VRP gRPC client <cuopt-grpc-examples-routing>` below, or the
HTTP/JSON :doc:`REST self-hosted server <../cuopt-server/index>` and
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
:doc:`Examples <../cuopt-server/examples/index>`.

Where to Find Examples
======================
Expand Down Expand Up @@ -70,6 +73,17 @@ without ``CUOPT_REMOTE_*``, use ``cuopt.grpc.linear_programming.Client``:
* :doc:`python-async-client-examples` — log streaming and incumbent streaming
* :doc:`python-async-client-api` — API reference

Routing (VRP)
-------------

.. _cuopt-grpc-examples-routing:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

could we have a sample response here? I think we add it for other example files

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added — routing.rst's Connect and Solve section now has a sample-output block right after the demo's literalinclude, matching the convention from cuopt-python/routing/routing-examples.rst's TSP batch example. Labeled as illustrative rather than a captured run, since there's no GPU in this environment to actually execute it against, and VRP status/objective/route order aren't guaranteed stable across runs.


For VRP, TSP, and PDP problems, use ``cuopt.grpc.routing.RoutingClient`` --
the same submit / wait / result / delete lifecycle, with no
``CUOPT_REMOTE_*`` equivalent yet:

* :doc:`routing` — overview, API reference, and :download:`remote_routing_demo.py <examples/remote_routing_demo.py>`

Custom gRPC Client
------------------

Expand Down
43 changes: 43 additions & 0 deletions docs/cuopt/source/cuopt-grpc/examples/remote_routing_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""Minimal VRP demo for the NVIDIA cuOpt VRP gRPC client.

Unlike LP/MIP, routing has no ``CUOPT_REMOTE_HOST``/``CUOPT_REMOTE_PORT``
transparent path yet -- build a :class:`cuopt.routing.DataModel` and solve it
with :class:`cuopt.grpc.routing.RoutingClient`, an explicit client (host and
port passed directly).

Start the server first::

cuopt_grpc_server --port 5001 --workers 1

Then::

python remote_routing_demo.py
"""

import numpy as np
from cuopt import routing
from cuopt.grpc.routing import RoutingClient

dm = routing.DataModel(5, 2)
cost_matrix = np.array(
[
[0, 1, 2, 2, 1],
[1, 0, 1, 2, 2],
[2, 1, 0, 1, 2],
[2, 2, 1, 0, 1],
[1, 2, 2, 1, 0],
],
dtype=np.float32,
)
dm.add_cost_matrix(cost_matrix)

client = RoutingClient("localhost:5001")
solution = client.solve(dm, {"time_limit": 5.0})

print("Status: ", solution["status_message"])
print("Vehicles: ", solution["vehicle_count"])
print("Objective: ", solution["total_objective_value"])
print("Route: ", solution["route"])
27 changes: 18 additions & 9 deletions docs/cuopt/source/cuopt-grpc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,25 @@ NVIDIA cuOpt can run LP, MIP, and QP solves on a remote GPU host through
**gRPC clients** (explicit client)
Your program opens a gRPC connection and manages jobs itself. Use the
:doc:`Python async gRPC client <python-async-client>`
(``cuopt.grpc.linear_programming.Client``) for job management, or speak
``CuOptRemoteService`` directly from a custom client (:doc:`api`).
(``cuopt.grpc.linear_programming.Client``) for LP/MIP/QP job management, the
:doc:`VRP gRPC client <routing>` (``cuopt.grpc.routing.RoutingClient``) for
routing, or speak ``CuOptRemoteService`` directly from a custom client
(:doc:`api`).

In this section, **remote execution** always means the zero-code-change path
above. When talking about programs that construct a client and call gRPC
themselves, we say **gRPC client**.

.. note::

**Problem types:** LP, MIP, and QP are supported today. **Routing** (VRP,
TSP, PDP, and related APIs) over gRPC is **not** available yet; support is
planned for an **upcoming** release. For remote routing today, use the
HTTP/JSON :doc:`REST self-hosted server <../cuopt-server/index>`.
**Problem types:** LP, MIP, and QP support both remote execution and
gRPC clients. **Routing** (VRP, TSP, PDP) supports the explicit
:doc:`VRP gRPC client <routing>` only -- there is no
``CUOPT_REMOTE_HOST``/``CUOPT_REMOTE_PORT`` remote-execution path for
routing yet (tracked in `#1633
<https://github.com/NVIDIA/cuopt/issues/1633>`_). The HTTP/JSON
:doc:`REST self-hosted server <../cuopt-server/index>` is also available
for remote routing.

This is **not** the HTTP/JSON :doc:`REST self-hosted server <../cuopt-server/index>`
(FastAPI). REST is for arbitrary HTTP clients; gRPC serves remote execution
Expand All @@ -43,13 +49,15 @@ When to Choose Which Path
scripts and APIs as a local solve.
* **Python async gRPC client** — explicit job control: submit now, wait or
poll later, cancel, stream solver logs, stream MIP incumbents.
* **VRP gRPC client** — explicit job control for routing (submit / wait /
result / delete); no remote execution or streaming yet.
* **Custom ``CuOptRemoteService`` client** — non-Python (or fully custom)
integrations that speak the protos directly. See :doc:`api`.

Start with :doc:`quick-start` (install, server, and a minimal LP). Use
:doc:`python-async-client` for the Python gRPC client; :doc:`advanced` for
TLS, Docker, environment variables, and troubleshooting; :doc:`examples` for
additional patterns.
:doc:`python-async-client` for the LP/MIP/QP gRPC client, :doc:`routing` for
the VRP gRPC client; :doc:`advanced` for TLS, Docker, environment variables,
and troubleshooting; :doc:`examples` for additional patterns.

.. toctree::
:maxdepth: 2
Expand All @@ -60,6 +68,7 @@ additional patterns.
python-async-client.rst
python-async-client-examples.rst
python-async-client-api.rst
routing.rst
advanced.rst
examples.rst
api.rst
Expand Down
10 changes: 6 additions & 4 deletions docs/cuopt/source/cuopt-grpc/quick-start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ directly (see :doc:`api`).

.. note::

**Problem types:** **LP**, **MIP**, and **QP** are supported today.
**Routing** (VRP, TSP, PDP) over gRPC is **not** available; for remote
routing, use the HTTP/JSON :doc:`REST self-hosted server <../cuopt-server/index>`.
This guide is **not** the REST server.
**Problem types:** **LP**, **MIP**, and **QP** support remote execution
(this guide) and gRPC clients. **Routing** (VRP, TSP, PDP) supports the
explicit :doc:`VRP gRPC client <routing>` only -- there is no remote
execution path for routing yet. The HTTP/JSON
:doc:`REST self-hosted server <../cuopt-server/index>` is also available
for remote routing. This guide is **not** the REST server.

How Remote Execution Works
==========================
Expand Down
154 changes: 154 additions & 0 deletions docs/cuopt/source/cuopt-grpc/routing.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
..
SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: Apache-2.0

=============================
VRP gRPC Client (Routing)
=============================

``cuopt.grpc.routing.RoutingClient`` is an explicit gRPC client for solving
**VRP** (vehicle routing, including TSP and PDP) problems on
``cuopt_grpc_server``. It uses the same job lifecycle as the LP/MIP
:doc:`Python async gRPC client <python-async-client>`: **submit** → **wait**
→ **result** → **delete**, plus a **solve** convenience method that does all
four.

There is no ``CUOPT_REMOTE_HOST``/``CUOPT_REMOTE_PORT`` transparent path for
routing yet (unlike LP/MIP/QP) -- always construct ``RoutingClient`` with an
explicit host and port. See :ref:`Limitations and Roadmap
<cuopt-grpc-routing-limitations>` below.

Prerequisites
=============

A running ``cuopt_grpc_server`` on a GPU host (see :doc:`quick-start`):

.. code-block:: bash

cuopt_grpc_server --port 5001 --workers 1

Connect and Solve
==================

.. code-block:: python

import numpy as np
from cuopt import routing
from cuopt.grpc.routing import RoutingClient

dm = routing.DataModel(5, 2)
cost_matrix = np.array(
[
[0, 1, 2, 2, 1],
[1, 0, 1, 2, 2],
[2, 1, 0, 1, 2],
[2, 2, 1, 0, 1],
[1, 2, 2, 1, 0],
],
dtype=np.float32,
)
dm.add_cost_matrix(cost_matrix)

client = RoutingClient("localhost:5001")
solution = client.solve(dm, {"time_limit": 5.0})

print(solution["status_message"])
print(solution["total_objective_value"])
print(solution["route"])

``RoutingClient.submit()`` accepts a :class:`cuopt.routing.DataModel` built
the same way as for a local :func:`cuopt.routing.Solve`. ``solve()`` submits,
waits, and deletes the job's server-side state when done (pass
``delete=False`` to keep it around for a later ``result()`` call).

:download:`remote_routing_demo.py <examples/remote_routing_demo.py>`

.. literalinclude:: examples/remote_routing_demo.py
:language: python
:linenos:

Job Lifecycle
=============

* ``submit(data_model, settings=None)`` — serializes the problem and settings, returns a ``job_id``.
* ``wait(job_id, timeout=0)`` — blocks until the job reaches a terminal state; returns the status.
* ``result(job_id)`` — returns the solution dict, or ``None`` if the job has not finished.
* ``delete(job_id)`` — releases the job's server-side result.
* ``solve(data_model, settings=None, *, timeout=0, delete=True)`` — submit + wait + result, deleting the job afterward unless ``delete=False``.

A failed or non-completed job raises ``RoutingSolveError`` from ``submit``,
``wait``, or ``solve``.

Settings
========

``settings`` accepts a ``dict`` or a :class:`cuopt.routing.SolverSettings`.
Today only ``time_limit`` is forwarded to the remote solve; other
``SolverSettings`` options (``verbose``, ``error_logging``,
``dump_best_results_path``/``interval``) are not yet mapped over gRPC (see
:ref:`Limitations and Roadmap <cuopt-grpc-routing-limitations>`).

Solution Fields
================

``result()`` and ``solve()`` return a ``dict`` with the same fields as a
local :class:`cuopt.routing.Assignment`, read directly off the wire:

.. list-table::
:header-rows: 1

* - Key
- Description
* - ``status`` / ``status_message``
- Integer and human-readable solve status.
* - ``error_message``
- Set when the solve failed.
* - ``vehicle_count``
- Number of vehicles used.
* - ``total_objective_value`` / ``objective_values``
- Overall cost and the per-objective breakdown.
* - ``route``, ``truck_id``, ``locations``, ``node_types``, ``arrival_stamp``
- Per-stop route arrays, one entry per stop across all vehicles.
* - ``unserviced_nodes``
- Orders that could not be served.
Comment thread
ramakrishnap-nv marked this conversation as resolved.
Outdated
* - ``accepted``
- Orders accepted, for prize-collection problems.

.. _cuopt-grpc-routing-limitations:

Limitations and Roadmap
=========================

* **No transparent remote execution** — routing does not read
``CUOPT_REMOTE_HOST``/``CUOPT_REMOTE_PORT``; always pass host and port to
``RoutingClient`` explicitly. Tracked in `#1633
<https://github.com/NVIDIA/cuopt/issues/1633>`_.
* **Settings surface** — only ``time_limit`` is forwarded today. Tracked in
`#1632 <https://github.com/NVIDIA/cuopt/issues/1632>`_.
* **No log or incumbent streaming** — unlike the LP/MIP client, there is no
``start_log_stream``/``start_incumbent_stream`` equivalent yet. Tracked in
`#1630 <https://github.com/NVIDIA/cuopt/issues/1630>`_.
* **Input validation** — malformed problems may fail late or with a generic
error rather than an early, descriptive one. Tracked in `#1631
<https://github.com/NVIDIA/cuopt/issues/1631>`_.

API Reference
=============

Import path: ``cuopt.grpc.routing``.

.. autoclass:: cuopt.grpc.routing.RoutingClient
:members:
:undoc-members:

.. autoexception:: cuopt.grpc.routing.RoutingSolveError
:members:
:show-inheritance:

See Also
========

* :doc:`index` — when to use gRPC vs. the REST self-hosted server
* :doc:`python-async-client` — the LP/MIP/QP equivalent client
* :doc:`api` — how VRP rides ``CuOptRemoteService``'s RPCs
* :doc:`../cuopt-python/routing/index` — the local routing Python API
Loading