discrete_optimization.generic_tools.graph_solver package
Submodules
discrete_optimization.generic_tools.graph_solver.solver_graph module
DAG-based solver workflow (SolverGraph).
- class discrete_optimization.generic_tools.graph_solver.solver_graph.BackTransformNode(node_id: str, transformation: ProblemTransformation, source_problem: Problem)[source]
Bases:
GraphNodeNode that back-transforms solutions through a transformation.
- execute(**kwargs: Any) NodeData[source]
Back-transform all solutions.
- Returns:
NodeData with back-transformed result, solution, and source problem
- transformation: ProblemTransformation
- class discrete_optimization.generic_tools.graph_solver.solver_graph.GraphNode(node_id: str)[source]
Bases:
ABCBase class for nodes in the solver graph.
A node takes inputs, executes an operation, and produces outputs. Data flows through the graph as NodeData objects.
- can_execute() bool[source]
Check if all required inputs are available.
Default: can execute if we have at least one input. Override in subclasses for specific requirements.
- Returns:
True if node can execute
- abstractmethod execute(**kwargs: Any) NodeData[source]
Execute the node’s operation.
- Parameters:
**kwargs – Execution parameters (e.g., time_limit)
- Returns:
NodeData with problem, result, and/or solution
- get_input_problem() Problem[source]
Extract problem from inputs.
- Returns:
Problem instance from first input that has one
- get_input_solution() Solution | None[source]
Extract best solution from inputs for warmstart.
- Returns:
Solution if available, None otherwise
- node_id: str
- class discrete_optimization.generic_tools.graph_solver.solver_graph.MergeNode(node_id: str, strategy: str = 'best')[source]
Bases:
GraphNodeNode that merges multiple result storages.
- execute(**kwargs: Any) NodeData[source]
Merge input result storages.
- Returns:
NodeData with merged result and solution
- strategy: str
- class discrete_optimization.generic_tools.graph_solver.solver_graph.NodeData(problem: Problem | None = None, result: ResultStorage | None = None, solution: Solution | None = None)[source]
Bases:
objectData flowing through graph nodes.
- problem
Problem instance (required for most nodes)
- result
ResultStorage from solver nodes (optional)
- solution
Single best solution for warmstart/kwargs extraction (optional)
- result: ResultStorage | None = None
- class discrete_optimization.generic_tools.graph_solver.solver_graph.RootNode(node_id: str, problem: Problem)[source]
Bases:
GraphNodeVirtual root node that provides the source problem.
- class discrete_optimization.generic_tools.graph_solver.solver_graph.SolverGraph(source_problem: Problem)[source]
Bases:
objectDAG-based solver workflow.
Supports: - Branching (parallel strategies) - Merging (combine results) - Transformations (problem conversion) - Arbitrary directed acyclic graphs
Example (linear, like SequentialMetasolver): # >>> graph = SolverGraph(problem) # >>> graph.add_solver(“solver1”, SubBrick(cls=Solver1, kwargs={})) # >>> graph.add_solver(“solver2”, SubBrick(cls=Solver2, kwargs={})) # >>> graph.add_edge(“root”, “solver1”) # >>> graph.add_edge(“solver1”, “solver2”) # >>> result = graph.run() # # Example (branching): # >>> graph = SolverGraph(problem) # >>> graph.add_solver(“cpsat”, SubBrick(cls=CPSat, kwargs={})) # >>> graph.add_solver(“lp”, SubBrick(cls=LP, kwargs={})) # >>> graph.add_merge(“merge”, strategy=”best”) # >>> graph.add_edge(“root”, “cpsat”) # >>> graph.add_edge(“root”, “lp”) # >>> graph.add_edge(“cpsat”, “merge”) # >>> graph.add_edge(“lp”, “merge”) # >>> result = graph.run()
- add_back_transform(node_id: str, transformation: ProblemTransformation, source_problem: Problem) str[source]
Add a back-transformation node.
- Parameters:
node_id – Unique identifier for this node
transformation – Transformation to reverse
source_problem – Original problem
- Returns:
Node ID (for chaining)
- add_edge(from_node: str, to_node: str) None[source]
Add an edge between nodes.
- Parameters:
from_node – Source node ID
to_node – Target node ID
- Raises:
ValueError – If nodes don’t exist
- add_merge(node_id: str, strategy: str = 'best') str[source]
Add a merge node.
- Parameters:
node_id – Unique identifier for this node
strategy – Merge strategy (“best” or “all”)
- Returns:
Node ID (for chaining)
- add_solver(node_id: str, solver_brick: SubBrick) str[source]
Add a solver node.
- Parameters:
node_id – Unique identifier for this node
solver_brick – Solver specification
- Returns:
Node ID (for chaining)
- add_transformation(node_id: str, transformation: ProblemTransformation) str[source]
Add a transformation node.
- Parameters:
node_id – Unique identifier for this node
transformation – Transformation to apply
- Returns:
Node ID (for chaining)
- edges: dict[str, list[str]]
- reverse_edges: dict[str, list[str]]
- run(**solve_kwargs: Any) ResultStorage[source]
Execute the graph and return final results.
- Parameters:
**solve_kwargs – Keyword arguments passed to all solver nodes
- Returns:
ResultStorage with final solutions
- Raises:
RuntimeError – If execution fails
- class discrete_optimization.generic_tools.graph_solver.solver_graph.SolverNode(node_id: str, solver_brick: SubBrick)[source]
Bases:
GraphNodeNode that runs a solver.
- class discrete_optimization.generic_tools.graph_solver.solver_graph.TransformationNode(node_id: str, transformation: ProblemTransformation)[source]
Bases:
GraphNodeNode that applies a problem transformation.
- execute(**kwargs: Any) NodeData[source]
Transform the input problem.
- Returns:
NodeData with transformed problem
- transformation: ProblemTransformation
Module contents
DAG-based solver workflows (SolverGraph).
- class discrete_optimization.generic_tools.graph_solver.BackTransformNode(node_id: str, transformation: ProblemTransformation, source_problem: Problem)[source]
Bases:
GraphNodeNode that back-transforms solutions through a transformation.
- execute(**kwargs: Any) NodeData[source]
Back-transform all solutions.
- Returns:
NodeData with back-transformed result, solution, and source problem
- transformation: ProblemTransformation
- class discrete_optimization.generic_tools.graph_solver.GraphNode(node_id: str)[source]
Bases:
ABCBase class for nodes in the solver graph.
A node takes inputs, executes an operation, and produces outputs. Data flows through the graph as NodeData objects.
- can_execute() bool[source]
Check if all required inputs are available.
Default: can execute if we have at least one input. Override in subclasses for specific requirements.
- Returns:
True if node can execute
- abstractmethod execute(**kwargs: Any) NodeData[source]
Execute the node’s operation.
- Parameters:
**kwargs – Execution parameters (e.g., time_limit)
- Returns:
NodeData with problem, result, and/or solution
- get_input_problem() Problem[source]
Extract problem from inputs.
- Returns:
Problem instance from first input that has one
- get_input_solution() Solution | None[source]
Extract best solution from inputs for warmstart.
- Returns:
Solution if available, None otherwise
- node_id: str
- class discrete_optimization.generic_tools.graph_solver.MergeNode(node_id: str, strategy: str = 'best')[source]
Bases:
GraphNodeNode that merges multiple result storages.
- execute(**kwargs: Any) NodeData[source]
Merge input result storages.
- Returns:
NodeData with merged result and solution
- strategy: str
- class discrete_optimization.generic_tools.graph_solver.NodeData(problem: Problem | None = None, result: ResultStorage | None = None, solution: Solution | None = None)[source]
Bases:
objectData flowing through graph nodes.
- problem
Problem instance (required for most nodes)
- result
ResultStorage from solver nodes (optional)
- solution
Single best solution for warmstart/kwargs extraction (optional)
- result: ResultStorage | None = None
- class discrete_optimization.generic_tools.graph_solver.SolverGraph(source_problem: Problem)[source]
Bases:
objectDAG-based solver workflow.
Supports: - Branching (parallel strategies) - Merging (combine results) - Transformations (problem conversion) - Arbitrary directed acyclic graphs
Example (linear, like SequentialMetasolver): # >>> graph = SolverGraph(problem) # >>> graph.add_solver(“solver1”, SubBrick(cls=Solver1, kwargs={})) # >>> graph.add_solver(“solver2”, SubBrick(cls=Solver2, kwargs={})) # >>> graph.add_edge(“root”, “solver1”) # >>> graph.add_edge(“solver1”, “solver2”) # >>> result = graph.run() # # Example (branching): # >>> graph = SolverGraph(problem) # >>> graph.add_solver(“cpsat”, SubBrick(cls=CPSat, kwargs={})) # >>> graph.add_solver(“lp”, SubBrick(cls=LP, kwargs={})) # >>> graph.add_merge(“merge”, strategy=”best”) # >>> graph.add_edge(“root”, “cpsat”) # >>> graph.add_edge(“root”, “lp”) # >>> graph.add_edge(“cpsat”, “merge”) # >>> graph.add_edge(“lp”, “merge”) # >>> result = graph.run()
- add_back_transform(node_id: str, transformation: ProblemTransformation, source_problem: Problem) str[source]
Add a back-transformation node.
- Parameters:
node_id – Unique identifier for this node
transformation – Transformation to reverse
source_problem – Original problem
- Returns:
Node ID (for chaining)
- add_edge(from_node: str, to_node: str) None[source]
Add an edge between nodes.
- Parameters:
from_node – Source node ID
to_node – Target node ID
- Raises:
ValueError – If nodes don’t exist
- add_merge(node_id: str, strategy: str = 'best') str[source]
Add a merge node.
- Parameters:
node_id – Unique identifier for this node
strategy – Merge strategy (“best” or “all”)
- Returns:
Node ID (for chaining)
- add_solver(node_id: str, solver_brick: SubBrick) str[source]
Add a solver node.
- Parameters:
node_id – Unique identifier for this node
solver_brick – Solver specification
- Returns:
Node ID (for chaining)
- add_transformation(node_id: str, transformation: ProblemTransformation) str[source]
Add a transformation node.
- Parameters:
node_id – Unique identifier for this node
transformation – Transformation to apply
- Returns:
Node ID (for chaining)
- edges: dict[str, list[str]]
- reverse_edges: dict[str, list[str]]
- run(**solve_kwargs: Any) ResultStorage[source]
Execute the graph and return final results.
- Parameters:
**solve_kwargs – Keyword arguments passed to all solver nodes
- Returns:
ResultStorage with final solutions
- Raises:
RuntimeError – If execution fails
- class discrete_optimization.generic_tools.graph_solver.SolverNode(node_id: str, solver_brick: SubBrick)[source]
Bases:
GraphNodeNode that runs a solver.
- class discrete_optimization.generic_tools.graph_solver.TransformationNode(node_id: str, transformation: ProblemTransformation)[source]
Bases:
GraphNodeNode that applies a problem transformation.
- execute(**kwargs: Any) NodeData[source]
Transform the input problem.
- Returns:
NodeData with transformed problem
- transformation: ProblemTransformation