11from __future__ import annotations
22
33from collections .abc import AsyncIterator , Iterable , Mapping , Sequence
4+ import dataclasses
45import json
56import logging
67from typing import Any , BinaryIO
@@ -259,9 +260,7 @@ async def register_specification(
259260 tag_name = tag_names [0 ] if tag_names else None ,
260261 )
261262
262- async def _prepare_problem (
263- self , problem : Problem
264- ) -> tuple [Json , ProblemOutline ]:
263+ async def _prepare_problem (self , problem : Problem ) -> _PreparedProblem :
265264 """Generates solve problem and final outline."""
266265 # First we fetch the outline to validate/coerce inputs later on
267266 if isinstance (problem .specification , FormulationSpecification ):
@@ -315,7 +314,7 @@ async def _prepare_problem(
315314 strategy = solve_strategy_to_json (problem .strategy , outline ),
316315 options = solve_options_to_json (problem .options ),
317316 )
318- return (problem , outline )
317+ return _PreparedProblem (problem , outline , inputs )
319318
320319 async def serialize_problem (self , problem : Problem ) -> Json :
321320 """Returns a serialized representation of the problem
@@ -326,21 +325,21 @@ async def serialize_problem(self, problem: Problem) -> Json:
326325 Args:
327326 problem: :class:`.Problem` instance to serialize
328327 """
329- problem , _outline = await self ._prepare_problem (problem )
330- return problem
328+ prepared = await self ._prepare_problem (problem )
329+ return prepared . data
331330
332331 async def summarize_problem (self , problem : Problem ) -> ProblemSummary :
333332 """Returns summary statistics about a problem without solving it
334333
335334 Args:
336335 problem: :class:`.Problem` instance to summarize
337336 """
338- problem , _outline = await self ._prepare_problem (problem )
337+ prepared = await self ._prepare_problem (problem )
339338 async with self ._executor .execute (
340339 result_type = JsonExecutorResult ,
341340 url = "/summarize-problem" ,
342341 method = "POST" ,
343- json_data = json_dict (problem = problem ),
342+ json_data = json_dict (problem = prepared . data ),
344343 ) as res :
345344 return problem_summary_from_json (res .json_data ())
346345
@@ -379,12 +378,12 @@ async def format_problem(
379378
380379 .. _LP format: https://web.mit.edu/lpsolve/doc/CPLEX-format.htm
381380 """
382- problem , _outline = await self ._prepare_problem (problem )
381+ prepared = await self ._prepare_problem (problem )
383382 async with self ._executor .execute (
384383 result_type = PlainTextExecutorResult ,
385384 url = "/format-problem" ,
386385 method = "POST" ,
387- json_data = json_dict (problem = problem ),
386+ json_data = json_dict (problem = prepared . data ),
388387 ) as res :
389388 lines = []
390389 async for line in res .lines ():
@@ -447,15 +446,15 @@ async def solve(
447446 See also :meth:`.Client.queue_solve` for an alternative for
448447 long-running solves.
449448 """
450- problem , outline = await self ._prepare_problem (problem )
449+ prepared = await self ._prepare_problem (problem )
451450 if prefer_streaming and self ._executor .supports_streaming :
452451 problem_summary = None
453452 response_json = None
454453 async with self ._executor .execute (
455454 result_type = JsonSeqExecutorResult ,
456455 url = "/solve" ,
457456 method = "POST" ,
458- json_data = json_dict (problem = problem ),
457+ json_data = json_dict (problem = prepared . data ),
459458 ) as res :
460459 async for data in res .json_seq_data ():
461460 kind = data ["kind" ]
@@ -498,7 +497,8 @@ async def solve(
498497 if not problem_summary or not response_json :
499498 raise Exception ("Streaming solve terminated early" )
500499 solution = solution_from_json (
501- outline = outline ,
500+ outline = prepared .outline ,
501+ inputs = prepared .inputs ,
502502 response_json = response_json ,
503503 problem_summary = problem_summary ,
504504 )
@@ -510,7 +510,7 @@ async def solve(
510510 json_data = json_dict (problem = problem ),
511511 ) as res :
512512 solution = solution_from_json (
513- outline = outline ,
513+ outline = prepared . outline ,
514514 response_json = res .json_data (),
515515 )
516516
@@ -579,13 +579,13 @@ async def queue_solve(
579579 raise Exception (
580580 "Queued solves must have a formulation as specification"
581581 )
582- problem , _outline = await self ._prepare_problem (problem )
582+ prepared = await self ._prepare_problem (problem )
583583 async with self ._executor .execute (
584584 result_type = JsonExecutorResult ,
585585 url = "/queue-solve" ,
586586 method = "POST" ,
587587 json_data = json_dict (
588- problem = problem ,
588+ problem = prepared . data ,
589589 annotations = encode_annotations (annotations or []),
590590 ),
591591 ) as res :
@@ -849,3 +849,10 @@ async def _next_page() -> list[QueuedSolve]:
849849 for solve in solves :
850850 yield solve
851851 limit -= len (solves )
852+
853+
854+ @dataclasses .dataclass (frozen = True )
855+ class _PreparedProblem :
856+ data : Json
857+ outline : ProblemOutline
858+ inputs : SolveInputs
0 commit comments