@@ -300,7 +300,45 @@ def GenericDispatch(default_factory) -> SortDispatch:
300300"""Sort based dispatch for `Exists` quantifier."""
301301# smt.ExprRef.exists = lambda vs, body: exists(vs, body)
302302
303- induct = SortDispatch (name = "induct" )
303+
304+ def induct_seq (a : smt .SeqRef , P ) -> kd .kernel .Proof :
305+ """
306+ >>> x = smt.Const("x", smt.SeqSort(smt.IntSort()))
307+ >>> induct(x, lambda s: smt.Length(s) >= 0)
308+ |= Implies(And(Length(Empty(Seq(Int))) >= 0,
309+ ForAll(z!..., Length(Unit(z!...)) >= 0),
310+ ForAll([x!..., y!...],
311+ Implies(And(Length(x!...) >= 0,
312+ Length(y!...) >= 0),
313+ Length(Concat(x!..., y!...)) >= 0))),
314+ Length(x) >= 0)
315+ """
316+ assert isinstance (a , smt .SeqRef )
317+ sort = a .sort ()
318+ T = sort .basis ()
319+ z = smt .FreshConst (T , prefix = "z" )
320+ x , y = smt .FreshConst (sort , prefix = "x" ), smt .FreshConst (sort , prefix = "y" )
321+ return kd .axiom (
322+ smt .Implies (
323+ smt .And (
324+ P (smt .Empty (sort )),
325+ QForAll ([z ], P (smt .Unit (z ))),
326+ QForAll ([x , y ], P (x ), P (y ), P (smt .Concat (x , y ))),
327+ ),
328+ # -------------------------------------------------
329+ P (a ),
330+ )
331+ )
332+
333+
334+ def induct_default (x , P ):
335+ if isinstance (x , smt .SeqRef ):
336+ return induct_seq (x , P )
337+ else :
338+ raise NotImplementedError ("No default induct implementation for sort" , x .sort ())
339+
340+
341+ induct = SortDispatch (name = "induct" , default = induct_default )
304342"""Sort based dispatch for induction principles. Should instantiate an induction scheme for variable x and predicate P"""
305343smt .ExprRef .induct = lambda x , P : induct (x , P ) # type: ignore
306344
0 commit comments