Skip to content

Comments

Moving formulas in LIRA theory towards core LIRA#77

Open
nclskoh wants to merge 20 commits intozkincaid:flintfrom
nclskoh:flint/standardize-linearization
Open

Moving formulas in LIRA theory towards core LIRA#77
nclskoh wants to merge 20 commits intozkincaid:flintfrom
nclskoh:flint/standardize-linearization

Conversation

@nclskoh
Copy link
Contributor

@nclskoh nclskoh commented Feb 15, 2026

Core LIRA formulas have terms in LRA and atoms in LIA (i.e., LRA atoms + is_int predicates). This PR refactors some components to use formulas that are closer to core LIRA.

  • Iteration.Solver currently allows LIRA formulas in the solver to have floor and mod terms, which makes abstraction complex. This PR changes pre-processing of the formula so that only core LIRA formulas are in the solver. Iteration.Solver is used for e.g., summarizing loops.
  • Quantifier elimination (Quantifier.ml) currently introduces divisibility constraints in the form of t % c = 0, which comingles divisibility with equality. This PR changes it to Int(t/c).

TODO: We should have a future PR that removes the introduction of floor symbols when doing QE for LIA formulas. TerminationDTA.mp has to eliminate floor right now because of this, and it is correct for integer division up to divisor = 10, but is unsound in the general case, because new symbols are introduced.

(* TODO: floor can be present in transition due to e.g., integer division.
Change to eliminate_floor_mod_div?
*)
mk_and srk [SrkSimplify.eliminate_floor srk (K.guard transition);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently left as-is. Is it sound to eliminate floor using new symbols here, and should we also eliminate mod?

(mk_real srk QQ.zero)
V.scalar_mul (QQ.inverse (QQ.of_zz divisor)) linterm
|> Linear.of_linterm srk
|> mk_is_int srk
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change t % c = 0 to Int(t/c).

in
mk_and srk (formula::floor_constraints)

let simplify_integer_atom srk op s t =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove simplify_integer_atom from SrkSimplify. The implementation is copied from Quantifier.ml, and is no longer necessary in view of the current interface for Quantifier.

division with a dominator less than [max]. *)
val eliminate_idiv : ?max:int -> 'a context -> 'a formula -> 'a formula

(** Purify floor functions in an expression: replace each function
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used outside of SrkSimplify.ml, and this overlaps somewhat with Syntax.eliminate_floor_mod_div, so we should probably expose the logic there instead when needed.

let lower_bound = mk_leq srk (mk_real srk QQ.zero) fractional_part in
let upper_bound = mk_lt srk fractional_part (mk_real srk QQ.one) in
[mk_eq srk t sum; lower_bound; upper_bound]
(* floor(t) --> [s = floor(t)], iff t - 1 < s <= t /\ Int(s); Int(s) is handled by type of symbol *)
Copy link
Contributor Author

@nclskoh nclskoh Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduce the number of symbols introduced.

module XSeq = struct
let seq_of_exp modulus lambda =
UltimatelyPeriodic.unfold (fun power -> (power * lambda) mod modulus) 1
let seq_of_exp modulus lambda =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting changes up to line 295

|> Quantifier.mbp srk (fun s -> Symbol.Set.mem s gz_symbols_set)
|> SrkSimplify.simplify_dda srk
|> SrkSimplify.eliminate_floor srk
(*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SrkSimplify.eliminate_floor is kept as-is here, because it removes floor without introducing new symbols when it arises from integer division with divisor up to 10. But this is otherwise unsound, and we should change Quantifier.mbp to not introduce floor when the input formula is LIA, and remove SrkSimplify.eliminate_floor here.

| `Or xs -> Periodic.mapn (mk_or srk) xs
| `Not x -> Periodic.map (mk_not srk) x
| `Atom (`Arith (op, s, t)) ->
let normalize typ v =
Copy link
Contributor Author

@nclskoh nclskoh Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline the logic in simplify_integer_atom for handling inequalities and equations with LRA terms, i.e., no mod/divisibility constraints. Logic for divisibility is moved to IsInt below.

XSeq.seq_of_compare_atom srk predicate cf term_of_dim
| `Quantify _ -> failwith "should not see quantifiers in the TF"
| `Atom (`ArrEq _) -> failwith "should not see ArrEq in the TF"
| `Atom (`IsInt t) ->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle divisibility constraints.

Copy link
Contributor Author

@nclskoh nclskoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments on what's changed.

@nclskoh nclskoh marked this pull request as ready for review February 16, 2026 02:51
@nclskoh nclskoh changed the title Flint/standardize linearization Moving formulas in LIRA theory towards core LIRA Feb 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant