From 30b2b8944f0d0fb8ff6b69b72dfe0a0a007c1201 Mon Sep 17 00:00:00 2001 From: Corentin Le Molgat Date: Thu, 18 Jan 2024 14:18:42 +0100 Subject: [PATCH] math_opt: Sync from google3 --- .../math_opt/core/c_api/cpp_example_test.py | 6 +-- .../core/python/solver_gurobi_test.py | 6 +-- ortools/math_opt/core/python/solver_test.py | 4 +- ortools/math_opt/cpp/BUILD.bazel | 2 + .../math_opt/python/ipc/remote_http_solve.py | 41 ++++++++++++++++--- ortools/math_opt/samples/cpp/BUILD.bazel | 34 +++++++++++---- .../cpp/advanced_linear_programming.cc | 2 +- 7 files changed, 74 insertions(+), 21 deletions(-) diff --git a/ortools/math_opt/core/c_api/cpp_example_test.py b/ortools/math_opt/core/c_api/cpp_example_test.py index 6177b4aadb..ca3516314e 100644 --- a/ortools/math_opt/core/c_api/cpp_example_test.py +++ b/ortools/math_opt/core/c_api/cpp_example_test.py @@ -17,7 +17,7 @@ This is done by running the program in a subprocess and then asserting against what was printed to standard out. """ -import unittest +from absl.testing import absltest from ortools.math_opt.examples import log_scraping from ortools.math_opt.testing import binary_testing @@ -25,7 +25,7 @@ from ortools.math_opt.testing import binary_testing class CppExampleTest( binary_testing.BinaryAssertions, log_scraping.LogScraping, - unittest.TestCase, + absltest.TestCase, ): def test_regression(self): result = self.assert_binary_succeeds("ortools/math_opt/core/c_api/cpp_example") @@ -40,4 +40,4 @@ class CppExampleTest( if __name__ == "__main__": - unittest.main() + absltest.main() diff --git a/ortools/math_opt/core/python/solver_gurobi_test.py b/ortools/math_opt/core/python/solver_gurobi_test.py index a63bef92f5..876e82ca05 100644 --- a/ortools/math_opt/core/python/solver_gurobi_test.py +++ b/ortools/math_opt/core/python/solver_gurobi_test.py @@ -15,7 +15,7 @@ import datetime import math -import unittest +from absl.testing import absltest from google3.third_party.pybind11_abseil.status import StatusNotOk from ortools.math_opt import infeasible_subsystem_pb2 from ortools.math_opt import model_pb2 @@ -94,7 +94,7 @@ def _expected_iis_success() -> ( class PybindComputeInfeasibleSubsystemTest( - compare_proto.MathOptProtoAssertions, unittest.TestCase + compare_proto.MathOptProtoAssertions, absltest.TestCase ): def test_compute_infeasible_subsystem_infeasible(self) -> None: iis_result = solver.compute_infeasible_subsystem( @@ -177,4 +177,4 @@ class PybindComputeInfeasibleSubsystemTest( if __name__ == "__main__": - unittest.main() + absltest.main() diff --git a/ortools/math_opt/core/python/solver_test.py b/ortools/math_opt/core/python/solver_test.py index 7d71132f74..f66f6d52c2 100644 --- a/ortools/math_opt/core/python/solver_test.py +++ b/ortools/math_opt/core/python/solver_test.py @@ -14,7 +14,7 @@ import threading from typing import Callable, Optional, Sequence -import unittest +from absl.testing import absltest from absl.testing import parameterized from pybind11_abseil.status import StatusNotOk from ortools.math_opt import callback_pb2 @@ -270,4 +270,4 @@ class PybindSolveInterrupterTest(parameterized.TestCase): if __name__ == "__main__": - unittest.main() + absltest.main() diff --git a/ortools/math_opt/cpp/BUILD.bazel b/ortools/math_opt/cpp/BUILD.bazel index 78b5efe112..78a3f11c79 100644 --- a/ortools/math_opt/cpp/BUILD.bazel +++ b/ortools/math_opt/cpp/BUILD.bazel @@ -277,6 +277,8 @@ cc_library( "//ortools/math_opt:sparse_containers_cc_proto", "//ortools/math_opt/storage:model_storage", "//ortools/util:status_macros", + "@com_google_absl//absl/algorithm:container", + "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_protobuf//:protobuf", diff --git a/ortools/math_opt/python/ipc/remote_http_solve.py b/ortools/math_opt/python/ipc/remote_http_solve.py index 663ef1a6d8..8e210f5ad7 100644 --- a/ortools/math_opt/python/ipc/remote_http_solve.py +++ b/ortools/math_opt/python/ipc/remote_http_solve.py @@ -14,7 +14,7 @@ """Solve MathOpt models via HTTP request to the OR API.""" import json -from typing import Optional, Tuple, List +from typing import List, Optional, Tuple from google.protobuf import json_format import requests from ortools.service.v1 import optimization_pb2 @@ -24,6 +24,7 @@ from ortools.math_opt.python.ipc import proto_converter _DEFAULT_DEADLINE_SEC = 10 _DEFAULT_ENDPOINT = "https://optimization.googleapis.com/v1/mathopt:solveMathOptModel" +_RELATIVE_TIME_BUFFER = 0.05 class OptimizationServiceError(Exception): @@ -47,7 +48,7 @@ def remote_http_solve( params: Optional configuration of the underlying solver. model_params: Optional configuration of the solver that is model specific. endpoint: An URI identifying the service for remote solves. - api_key: Tey to the OR API. + api_key: Key to the OR API. deadline_sec: The number of seconds before the request times out. Returns: @@ -64,8 +65,9 @@ def remote_http_solve( payload = _build_json_payload(model, solver_type, params, model_params) - response = requests.post( - url=f"{endpoint}?key={api_key}", + session = create_optimization_service_session(api_key, deadline_sec) + response = session.post( + url=endpoint, json=payload, timeout=deadline_sec, ) @@ -79,6 +81,35 @@ def remote_http_solve( return _build_solve_result(response.content, model) +def create_optimization_service_session( + api_key: str, + deadline_sec: float, +) -> requests.Session: + """Creates a session with the appropriate headers. + + This function sets headers for authentication via an API key, and it sets + deadlines set for the server and the connection. + + Args: + api_key: Key to the OR API. + deadline_sec: The number of seconds before the request times out. + + Returns: + requests.Session a session with the necessary headers to call the + optimization serive. + """ + session = requests.Session() + server_timeout = deadline_sec * (1 - _RELATIVE_TIME_BUFFER) + session.headers = { + "Content-Type": "application/json", + "Connection": "keep-alive", + "Keep-Alive": f"timeout={deadline_sec}, max=1", + "X-Server-Timeout": f"{server_timeout}", + "X-Goog-Api-Key": api_key, + } + return session + + def _build_json_payload( model: mathopt.Model, solver_type: mathopt.SolverType, @@ -140,7 +171,7 @@ def _build_solve_result( ) except json_format.ParseError as json_err: raise ValueError( - "api response is not a valid SolveMathOptModelResponse JSON" + "API response is not a valid SolveMathOptModelResponse JSON" ) from json_err response = proto_converter.convert_response(api_response) diff --git a/ortools/math_opt/samples/cpp/BUILD.bazel b/ortools/math_opt/samples/cpp/BUILD.bazel index a4a1abc351..1814b1c3cd 100644 --- a/ortools/math_opt/samples/cpp/BUILD.bazel +++ b/ortools/math_opt/samples/cpp/BUILD.bazel @@ -22,7 +22,6 @@ cc_binary( "//ortools/math_opt/cpp:math_opt", "//ortools/math_opt/solvers:gscip_solver", "@com_google_absl//absl/status", - "@com_google_absl//absl/status:statusor", ], ) @@ -36,7 +35,10 @@ cc_binary( "//ortools/math_opt/cpp:math_opt", "//ortools/math_opt/solvers:gscip_solver", "//ortools/util:status_macros", + "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", + "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", @@ -51,7 +53,7 @@ cc_binary( "//ortools/base:status_macros", "//ortools/math_opt/cpp:math_opt", "//ortools/math_opt/solvers:glop_solver", - "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", ], @@ -65,7 +67,7 @@ cc_binary( "//ortools/base:status_macros", "//ortools/math_opt/cpp:math_opt", "//ortools/math_opt/solvers:glop_solver", - "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", ], @@ -79,7 +81,7 @@ cc_binary( "//ortools/base:status_macros", "//ortools/math_opt/cpp:math_opt", "//ortools/math_opt/solvers:gscip_solver", - "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/status", "@com_google_absl//absl/time", ], ) @@ -93,8 +95,10 @@ cc_binary( "//ortools/math_opt/cpp:math_opt", "//ortools/math_opt/solvers:cp_sat_solver", "//ortools/math_opt/solvers:glop_solver", + "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", ], ) @@ -112,6 +116,7 @@ cc_binary( "//ortools/util:status_macros", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/memory", "@com_google_absl//absl/random", "@com_google_absl//absl/random:distributions", "@com_google_absl//absl/random:seed_sequences", @@ -120,6 +125,7 @@ cc_binary( "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/time", + "@com_google_absl//absl/types:span", ], ) @@ -135,7 +141,7 @@ cc_binary( "//ortools/math_opt/solvers:glop_solver", "//ortools/math_opt/solvers:gscip_solver", "@com_google_absl//absl/flags:flag", - "@com_google_absl//absl/memory", + "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", @@ -153,8 +159,12 @@ cc_binary( "//ortools/math_opt/solvers:gurobi_solver", "//ortools/math_opt/solvers:pdlp_solver", "@com_google_absl//absl/algorithm:container", + "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/log:check", "@com_google_absl//absl/random", "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", ], ) @@ -181,12 +191,16 @@ cc_binary( "//ortools/base", "//ortools/base:status_macros", "//ortools/math_opt/cpp:math_opt", + "//ortools/math_opt/solvers:gscip_solver", "//ortools/math_opt/solvers:gurobi_solver", - "//ortools/port:proto_utils", + "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/log:check", "@com_google_absl//absl/random", - "@com_google_absl//absl/random:distributions", + "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", + "@com_google_absl//absl/types:span", ], ) @@ -198,8 +212,10 @@ cc_binary( "//ortools/base:status_macros", "//ortools/math_opt/cpp:math_opt", "//ortools/math_opt/solvers:cp_sat_solver", + "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", ], ) @@ -214,9 +230,12 @@ cc_binary( "//ortools/math_opt/solvers:gscip_solver", "//ortools/math_opt/solvers:gurobi_solver", "@com_google_absl//absl/algorithm:container", + "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/log", "@com_google_absl//absl/random", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/types:span", ], ) @@ -227,6 +246,7 @@ cc_binary( "//ortools/base", "//ortools/base:status_macros", "//ortools/math_opt/cpp:math_opt", + "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/status", ], ) diff --git a/ortools/math_opt/samples/cpp/advanced_linear_programming.cc b/ortools/math_opt/samples/cpp/advanced_linear_programming.cc index 1b3b4c5799..4bf0493a5e 100644 --- a/ortools/math_opt/samples/cpp/advanced_linear_programming.cc +++ b/ortools/math_opt/samples/cpp/advanced_linear_programming.cc @@ -19,7 +19,7 @@ #include #include -#include "absl/status/statusor.h" +#include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "absl/time/time.h"