Send a batchOptimizeTours Request

This example shows how to solve the VRP example by sending an asynchronous request to the Fleet Routing Service. If you encounter an IAM permission error, make sure to add proper IAM roles to your service account by following Before You Begin.

REST

The following example sends an optimization request to Cloud Fleet Routing API and creates a solution in Google Cloud Storage.

Before using any of the request data, make the following replacements:

  • project-id: your GCP project ID.
  • model-google-cloud-storage-uri: The Google Cloud Storage URI for the model to be solved, e.g. gs://foo-service/model.json.
  • solution-google-cloud-storage-uri: The Google Cloud Storage URI for the solution generated, e.g. gs://foo-service/solution.json..

HTTP method and URL:

POST https://cloudoptimization.googleapis.com/v1/projects/project-id:batchOptimizeTours

Request JSON body:

{
  "parent": "projects/project-id",
  "model_configs":[
      {
         "input_config":{
            "gcs_source":{
                "uri":"model-google-cloud-storage-uri"
            },
            "data_format":"JSON"
         },
         "output_config":{
            "gcs_destination":{
               "uri":"solution-google-cloud-storage-uri"
            },
            "data_format":"JSON"
         }
      }
   ]
}

To send your request, choose one of these options:

curl

Save the request body in a file named request.json, and execute the following command:

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "x-goog-user-project: project-id" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://cloudoptimization.googleapis.com/v1/projects/project-id:batchOptimizeTours"

PowerShell

Save the request body in a file named request.json, and execute the following command:

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred"; "x-goog-user-project" = "project-id" }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://cloudoptimization.googleapis.com/v1/projects/project-id:batchOptimizeTours" | Select-Object -Expand Content

You should see output similar to the following. You can use the operation ID (7781633313341553605, in this case) to get the status of the task. For an example, see Working with long-running operations:

{
  "name": "projects/project-id/operations/7781633313341553605",
}

After the long-running operation completes you can find the generated solution in the Google Cloud Storage you specified in your request with solution-google-cloud-storage-uri. In this example, we only specified one model config so it only generates one solution and it is worthwhile to mention that you can specify multiple model configs. The solution should look similar to the following:

{
  "routes": [
    {
      "vehicleStartTime": "1970-01-01T00:02:11Z",
      "vehicleEndTime": "1970-01-01T01:15:34Z",
      "visits": [
        {
          "isPickup": true,
          "startTime": "1970-01-01T00:16:40Z",
          "detour": "0s",
          "arrivalLoads": [
            {
              "type": "weight"
            }
          ]
        },
        {
          "shipmentIndex": 1,
          "isPickup": true,
          "startTime": "1970-01-01T00:27:35Z",
          "detour": "725s",
          "arrivalLoads": [
            {
              "type": "weight",
              "value": "10"
            }
          ]
        },
        {
          "startTime": "1970-01-01T00:50:00Z",
          "detour": "1345s",
          "arrivalLoads": [
            {
              "type": "weight",
              "value": "30"
            }
          ]
        },
        {
          "shipmentIndex": 1,
          "startTime": "1970-01-01T00:58:43Z",
          "detour": "1444s",
          "arrivalLoads": [
            {
              "type": "weight",
              "value": "20"
            }
          ]
        }
      ],
      "travelSteps": [
        {
          "duration": "869s",
          "distanceMeters": 4243
        },
        {
          "duration": "505s",
          "distanceMeters": 2480
        },
        {
          "duration": "0s"
        },
        {
          "duration": "273s",
          "distanceMeters": 986
        },
        {
          "duration": "760s",
          "distanceMeters": 3099
        }
      ],
      "vehicleDetour": "4403s",
      "endLoads": [
        {
          "type": "weight"
        }
      ],
      "transitions": [
        {
          "travelDuration": "869s",
          "travelDistanceMeters": 4243,
          "loads": [
            {
              "type": "weight"
            }
          ]
        },
        {
          "travelDuration": "505s",
          "travelDistanceMeters": 2480,
          "loads": [
            {
              "type": "weight",
              "value": "10"
            }
          ]
        },
        {
          "travelDuration": "0s",
          "loads": [
            {
              "type": "weight",
              "value": "30"
            }
          ]
        },
        {
          "travelDuration": "273s",
          "travelDistanceMeters": 986,
          "loads": [
            {
              "type": "weight",
              "value": "20"
            }
          ]
        },
        {
          "travelDuration": "760s",
          "travelDistanceMeters": 3099,
          "loads": [
            {
              "type": "weight"
            }
          ]
        }
      ]
    },
    {
      "vehicleIndex": 1,
      "vehicleStartTime": "1970-01-01T00:00:00Z",
      "vehicleEndTime": "1970-01-01T00:00:00Z",
      "vehicleDetour": "0s"
    }
  ]
}

