Entry points
A solver library exports exactly thirteen symbols, each named fznso_<name>_… after the library’s own name: fznso_gecode_solver_run for a solver named gecode.
All thirteen are mandatory. A loader looks every one of them up when opening a library, and a missing symbol fails the load.
The library
Section titled “The library”These describe the library itself. They take no solver instance, and may be called before one exists.
| Symbol | Returns | Purpose |
|---|---|---|
fznso_<name>_abi_version | uint32_t | The protocol revision this solver was built against. Checked first; see ABI stability. |
fznso_<name>_constraint_list | FznsoConstraintList | Constraint identifiers and argument types the solver accepts. |
fznso_<name>_decision_list | FznsoTypeList | Decision-variable types the solver can create. |
fznso_<name>_objective_list | FznsoObjectiveList | Objective strategies the solver can pursue. |
fznso_<name>_option_list | FznsoOptionList | Options the solver accepts, with types and defaults. |
fznso_<name>_statistic_list | FznsoStatisticList | Statistics the solver can report, and whether each comes from a solution, the solver, or both. |
The five lists are a solver’s declaration of what it can do. An application must not use a name that does not appear in them, and a solver must not accept one. Where a name has a registry entry, declaring it means committing to the registry’s meaning.
Every list is static: the arrays stay valid for as long as the library is loaded, and the caller never frees them.
Declaring a narrower argument type
Section titled “Declaring a narrower argument type”FznsoConstraintType carries an arg_types array, and those types are the solver’s own answer, not a copy of the registry’s signature.
A solver may declare an argument type narrower than the registry’s — usually to say an argument is only handled as a parameter:
registry int_in(var int: x, var set of int: values)a solver int_in(var int: x, set of int: values)Narrowing applies to every part of a type (var int to int, opt int to int), and is the type qualifier relation read as “accepts fewer things”.
That is still the same constraint, restricted to what the solver’s propagator can do — so the obligation lands on the application: having read arg_types, it must not pass a decision variable where the solver asked for a parameter.
The solver instance
Section titled “The solver instance”| Symbol | Purpose |
|---|---|
fznso_<name>_solver_create | Create an instance. Returns FznsoSolver *, never null. |
fznso_<name>_solver_free | Destroy an instance and release everything it holds. |
fznso_<name>_solver_option_set | Set one option. Returns false on failure. |
fznso_<name>_solver_option_get | Read one option’s current value. |
fznso_<name>_solver_statistic | Read one statistic from the instance. |
fznso_<name>_solver_read_error | Hand the most recent error message to a callback. |
fznso_<name>_solver_run | Search. See Running a search. |
An instance is created, configured, run any number of times, and freed.
Options may be changed between runs.
Only fznso_<name>_solver_run is expected to take a long time.
Errors
Section titled “Errors”Two entry points can fail in a way that carries a message: option_set returns false, and run returns FznsoError.
Neither returns the reason directly.
The caller then calls fznso_<name>_solver_read_error, which passes the message to a callback rather than returning it, so the message need only stay valid for the duration of that callback.
This is the only error channel.
The on_message callback during a run is not for failures.
fznso_<name>_solver_create cannot fail.
It returns a valid instance even when the solver cannot work, for example because a licence is missing.
The instance records the failure and reports it through the channel above: the next option_set returns false, or the next run returns FznsoError.
The application therefore always has an instance to call fznso_<name>_solver_read_error on, and to free.
The template
Section titled “The template”Copy the template and fill it in; it is not a library to link against.
- ABI entry points — the full contract on each, generated from the template
c/fznso_solver_template.c— the C template, generated by cbindgenFZNSO_EXPORT_SOLVER— C++, which writes all thirteen for youfznso_export!— Rust, likewise