All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Warm-start:
OptimizationSearch::with_hint,Model::optimize_objective_with_hint, CLIsolve --hint(JSON int map). - Large-neighborhood search for single-objective optimize:
LargeNeighborhoodSearch/Model::optimize_objective_lns, CLI--lns-iterations/--lns-destroy/--lns-seed. - Variable resource capacity for
cumulative/fzn_cumulative(Model::cumulative_var, capacity as int param orvar int). - Variable-size
diffnrectangles (RectangleSpecwidth/height vars; FlatZinc width/height arrays may bevar). - Timed FlatZinc perf corpus (
benchmarks/perf/manifest.txt,scripts/flatzinc-perf-report.sh) plus Criterion benchpropaga-flatzinc/flatzinc_solveand weeklyPerfworkflow. - Cumulative time-table / overload use duration and demand mins (and watch those vars), not only fixed fields.
- Classical cumulative edge-finding (energetic overload + EST/LCT bound pruning) beyond time-table reasoning.
- Portfolio
--workersfor single-objective BnB, lexicographic, and Pareto FlatZinc solves (diversified configs; best objective / merged front); single-objective BnB workers honor--hintwarm-starts. - Typed conflict learning for set/float wipeouts: posts a
ForbiddenAssignmentPropagator(float points viaencode_forbidden_float) over fixed decision vars at conflict, then decision-UIP backjumps using unique branch literals on the trail. - FlatZinc alias layer for MiniZinc solver-library predicates (
fzn_*,array_int_lt, …) plusfzn_cumulative/fzn_exactly_int/ 3-argfzn_global_cardinalityremaps. SearchConfig::incompletefrom FlatZincincompleteannotations: BnB returns after the first feasible solution.- CI job
minizinc-fresh: install MiniZinc bundle +flatzinc-full-compat-report.sh(fail-closed). - ROADMAP phased backlog for v1.2 polish, v1.3 MiniZinc ecosystem, and v1.4+ competitive work.
- Wide-span
ceil/floor/roundforward images consult the domain hole list (and unit-width gap checks) when deciding emptied integer images. - COMPATIBILITY lists
restart_linear/restart_on_solution, alias table, and realincompletesemantics;--workerscovers optimize paths.
- Float propagation remains interval-based (sound, not exact real arithmetic).
- Typed set/float learning uses forbidden-assignment blocking plus decision-UIP backjump (no typed first-UIP explanation graph / LCG yet).
1.1.0 - 2026-07-29
- Lexicographic and Pareto multi-objective search now accept float and set-cardinality objectives (same typed targets as single-objective optimization).
- Incremental Pareto enumeration: DFS streams solutions via
solve_eachand updates the non-dominated front online (no full feasible-set buffer). - Typed Pareto dominance cuts (
DominanceCutPropagator) for int, float, and set-cardinality thresholds; Pareto search posts cuts between solutions for all objective types. ForbiddenAssignmentPropagatorblocks rediscovery of int / float / set assignments during Pareto enumeration.encode_forbidden_floatexcludes a continuous float point via reified≤ next_down ∨ ≥ next_up, and Pareto blocking adds those reifs as search decisions.- DFS float branching can split around registered blocked IEEE points; Pareto search feeds blocked float values into those split hints.
FloatNePropagatorprunes forbidden float values at interval endpoints;FloatEqReif(false)delegates to it; FlatZincfloat_ltuses strict¬(b ≤ a).FloatLinearNePropagatorforsum ≠ rhswith bound-touch and unit-endpoint pruning;ReifiedFloatLinearEq(false)no longer posts contradictory≤and≥cuts.FloatDomaincan record interior excluded IEEE points;ExtendedPropagationContext::exclude_float_pointwires exclusion intoFloatNe/ assignment blocking, and DFS prefers splitting at domain holes.- Hole-aware float arithmetic:
FloatDomain::affineand fixed-operandplus/times/dividepreserve holes;FloatEqshares holes; plus/times/div propagators project holes when a side is fixed. FloatLinearEqPropagatorforfloat_lin_eqwith affine hole sharing when two variables remain free;float_lin_neexcludes interior equality-forcing points when other terms are fixed.- Unary float maps (
abs,sqrt,ln,exp) preserve or safely project holes;FloatUnaryPropagatorreverse-projects through locally invertible cases. FloatElementPropagatorfor floatarray_element: shares holes when the index is fixed and projects holes absent from every remaining candidate.- Locally monotonic
sin/cospreserve and reverse-project holes;ceil/floor/roundcollapse to a fixed point when constant on the domain. - FlatZinc
float_search/set_searchparsing;indomain_random(deterministic) andindomain_reverse_splitvalue orderings;most_constrained/least_constrainedaliases. - FlatZinc
indomain_intervalvalue ordering and multi-phaseseq_search(per nested group selectors until that group's variables are fixed). - Stdlib corpus fixtures
seq_search,search_selectors,float_search_ann,set_search_ann,bool_search_ann,indomain_random_ann,reverse_split_ann, andmedian_luby_annwith compile + SAT regression inbuiltin_corpus(including portfolio SAT forseq_search). - Portfolio search attaches model
search_phasesto every worker so FlatZincseq_searchis respected with--workers > 1. ExtendedPropagationContext::tighten_set_cardinalityfor set-cardinality bound updates during propagation.SetUnionPropagatortightens set-cardinality bounds (|A∪B| ≥ max(|A|,|B|,|glb(A)∪glb(B)|,|A|+|glb(R)\lub(A)|),|A∪B| ≤ |A|+|B|, subset relations).SetIntersectPropagatortightens set-cardinality bounds (|A∩B| ≤ min(|A|,|B|, overlap),|A| ≥ |R| + |glb(A)\lub(R)|, operand outside-overlap lower bounds).SetSubsetPropagatortightens set-cardinality bounds (|A| ≤ |B|,|B| ≥ |A| + |glb(B)\lub(A)|whenA ⊆ B).- Handwritten FlatZinc fixtures
float_round.fznandset_subset.fzn; CI smoke solves forset_union.fzn,set_intersect.fzn, andfloat_round.fzn. FloatUnaryPropagatorreverse-projects fixed integer images ofceil/floor/roundonto the input domain.- Handwritten FlatZinc fixtures
float_floor.fznandfloat_ceil.fzn(fixed-image reverse projection); CI smoke forfloat_floor.fzn. - CLI and README document the full
--var-ordering/--value-orderingalias sets (includingsplit,reverse-split,interval,random,activity). - CLI
--var-orderingaccepts FlatZinc aliasessmallest/occurrence/degree(same mapping as compile); CI smoke-solvesfloat_ceil.fzn. - Stdlib corpus fixture
bool_search_ann(bool_search+restart_geometric) with compile + SAT regression. - Stdlib corpus fixture
indomain_random_ann(indomain_randomvalue ordering) with compile + SAT regression. - Stdlib corpus fixture
reverse_split_ann(indomain_reverse_split+restart_constant) with compile + SAT regression. - Stdlib corpus fixture
median_luby_ann(activity+indomain_median+restart_luby) with compile + SAT regression. - BnB / lexicographic / Pareto search attach model
search_phases(FlatZincseq_searchrespected under optimize paths). SetIntervalDomain::with_cardinalityclamps requested bounds to[|GLB|, |LUB|].SetIntervalDomain::force_in/force_outkeep cardinality bounds aligned with GLB/LUB sizes.- CI smoke solves for
set_subset.fznandset_eq.fzn. - Handwritten FlatZinc fixture
seq_search_minimize.fzn; CI smoke for BnB +seq_searchandfloat_abs.fzn. FloatUnaryPropagatorreverse-projects fixed images ofexp/ln/sqrtonto the input.- Handwritten FlatZinc fixture
float_exp.fzn; CI smoke forfloat_exp,float_times,lexicographic_multi, andpareto_biobjective. - Handwritten FlatZinc fixtures
set_diff.fznandset_symdiff.fzn; CI smoke solves for both. SetIntervalDomain::wipeoutfor failed membership forces;with_cardinality(…, 0)collapses to the fixed empty set.Model::set_var_auxfor non-decision set auxiliaries; FlatZincset_diff/set_symdiffdecompositions use it.- Handwritten FlatZinc fixtures
float_ln.fznandfloat_sqrt.fzn; CI smoke solves for both. Model::int_var_auxandModel::float_var_auxfor non-decision decomposition variables.- Handwritten FlatZinc fixture
float_log2.fzn; CI smoke forfloat_log2andset_cardinality. - Float / int FlatZinc decompositions (
float_max/min,float_in/dom, array float extrema,array_int_maximum/minimum,int_plusoverflow path,array_bool_xor) create auxiliaries with*_aux. Model::int_var_fixedis no longer a search decision variable.- CI smoke solves for
float_minimize.fznandset_optimize.fzn. - FlatZinc compile paths for unit-sum chains / reified linear / set-element indexing, and globals decompositions (lex / count / nvalue / …), create intermediates with
int_var_aux(sort permutation variables remain decisions). - Handwritten FlatZinc fixture
float_sin.fzn; CI smoke forfloat_sin,set_param,float_bounds, andfloat_lin_le. - Handwritten FlatZinc fixture
float_cos.fzn; CI smoke forfloat_cos,lex_less,all_different_only, andgeneric_min. - CI smoke solves for core int/bool/reified/BnB/globals fixtures:
int_plus,int_times,int_abs,int_min,int_lin_ne,bool_clause,bool_xor,bool_logic,reified_eq,reified_ne,maximize_x,minimize_cost,regular_chain,automaton_chain, andnested_predicate. - CI smoke solves for remaining handwritten fixtures: reified linear/lt/
bool_reify, bounded/weighted sums,count/cumulative/disjunctive, ordered/strict chains,permutation_sum/predicate_multi/table_puzzle, andint_searchorder/restart. - Native
SetDiffPropagatorfor FlatZincset_diff(replaces multi-constraint aux decomposition);Model::set_diff. - Native
SetSymDiffPropagatorfor FlatZincset_symdiff;Model::set_symdiff. SetCardEqPropagator/Model::set_card_eqfor FlatZincset_card(S, k)with a variable cardinality; handwrittenset_card_var.fzn+ CI smoke.- Native
SetEqPropagatorfor FlatZincset_eq(membership + cardinality sync; replaces dual-subset encoding). - FlatZinc
array_var_set_elementuses 1-based indices;array_var_set_element_nonshiftedstays 0-based; handwritten fixtures + CI smoke. - FlatZinc
array_var_bool_elementuses 1-based indices via an index shift intoElementPropagator;_nonshiftedstays 0-based; handwritten fixtures + CI smoke. - FlatZinc
array_int_element/array_var_int_element/array_bool_element/array_float_element/array_var_float_elementuse 1-based indices (with_nonshifted0-based variants); shared index-shift helper; CI smoke for int/float element. - FlatZinc
array [L..U] of var set of A..Bdeclarations; handwrittenarray_set_vars.fzn+ CI smoke. - FlatZinc
array [L..U] of var float/ float-bounded array declarations; handwrittenarray_float_vars.fzn+ CI smoke. - FlatZinc
array [L..U] of set of intparameter arrays andarray_set_element(1-based /_nonshifted); handwrittenarray_set_element.fzn+ CI smoke. - FlatZinc
array [L..U] of float/of boolparameter arrays; handwrittenarray_float_element.fzn/array_bool_element.fzn+ CI smoke. - Native
SetNePropagatorfor FlatZincset_ne(replaces reifiedset_eq); handwrittenset_ne.fzn+ CI smoke. SetLtPropagatorfor FlatZincset_lt(A ⊂ Bvia subset +|B| ≥ |A| + 1cards); handwrittenset_lt.fzn+ CI smoke.- Native
FloatMinMaxPropagatorfor FlatZincfloat_min/float_max(replaces reified OR encoding); handwrittenfloat_min_max.fzn+ CI smoke. - Native
IntMinMaxPropagatorfor FlatZincint_min/int_max(replaces domain tables);array_float_minimum/maximumfold via binary min/max; fixturesint_min_max.fzn/array_float_min_max.fzn+ CI smoke. - Native
IntAbsPropagatorfor FlatZincint_abs(replaces domain table);array_int_minimum/maximumfold via binary min/max; fixturearray_int_min_max.fzn+ CI smoke. - Native
IntTimesPropagatorfor FlatZincint_times(replaces domain table / 10k cap); handwrittenint_times_large.fzn+ CI smoke. - Native
IntDivPropagatorfor FlatZincint_div(trunc toward zero, excludes divisor 0);int_plusalways postslinear_eq; handwrittenint_div.fzn+ CI smoke. - Native
IntModPropagatorfor FlatZincint_mod;bool_notpostsa + b = 1; handwrittenint_mod.fzn+ CI smoke. - FlatZinc
bool_and/bool_or/bool_xorvia linear and reified encodings (no truth tables); handwrittenbool_and_or_xor.fzn+ CI smoke. - FlatZinc
int_pow_fixedviaint_timesmultiply chain (no domain table); handwrittenint_pow_fixed.fzn/bool_le_lt.fzn+ CI smoke. - FlatZinc
int_powvia exponent case-split +element(table fallback for huge exponent spans); fixElementPropagatorincorrectly intersecting value with every array cell when the index is unfixed; handwrittenint_pow.fzn+ CI smoke. ElementPropagatorprunes indices whose cells are bound/fixed-disjoint from the value (not only when the value is fixed); handwrittenarray_element_prune.fzn+ CI smoke.FloatDomain::ceil/floor/rounddrop integer images whose preimages are emptied by holes (endpoint-only cases); wide spans still use a hole-free bound fallback.- FlatZinc / CLI
indomain_middlevalue ordering (domain value closest to the mean of current bounds); stdlib corpus fixtureindomain_middle_ann. - FlatZinc / CLI variable selectors: true
smallest/largest/max_regret,anti_first_failas largest-domain,dom_w_deg(plusoccurrence/degree≈ W-DEG); corpus fixturemax_regret_ann. set_searchvalue selectors choose which undecided element to branch on and whether to try membership in/out first;float_searchreverse-split tries the upper half first; corpus fixtureset_search_max_ann.- FlatZinc
set_le/set_lt(+ reifs) use sorted-list lexicographic order viaSetLexPropagator(RustModel::set_ltremains proper-subset); fixturesset_le.fzn/set_lt.fzn+ CI smoke. SetLexReifPropagatorposts the negated lex relation when reif is false (¬(A≤B)≡B<A,¬(A<B)≡B≤A); fixtureset_le_reif.fzn+ CI smoke.float_ceil/floor/roundreverse-project integer output holes onto singleton preimages; unary reverse projection keeps pre-tighten holes so endpoint sync cannot drop them.FloatMinMaxPropagatorreverse-projects result holes onto an operand when the other side cannot realize that value as the min/max; handwrittenfloat_min_hole.fzn+ CI smoke.float_absreverse-projects result holesh > 0to both±hon the input (including domains that straddle zero); fixed nonnegative images tighten to the abs preimage hull.float_divreverse-projects viaa = c·bandb = a/c(when0 ∉ Dom(c));FloatDomain::dividemaps divisor holes when the dividend is fixed; handwrittenfloat_div.fzn+ CI smoke.float_sin/float_cosreverse-project a fixed image onto the unique preimage when the input domain is locally monotonic; handwrittenfloat_sin_fixed.fzn+ CI smoke.int2floatkeeps discrete holes aligned both ways (missing ints punch float holes; float holes remove ints); handwrittenint2float.fzn+ CI smoke.ceil/floor/roundwide spans (>10 000 integers) still shrink hole-emptied image endpoints via bounded end scans (interior remains hole-free).FloatDomainbound tightening that lands on a hole advances past it (pinning to a hole empties the domain).- Float
array_elementtreats a singleton bound-overlap that lands on a hole as disjoint (index prune); handwrittenarray_float_element_prune.fzn+ CI smoke. float_min/float_maxforward images drop a hole when one operand forbids it and the other lies entirely above (min) / below (max) that hole; handwrittenfloat_max_hole.fzn+ CI smoke.float_lin_eqaffine hole sharing ignores unfixed zero-coeff terms so two free nonzero-coeff variables still link; handwrittenfloat_lin_eq_zero_coeff.fzn+ CI smoke.float_plus/float_div/float_timesreverse-project using pre-tighten result holes (same pattern as unary); handwrittenfloat_cos_fixed.fzn+ CI smoke.float_eqshares pre-tighten holes so a hole that bound sync would drop at a new endpoint is still mirrored onto the other side.- FlatZinc
float_searchprecision is applied during DFS: floats whose domain width is at most the precision are fixed (value from the active ordering: min/max endpoints or midpoint); handwrittenfloat_search_precision.fzn+ CI smoke. - Nested
float_searchprecision insideseq_searchis kept per phase (and lifts a global fallback when standalonefloat_searchis absent); handwrittenseq_float_search_precision.fzn+ CI smoke. - When a float domain reaches
float_searchprecision, DFS assigns lower/upper/midpoint according to the active value ordering (indomain_min/indomain_max/ split-style). - Float
indomain_intervalsplits at the leftmost interior hole (first contiguous component) instead of the hole nearest the midpoint. float_min/float_maxsync_equalkeeps pre-tighten holes when bound sync would drop them (parity withfloat_eq); handwrittenfloat_min_sync_hole.fzn+ CI smoke.- Float domain
size()for MRV / anti-first-fail uses coarse width buckets (plus holes) instead of a constant2for every unfixed float. - Variable selectors
smallest/largest/max_regretuse float bounds (scaled keys / width proxy) instead of ignoring non-int domains. - The same selectors also use set cardinality (
card_min/card_max) and undecided membership count formax_regret. float_leshares holes when ≤ collapses both sides to the same fixed value;float_netreats singleton overlap excluded by a hole as already separated.- DFS bumps VSIDS activity and WDEG weights on float/set wipeouts (nogood learning remains int-only).
- Activity (VSIDS) tie-breaks prefer the earlier decision variable, matching Dom / input-order stability.
- Float phase saving: when
phase_savingis on, precision fixes reuse the last successful float assignment if it remains in-domain. float_abswith a fixed nonnegative image forces the unique remaining preimage when the opposite sign is a hole; handwrittenfloat_abs_unique.fzn+ CI smoke.ceil/floor/roundreverse-project unfixed output integer bounds onto the input (not only fixed images / singleton holes).float_eq_reifinfers false when the only overlapping IEEE point is a hole on either side (FloatNeparity).int2floatalways maps explicit float holes onto the int domain and punches endpoint float holes on wide spans.set_eq_reif/set_netreat disjoint cardinality bounds as definite inequality.set_subset_reifforces reif=false when ⊆ is card-impossible (|A| + |glb(B)\lub(A)| > |B|).set_in_reif=falseprunes GLB members from the value domain (mirrorsreif=trueLUB pruning).set_ltforces the sole extra superset element when the subset is fixed and|B| = |A| + 1with one LUB candidate left.float_le_reifinfers reif using hole-aware admissible endpoints (min/maxadmissible IEEE points).- Reified float linear (
le/ge/eq) entailment uses hole-aware admissible term sums. set_lexwith fixed right forces required left members when omitting them breaks≤_lex/<_lex.- DFS float precision fixes avoid midpoint holes by choosing an admissible representative before branching stops.
float_lt_reifis now native, soreif = 0prunes asleft >= rightinstead of relying on a weaker decomposition.set_eq_reif(reif=0)now breaks the last equalizer, matching nativeset_nepruning strength.set_subset_reifalso detects when|A|_minexceeds the sharedlub(A) ∩ lub(B)capacity.- Float
indomain_intervalnow keeps preferring the leftmost component when precision assignment stops branching. set_subset_reif(reif=0)can now force a unique outside witness into the subset when ¬⊆ needs one.float_eq_reifcan now inferreif=1when both sides are “pinched” to the same single admissible IEEE value by holes.set_eq_reif(reif=0)can now force a unique outsider into the other set when that is the only remaining witness for!=.set_subset_reif(reif=0)also forces a unique blocker out of the superset when that is the only remaining ¬⊆ witness.- Float phase saving now reorders wide float branch cuts toward the saved side, not just final precision fixes.
float_le_reif(reif=0)now prunes using admissible endpoints instead of raw hull bounds, avoiding over-pruning against holed maxima.- Native
set_nenow also forces a unique outsider into the other set when that is the only remaining witness for inequality. float_lt_reif(reif=1)now prunes from admissible supports instead of raw hull maxima, preserving feasible right-side values.float_lenow tightens against admissible endpoints instead of raw hull bounds, strengthening native≤andfloat_lt_reif(reif=0)via≥.
array_var_set_elementindexes from 1 (was incorrectly 0-based like_nonshifted).array_var_bool_elementindexes from 1 (was incorrectly 0-based like_nonshifted).array_int_element/array_var_int_element/array_bool_element/array_float_element/array_var_float_elementindex from 1 (were incorrectly 0-based).SetEqReifPropagatoronly treats sets as definitely unequal on GLB/LUB conflicts (not mere domain asymmetry), assigns the reif literal when equality is decided, and syncs cardinality when reif is true.SetSubsetReifPropagatorassigns the reif on definite subset/violation, syncs cardinality when reif is true, and fails when reif is false but subsethood is inevitable.SetInReifPropagatorassigns the reif from membership facts (value outside LUB ⇒ false, in GLB ⇒ true) instead of failing, and forces set out when reif is false.SetInPropagatorno longer forces GLB members out when they are outside the integer domain (unsound forvalue ∈ S); whenSis fixed it prunes the value toS's members.- Lexicographic search restores the engine after each objective's branch-and-bound so interior optima are pinned correctly before optimizing the next priority.
FloatLeReifPropagatorwith reif=false now tightens the correct float bounds (strict greater-than encoding).- DFS
solve_eachset branching no longer applies in/out forces eagerly before trail marks (both membership branches are explored). SetIntersectPropagator/SetSubsetPropagatorcardinality bounds use|lub \ glb|outside estimates (were unsound|lub \ lub|); intersect forces result membership only from shared GLB.- FlatZinc
set_diffpostsleft ⊆ result ∪ rightinstead of incorrectly requiringresult ∪ right ⊆ left. - Failed
force_set_in/force_set_outno longer replace domains with a valid empty set (which wiped cardinality); DFS skips int nogood learning on set/float conflicts. FloatDomain::rounduses trueroundbounds (with constant collapse) instead of the loosefloor + [0,1]envelope.
- COMPATIBILITY.md documents float IEEE-hole projection per constraint family; README no longer lists shipped float array/membership builtins as gaps.
- COMPATIBILITY.md clarifies
set_diffdecomposition (L ⊆ R ∪ B) and non-decision auxiliaries. - README FlatZinc section notes that decomposition auxiliaries are not search decision variables.
ceil/floor/roundstill drop sparse holes when the map is non-constant (preimages are intervals); wide spans keep a hole-free interior except endpoint shrink (addressed in Unreleased).- Float propagation remains interval-based (sound, not exact real arithmetic).
1.0.0 - 2026-07-13
- Full MiniZinc FlatZinc 1.6 builtin support for the standard library workflow (int / bool / set / float).
- Set parameters and extended predicate parameter types (
var set,var float). - Float and set single-objective optimization (
minimize/maximize). - Stdlib global decompositions:
count,among,at_least,at_most,distribute,nvalue,sort, lexicographic and monotonicity globals. - Integer / float primitives:
int_plus,int_lin_ne,int_min/int_max/int_pow, genericmin/max, full bool builtin set. - Float core: interval arithmetic, linear constraints, reified forms, unary transcendental ops (
float_sin,float_log2, …). - Float array builtins:
array_float_element,array_var_float_element,array_float_maximum,array_float_minimum. - Float membership:
float_dom,float_in. - Set builtins beyond union/intersect: equality, reified comparisons,
set_in, etc. - MiniZinc stdlib corpus (
benchmarks/minizinc/stdlib/) with bundled FlatZinc fixtures and CIminizinc-stdlibjob. scripts/flatzinc-full-compat-report.shacceptance gate for models + stdlib.
set_inpropagation no longer requires the int domain to contain every set GLB element.- Float linear
<=/>=propagators now tighten the correct interval bounds.
functionandtesttop-level declarations are skipped during parse (likeannotation).- Unknown
min/maxpredicate calls dispatch toint_*orfloat_*by variable domain. - Optimization objectives use typed
ObjectiveSpec(int, float, set cardinality) with JSON/plain CLI output.
- Lexicographic and Pareto multi-objective search remain int-only.
- Table-based int decompositions (
int_times,int_pow, …) cap at 10 000 tuples. - Float propagation is interval-based (conservative, not exact real arithmetic).
- FlatZinc primitive constraints:
int_abs,int_times,int_div,int_mod. - FlatZinc bool primitives:
bool_not,bool_and,bool_or. - FlatZinc
automatonglobal (compiled viaregularpropagator). boolandfloatFlatZinc parameters.- Recursive nested predicate expansion with full constraint substitution.
- Top-level
annotationstatements are skipped during parse. decomposemodule inpropaga-flatzincfor primitive constraint lowering.- Compile corpus test (
crates/propaga-flatzinc/tests/compile_corpus.rs). - MiniZinc model corpus under
benchmarks/minizinc/models/. scripts/flatzinc-compat-report.shfor local MiniZinc compatibility checks.- Regression benchmarks:
int_abs.fzn,bool_logic.fzn,int_times.fzn,nested_predicate.fzn,automaton_chain.fzn.
incompletesearch annotations are tolerated (treated likecomplete).- Unknown predicates now produce explicit compile errors instead of silent
PredicateCallleftovers.
int_times/int_div/int_moduse table decomposition with a 10_000 tuple cap.- Float parameters are parsed but not yet usable in float constraint expressions.
function/testtop-level declarations remain unsupported.
- Set global propagators:
set_union,set_intersect. - Float global propagator:
float_timeswith interval arithmetic. - Model API:
set_union,set_intersect,float_times. - FlatZinc:
set_union,set_intersect,float_timesconstraints. - Benchmarks:
set_union.fzn,set_intersect.fzn,float_times.fzn. FloatDomain::timesandFloatDomain::divideinterval helpers.
- Set/float optimization objectives remain int-only.
- Float globals beyond
float_timesnot yet supported. - Set globals beyond union/intersect/card/subset not yet supported.
AnyDomainengine storage for int, set, and float variables.SetIntervalDomainwith GLB/LUB/cardinality representation.- Set propagators:
SetCardPropagator,SetSubsetPropagator. - Float propagators:
FloatLePropagator,FloatEqPropagator. - Model API:
set_var,float_var,set_card,set_subset,float_le,float_eq. - Typed search branching and
AssignmentValuein solutions. - FlatZinc subset: set/float variables and
set_card,set_subset,float_le,float_eq. - Benchmarks:
set_cardinality.fzn,float_bounds.fzn.
- Optimization (minimize/maximize/Pareto) remains int-only.
- Float propagation is interval-only (no global float constraints).
- Set globals beyond
set_card/set_subsetnot yet supported.
- Pareto-front multi-objective enumeration (
ParetoOptimization,Model::pareto_optimize). - FlatZinc
solve :: pareto([...]) satisfyannotation and CLI JSONpareto_solutions. regularglobal constraint (DFA compiled to table propagator) with FlatZinc compile support.- LCG clause propagator posting during search when
SearchConfig::clause_learningis enabled. - WASM demo build script (
scripts/build-wasm.sh) and GitHub Pages deploy workflow. - Benchmarks:
regular_chain.fzn,pareto_biobjective.fzn.
ClauseStorelearned clauses are posted asClausePropagatorinstances on the engine.- WASM demo page includes an N-Queens solver section.
- Set/float domains are not yet wired into the propagation engine.
- Pareto enumeration collects all solutions before filtering (practical for small fronts).
0.3.0 - 2026-07-05
EngineCheckpointAPI withcheckpoint,restore_checkpoint, andfork_at_checkpointfor parallel search workers.- Parallel portfolio search using rayon when
--workers > 1(FlatZincsolve, Sudoku, and portfolio API). - Multi-constraint FlatZinc predicate bodies (
constraint A /\ constraint Band semicolon chains). - FlatZinc lexicographic multi-objective (
solve minimize x, y); CLI JSON includesobjective_values. - Lazy clause pruning in DFS via
SearchConfig::clause_learning. - Benchmarks:
predicate_multi.fzn,lexicographic_multi.fzn.
CompiledInstance.objectivereplaced byobjectives: Vec<ObjectiveSpec>.SolveGoal::Minimize/Maximizenow hold expression lists for lexicographic goals.- Propagators implement
DynClonefor engine fork at checkpoint.
- Set/float domains are not yet wired into the propagation engine.
- Predicate bodies still inline-expand only; nested predicate calls in bodies are rejected.
clause_learningprunes branches but does not post learned clauses as propagators yet.
0.2.0 - 2026-07-02
- Schedule JSON output for
propaga schedule --format json. - Value orderings
indomain_splitandindomain_median. - Activity-based variable ordering (VSIDS-style) and CLI/FlatZinc
activityselector. - Restart policies
restart_linearandrestart_on_solution. - FlatZinc
bool_searchannotation support. - Global propagators:
circuit,inverse,diffn. - Predicate inline expansion for simple single-constraint bodies.
- Cumulative constraints with variable duration/height arrays.
- Portfolio search (
--workers,--deterministic) and lexicographic multi-objective optimization API. - Set and float domain types in
propaga-domains. propaga-wasmcrate with Sudoku and N-Queens WASM bindings and browser demo.- Lazy clause generation spike (
ClauseStoreinpropaga-search).
- FlatZinc unknown constraint names become predicate calls when a matching predicate is declared.
- Portfolio search runs configurations sequentially on a shared engine (parallel rayon workers require engine snapshots).
- Set/float domains are not yet wired into the propagation engine.
- Predicate bodies support a single primitive constraint only.
0.1.0 - 2026-06-21
- Workspace of eight crates:
propaga-core,propaga-domains,propaga-engine,propaga-propagators,propaga-search,propaga-model,propaga-flatzinc,propaga-cli. - Propagation engine with explanation-aware trail and event scheduling.
- Domain implementations: interval, bitset, and hybrid.
- Built-in propagators: equality, linear, ordering, reified, all-different (GAC), GCC, table, element, cumulative, disjunctive, nogood.
- Search: MRV/DOM/DOM-W-DEG variable ordering, LCV value ordering, first-UIP nogood learning, Luby restarts, phase saving, branch-and-bound optimization.
- High-level
ModelAPI for constraint posting and solving. - FlatZinc subset parser and compiler with satisfy/minimize/maximize.
- CLI (
propaga):sudoku,n-queens,solve(single file and batch directory),schedule(JSON). - CLI flags:
--stats,--format json,--all,--solutions,--time-limit,--no-learning,--restarts,--var-ordering,--value-ordering,--no-phase-saving. - Scheduling JSON format with cumulative, sequential, and disjunctive modes.
- Criterion benchmarks for propagator micro-benchmarks.
- FlatZinc compatibility matrix at
benchmarks/minizinc/COMPATIBILITY.md.
- FlatZinc is a subset: no set/float variables in the engine, predicate bodies limited to one primitive constraint.
- Multi-objective optimization supports lexicographic API; FlatZinc multi-objective directives are not yet parsed.
- See ROADMAP.md for planned features.