Java

Before trying this sample, follow the setup instructions for this language on the Client Libraries page.

import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.optimization.v1.AsyncModelMetadata;
import com.google.cloud.optimization.v1.BatchOptimizeToursRequest;
import com.google.cloud.optimization.v1.BatchOptimizeToursRequest.AsyncModelConfig;
import com.google.cloud.optimization.v1.BatchOptimizeToursResponse;
import com.google.cloud.optimization.v1.DataFormat;
import com.google.cloud.optimization.v1.FleetRoutingClient;
import com.google.cloud.optimization.v1.GcsDestination;
import com.google.cloud.optimization.v1.GcsSource;
import com.google.cloud.optimization.v1.InputConfig;
import com.google.cloud.optimization.v1.OutputConfig;

/**
 * This is an example to send a request to Cloud Fleet Routing asynchronous API via Java API Client.
 * A sample async_request_java.textproto file and a sample request_model_java.json file can be found
 * in the resources folder.
 */
public class AsyncApi {
  public static void callAsyncApi() throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectParent = "projects/{YOUR_GCP_PROJECT_ID}";
    String inputUri = "gs://YOUR_GCS_PATH";
    String outputUri = "gs://YOUR_SOLUTION_PATH";
    callAsyncApi(projectParent, inputUri, outputUri);
  }

  public static void callAsyncApi(String projectParent, String inputUri, String outputUri)
      throws Exception {
    GcsSource gcsSource = GcsSource.newBuilder().setUri(inputUri).build();
    InputConfig inputConfig =
        InputConfig.newBuilder().setGcsSource(gcsSource).setDataFormat(DataFormat.JSON).build();
    GcsDestination gcsDestination = GcsDestination.newBuilder().setUri(outputUri).build();
    OutputConfig outputConfig =
        OutputConfig.newBuilder()
            .setGcsDestination(gcsDestination)
            .setDataFormat(DataFormat.JSON)
            .build();

    AsyncModelConfig asyncModelConfig =
        AsyncModelConfig.newBuilder()
            .setInputConfig(inputConfig)
            .setOutputConfig(outputConfig)
            .build();
    BatchOptimizeToursRequest request =
        BatchOptimizeToursRequest.newBuilder()
            .setParent(projectParent)
            .addModelConfigs(asyncModelConfig)
            .build();

    FleetRoutingClient fleetRoutingClient = FleetRoutingClient.create();
    OperationFuture<BatchOptimizeToursResponse, AsyncModelMetadata> response =
        fleetRoutingClient.batchOptimizeToursAsync(request);
    System.out.format("the response name: %s\n", response.getInitialFuture().get().getName());

    // Block to wait for the job to finish.
    response.getPollingFuture().get();
    if (response.getMetadata().get().getState() == AsyncModelMetadata.State.SUCCEEDED) {
      // Code to do your stuff
      System.out.println("Job finished successfully.");
    } else {
      System.out.println(
          "Job failed with message:" + response.getPollingFuture().get().getErrorMessage());
    }
  }
}

Python

Before trying this sample, follow the setup instructions for this language on the Client Libraries page.


from google.api_core.exceptions import GoogleAPICallError
from google.cloud import optimization_v1

# TODO(developer): Uncomment these variables before running the sample.
# project_id= 'YOUR_PROJECT_ID'
# request_file_name = 'YOUR_REQUEST_FILE_NAME'
# request_model_gcs_path = 'gs://YOUR_PROJECT/YOUR_BUCKET/YOUR_REQUEST_MODEL_PATH'
# model_solution_gcs_path = 'gs://YOUR_PROJECT/YOUR_BUCKET/YOUR_SOLUCTION_PATH'


