pub trait SolverAdaptor: Sealed + Any {
// Required methods
fn solve(
&mut self,
callback: Box<dyn Fn(HashMap<Name, Literal>) -> bool + Send>,
_: Internal,
) -> Result<SolveSuccess, SolverError>;
fn solve_mut(
&mut self,
callback: Box<dyn Fn(HashMap<Name, Literal>, Box<dyn ModelModifier>) -> bool + Send>,
_: Internal,
) -> Result<SolveSuccess, SolverError>;
fn load_model(
&mut self,
model: Model,
_: Internal,
) -> Result<(), SolverError>;
fn get_family(&self) -> SolverFamily;
// Provided methods
fn init_solver(&mut self, _: Internal) { ... }
fn get_name(&self) -> Option<String> { ... }
fn add_adaptor_info_to_stats(&self, stats: SolverStats) -> SolverStats { ... }
}
Expand description
A common interface for calling underlying solver APIs inside a Solver
.
Implementations of this trait aren’t directly callable and should be used through Solver
.
The below documentation lists the formal requirements that all implementations of
SolverAdaptor
should follow - see the top level module documentation and Solver
for
usage details.
§Encapsulation
The SolverAdaptor
trait must only be implemented inside a submodule of this one,
and should only be called through Solver
.
The private::Sealed
trait and private::Internal
type enforce these requirements by only
allowing trait implementations and calling of methods of SolverAdaptor to occur inside this
module.
§Thread Safety
Multiple instances of Solver
can be run in parallel across multiple threads.
Solver
provides no concurrency control or thread-safety; therefore, adaptors must
ensure that multiple instances of themselves can be ran in parallel. This applies to all
stages of solving including having two active solve()
calls happening at a time, loading
a model while another is mid-solve, loading two models at once, etc.
A SolverAdaptor may use whatever threading or process model it likes underneath the hood, as long as it obeys the above.
Method calls should block instead of erroring where possible.
Underlying solvers that only have one instance per process (such as Minion) should block
(eg. using a Mutex<()>
) to run calls to
Solver<A,ModelLoaded>::solve()
and Solver<A,ModelLoaded>::solve_mut()
sequentially.
Required Methods§
Sourcefn solve(
&mut self,
callback: Box<dyn Fn(HashMap<Name, Literal>) -> bool + Send>,
_: Internal,
) -> Result<SolveSuccess, SolverError>
fn solve( &mut self, callback: Box<dyn Fn(HashMap<Name, Literal>) -> bool + Send>, _: Internal, ) -> Result<SolveSuccess, SolverError>
Runs the solver on the given model.
Implementations of this function must call the user provided callback whenever a solution
is found. If the user callback returns true
, search should continue, if the user callback
returns false
, search should terminate.
§Returns
If the solver terminates without crashing a SolveSuccess struct must returned. The value of SearchStatus can be used to denote whether the underlying solver completed its search or not. The latter case covers most non-crashing “failure” cases including user termination, timeouts, etc.
To help populate SearchStatus, it may be helpful to implement counters that track if the user callback has been called yet, and its return value. This information makes it is possible to distinguish between the most common search statuses: SearchComplete::HasSolutions, SearchComplete::NoSolutions, and SearchIncomplete::UserTerminated.
Sourcefn solve_mut(
&mut self,
callback: Box<dyn Fn(HashMap<Name, Literal>, Box<dyn ModelModifier>) -> bool + Send>,
_: Internal,
) -> Result<SolveSuccess, SolverError>
fn solve_mut( &mut self, callback: Box<dyn Fn(HashMap<Name, Literal>, Box<dyn ModelModifier>) -> bool + Send>, _: Internal, ) -> Result<SolveSuccess, SolverError>
Runs the solver on the given model, allowing modification of the model through a
ModelModifier
.
Implementations of this function must return OpNotSupported
if modifying the model mid-search is not supported.
Otherwise, this should work in the same way as solve
.
fn load_model(&mut self, model: Model, _: Internal) -> Result<(), SolverError>
Sourcefn get_family(&self) -> SolverFamily
fn get_family(&self) -> SolverFamily
Get the solver family that this solver adaptor belongs to
Provided Methods§
fn init_solver(&mut self, _: Internal)
Sourcefn add_adaptor_info_to_stats(&self, stats: SolverStats) -> SolverStats
fn add_adaptor_info_to_stats(&self, stats: SolverStats) -> SolverStats
Adds the solver adaptor name and family (if they exist) to the given stats object.