Skip to content

Quickstart

The interface has two sides, with a quickstart for each.

Find a solver by name, describe a small problem, and print the solutions.

import fznso
# 1. Find and open a solver library, then create an instance.
solver = fznso.Library.find("example_solver").create_solver()
# 2. Describe the problem.
model = fznso.LayeredModel()
var_int = fznso.Type("int", decision=True)
a = model.add_decision(var_int, range(3, 21), name="a") # a in 3..20
b = model.add_decision(var_int, range(10, 21), name="b") # b in 10..20
model.add_constraint("int_lin_le", [[-1], [a], 0]) # a >= 0
model.set_objective("minimize", a)
# 3. Configure and run.
solver.option_set("time_limit", 10_000) # milliseconds
status = solver.run(model, on_solution=lambda s: print(s[a], s[b]))
print(status) # Status.Complete

Next: Using a solver for the complete workflow, or Installing solvers if find cannot see yours.

Implement the interface for your own solver, and every FZnSO application can drive it.

use fznso::{Model, Solution, Solver, SolverType, Status, Value};
struct MySolution;
impl Solution for MySolution {
fn value(&self, index: usize) -> Value<'_> { todo!() }
fn statistic(&self, name: &str) -> Value<'_> { todo!() }
}
struct MySolver;
impl Solver for MySolver {
type Solution<'s> = MySolution where MySolver: 's;
fn option_get(&self, name: &str) -> Value<'_> { todo!() }
fn option_set(&mut self, name: &str, value: Value<'_>) -> Result<(), String> { todo!() }
fn run<M, F, G, H>(
&mut self,
model: &M,
on_solution: &mut F,
on_message: Option<&mut G>, // `None` — nobody is listening, skip building diagnostics
should_stop: Option<&H>, // `None` — the caller never cancels, skip polling
) -> Status
where
M: Model + Sync,
F: for<'s> FnMut(&'s MySolution) + Send,
G: FnMut(&str, Value<'_>) + Send,
H: Fn() -> bool + Send + Sync,
{ todo!() }
}
// What the solver declares. Every capability list defaults to empty.
impl SolverType for MySolver {
fn new() -> Self { MySolver }
}
// Writes all thirteen entry points as `fznso_mysolver_…`.
fznso::fznso_export!(MySolver, "mysolver");

Build as a cdylib, and the file name must match the name you passed:

[lib]
crate-type = ["cdylib"]
name = "mysolver"

The name in the symbols must match the library’s file name; see Naming & versioning.

Next: Implementing a solver for the complete walkthrough with a working example.