def call_async_api(
    project_id: str, request_model_gcs_path: str, model_solution_gcs_path_prefix: str
) -> None:
    """Call the async api for fleet routing."""
    # Use the default credentials for the environment to authenticate the client.
    fleet_routing_client = optimization_v1.FleetRoutingClient()
    request_file_name = "resources/async_request.json"

    with open(request_file_name) as f:
        fleet_routing_request = optimization_v1.BatchOptimizeToursRequest.from_json(
            f.read()
        )
        fleet_routing_request.parent = f"projects/{project_id}"
        for idx, mc in enumerate(fleet_routing_request.model_configs):
            mc.input_config.gcs_source.uri = request_model_gcs_path
            model_solution_gcs_path = f"{model_solution_gcs_path_prefix}_{idx}"
            mc.output_config.gcs_destination.uri = model_solution_gcs_path

        # The timeout argument for the gRPC call is independent from the `timeout`
        # field in the request's OptimizeToursRequest message(s).
        operation = fleet_routing_client.batch_optimize_tours(fleet_routing_request)
        print(operation.operation.name)

        try:
            # Block to wait for the job to finish.
            result = operation.result()
            print(result)
            # Do you stuff.
        except GoogleAPICallError:
            print(operation.operation.error)

Working with long-running operations

You can get the status of a long-running operation by using the following code samples.

REST

Before using any of the request data, make the following replacements:

  • project-id: your GCP project ID.
  • operation-id: the ID of your operation. The ID is the last element of the name of your operation. For example:
    • operation name: projects/project-id/operations/7781633313341553605
    • operation id: 7781633313341553605

HTTP method and URL:

GET https://cloudoptimization.googleapis.com/v1/projects/project-id/operations/operation-id

To send your request, choose one of these options:

curl

Execute the following command:

curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "x-goog-user-project: project-id" \
"https://cloudoptimization.googleapis.com/v1/projects/project-id/operations/operation-id"

PowerShell

Execute the following command:

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred"; "x-goog-user-project" = "project-id" }

Invoke-WebRequest `
-Method GET `
-Headers $headers `
-Uri "https://cloudoptimization.googleapis.com/v1/projects/project-id/operations/operation-id" | Select-Object -Expand Content
You should see output similar to the following for a completed batchOptimizeTours request:
{
  "name":  "projects/project-id/operations/operation-id",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.optimization.v1.AsyncModelMetadata",
    "state": "SUCCEEDED",
    "createTime": "2022-04-01T20:35:36.416835Z",
    "updateTime": "2022-04-01T20:35:37.906284Z"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.optimization.v1.BatchOptimizeToursResponse"
  }
}

Java

Before trying this sample, follow the set up instructions for this language on the APIs & Reference > Client Libraries page.

import com.google.cloud.optimization.v1.FleetRoutingClient;
import com.google.longrunning.Operation;
import java.io.IOException;

class GetOperation {

  static void getOperation() throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String operationFullId = "projects/[projectId]/operations/[operationId]";
    getOperation(operationFullId);
  }

  // Get the status of an operation
  static void getOperation(String operationFullId) throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources.
    try (FleetRoutingClient client = FleetRoutingClient.create()) {
      // Get the latest state of a long-running operation.
      Operation operation = client.getOperationsClient().getOperation(operationFullId);

      // Display operation details.
      System.out.println("Operation details:");
      System.out.format("\tName: %s\n", operation.getName());
      System.out.format("\tMetadata Type Url: %s\n", operation.getMetadata().getTypeUrl());
      System.out.format("\tDone: %s\n", operation.getDone());
      if (operation.hasResponse()) {
        System.out.format("\tResponse Type Url: %s\n", operation.getResponse().getTypeUrl());
      }
      if (operation.hasError()) {
        System.out.println("\tResponse:");
        System.out.format("\t\tError code: %s\n", operation.getError().getCode());
        System.out.format("\t\tError message: %s\n", operation.getError().getMessage());
      }
    }
  }
}

Python

Before trying this sample, follow the set up instructions for this language on the APIs & Reference > Client Libraries page.

from google.cloud import optimization_v1


def get_operation(operation_full_id: str) -> None:
    """Get operation details and status."""
    # TODO(developer): Uncomment and set the following variables
    # operation_full_id = \
    #     "projects/[projectId]/operations/[operationId]"

    client = optimization_v1.FleetRoutingClient()
    # Get the latest state of a long-running operation.
    response = client.transport.operations_client.get_operation(operation_full_id)

    print(f"Name: {response.name}")
    print("Operation details:")
    print(response)