C++ solver export
Subclass fznso::Solver and expand FZNSO_EXPORT_SOLVER(YourSolver, yoursolver)
once; the macro writes all thirteen entry points.
The consumer side is fznso.hpp.
5 classs
Classes
Section titled “Classes”fznso::MessageSink
Section titled “fznso::MessageSink”class fznso::MessageSinksourceReceives the non-fatal diagnostics a solver reports during a run.
The sink may be absent, meaning nobody is listening. Check wanted() before doing any work to produce a message: the point of the absent case is that a solver skips formatting diagnostics rather than handing them to something that discards them.
MessageSink(void *context, void(*on_message)(void *, FznsoStr, FznsoValueRef))bool wanted() constWhether anything is listening. When false, message does nothing.
void message(std::string_view scope, Value value)Report a message.
value must outlive this call. Does nothing when no listener is attached, so guard the construction with wanted().
fznso::SolutionSink
Section titled “fznso::SolutionSink”class fznso::SolutionSinksourceReceives the solutions a solver finds during a run.
SolutionSink(void *context, void(*on_solution)(void *, FznsoSolutionRef))void solution(const S &src)Report a solution. src must outlive this call.
fznso::SolutionSource
Section titled “fznso::SolutionSource”class fznso::SolutionSourcesourceThe values a solver publishes for one solution.
Subclass this and hand an instance to SolutionSink::solution. The returned values borrow storage the source owns, which must outlive the solution call.
~SolutionSource()=default`Value` value(Decision decision) const =The value assigned to a decision variable.
`Value` statistic(std::string_view) constA named statistic for this solution, or absent if unknown.
fznso::Solver
Section titled “fznso::Solver”class fznso::SolversourceThe interface a solver implements.
Subclass this, implement the three instance methods, and expand FZNSO_EXPORT_SOLVER(YourSolver, yourname). The capability lists are static and default to empty; hide the ones your solver supports.
~Solver()=default`Value` option_get(std::string_view name) const =The current value of a named option. Borrows storage the solver owns.
std::optional< std::string > option_set(std::string_view name, Value value)=Set a named option.
Return a message to reject the value; the consumer receives it. Return std::nullopt on success.
`Value` statistic(std::string_view) constThe current value of a named solver-level statistic, or absent if unknown.
Only statistics this solver declares with the solver flag set in statistic_list() are readable here; statistics carrying only the solution flag are reported through SolutionSource::statistic instead. A solver with no solver-level statistics need not override this.
`Status` run(const Model &model, SolutionSink &solutions, MessageSink &messages, const StopSignal &stop)=Run against model, reporting solutions and messages through the sinks.
Threading contract, if the solver searches on several threads: the sinks must be driven serially — SolutionSink::solution and MessageSink::message may be called from any thread, but never two at once and never one while the other runs (funnel them through the thread that updates the incumbent, or a dedicated reporting thread). model is a read-only view for the duration of the call and may be queried concurrently from any number of threads. stop may be polled from any thread too, including several at once.
FznsoConstraintList constraint_list()The constraints this solver accepts. Empty by default.
FznsoTypeList decision_list()The decision-variable types this solver accepts. Empty by default.
FznsoObjectiveList objective_list()The objective strategies this solver supports. Empty by default.
FznsoOptionList option_list()The options this solver accepts. Empty by default.
FznsoStatisticList statistic_list()The statistics this solver reports. Empty by default.
fznso::StopSignal
Section titled “fznso::StopSignal”class fznso::StopSignalsourcePolled by a solver to ask whether the caller wants the search abandoned.
Answering true means stop as soon as convenient and return Status::Kind::Incomplete. A solver is expected to poll once before starting, again after each reported solution (so a caller can stop from inside its own callback), and otherwise as often as is reasonable so that a cancel is acted on promptly. The answer is monotone — once true it stays true — so it may be cached.
It is cheap and never blocks, but it is an indirect call, so polling every node is wasteful; once per restart or node batch is the intent. It is safe to call from any thread, including concurrently from several at once.
The signal may be absent, meaning the caller will never ask to stop; requested() is then constantly false and pollable() says so, letting a solver drop the check from its loop entirely. A caller that only wants a deadline should set the time_limit option instead of polling a clock here, since a solver told its deadline up front can plan its search around it.
StopSignal(void *context, bool(*should_stop)(void *))bool pollable() constWhether there is anything to poll at all.
bool requested() constWhether the caller has asked the search to stop.