Parameter generation (Z3)
Actions often take parameters. Parameter generation is the process of turning
declarative constraints into concrete argument combinations to explore. SEK uses the
Z3 theorem prover (via Microsoft.Z3) as its solver, with a dependency-free
enumerative solver as a cross-check and fallback.
Where domains come from
For each rule parameter, SEK determines a candidate domain:
| Source | When it applies |
|---|---|
Cord Condition.In(p, v1, v2, …) |
value parameters (int, string, enum, bool) |
[Domain("Method")] |
a method returns candidates; supports state-dependent domains |
| Natural domain | enum → all members; bool → {false, true} |
| Reachable objects | reference-typed parameters — see Object domains |
What Z3 does
Given the domains and constraints for an action, SEK builds an SMT problem:
- Each parameter becomes an SMT constant (integers for numeric/enum values, booleans, and an index for finite string domains).
Condition.Inbecomes a membership constraint.Condition.IsTrue(expr)becomes a boolean/arithmetic predicate (== != < <= > >=,&& || !,+ - * / %, and bitwise&|). Enum-qualified literals such asFrequency.Dailyare resolved to their underlying values.- Z3 then enumerates all satisfying assignments, blocking each model it finds so the next is different. Predicates Z3 can't represent are applied as a C# post-filter.
The result is exactly the set of parameter combinations that satisfy your constraints — no more, no less.
A worked example
From the ParameterGeneration sample:
action static void SUT.AddJob(string name, int time, Frequency frequency)
where {.
Condition.In(name, "@$^", "t.cmd", "t.exe");
Condition.In(time, -1, 60, 3600);
Condition.IsTrue(!(name == "t.cmd" & frequency != Frequency.Daily));
.};
name∈ 3 values,time∈ 3 values,frequency∈{Once, Daily, Weekly}(natural enum domain) → 27 combinations for the full product.- The
Condition.IsTruepredicate prunes the 6 combinations wherename == "t.cmd"andfrequency != Daily, leaving 21.
Exploring the Product machine yields 27 transitions; Constraint yields 21 —
demonstrating Z3-driven pruning.
Choosing the solver
sek explore <machine> --solver z3 # default
sek explore <machine> --solver enum # dependency-free enumerative solver
On small models the two agree exactly; running both is a good sanity check. Z3 scales to larger domains and richer predicates.
Performance
Value-parameter domains and constraints are state-independent, so SEK caches the solver result per action, turning what would be one solve per state into one solve per action. Object- and floating-point-typed parameters are enumerated directly (their domains can be state-dependent) rather than sent to Z3.
Self-test
sek z3 # prints SATISFIABLE and a sample model — confirms the native Z3 library loaded