Skip to content

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

class fznso::MessageSinksource

Receives 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.

methodMessageSink(void *context, void(*on_message)(void *, FznsoStr, FznsoValueRef))
methodbool wanted() const

Whether anything is listening. When false, message does nothing.

methodvoid 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().

class fznso::SolutionSinksource

Receives the solutions a solver finds during a run.

methodSolutionSink(void *context, void(*on_solution)(void *, FznsoSolutionRef))
methodvoid solution(const S &src)

Report a solution. src must outlive this call.

class fznso::SolutionSourcesource

The 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.

method~SolutionSource()=default
method`Value` value(Decision decision) const =

The value assigned to a decision variable.

method`Value` statistic(std::string_view) const

A named statistic for this solution, or absent if unknown.

class fznso::Solversource

The 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.

method~Solver()=default
method`Value` option_get(std::string_view name) const =

The current value of a named option. Borrows storage the solver owns.

methodstd::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.

method`Value` statistic(std::string_view) const

The 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.

method`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 seriallySolutionSink::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.

methodFznsoConstraintList constraint_list()

The constraints this solver accepts. Empty by default.

methodFznsoTypeList decision_list()

The decision-variable types this solver accepts. Empty by default.

methodFznsoObjectiveList objective_list()

The objective strategies this solver supports. Empty by default.

methodFznsoOptionList option_list()

The options this solver accepts. Empty by default.

methodFznsoStatisticList statistic_list()

The statistics this solver reports. Empty by default.

class fznso::StopSignalsource

Polled 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.

methodStopSignal(void *context, bool(*should_stop)(void *))
methodbool pollable() const

Whether there is anything to poll at all.

methodbool requested() const

Whether the caller has asked the search to stop.