Zulip Chat Archive

Stream: new members

Topic: Design pattern for further constraining inductive predicate


pandaman (Aug 14 2024 at 12:56):

Hello. I have an inductive predicate that represents a reflexive transitive closure of a relation:

inductive Closure (R : Nat  Nat  Prop) : Nat  Nat  Prop where
  | refl : Closure R a a
  | cons : R a b  Closure R b c  Closure R a c

I'd like to define another predicate that restricts the left hand side of each step using a predicate P. One way to do this is to embed the predicate like this:

inductive RestrictedClosure (R : Nat  Nat  Prop) (P : Nat  Prop) : Nat  Nat  Prop where
  | refl : RestrictedClosure R P a a
  | cons : P a  R a b  RestrictedClosure R P b c  RestrictedClosure R P a c

However, it's a bit annoying that we need to define a new predicate. Alternative way is to define Closure as Type and attach a predicate like this

inductive Closure' (R : Nat  Nat  Prop) : Nat  Nat  Type where
  | refl : Closure' R a a
  | cons : R a b  Closure' R b c  Closure' R a c

def Closure'.Restricted (P : Nat  Prop) : Closure' R a b  Prop
  | .refl => True
  | .cons _ cls => P a  cls.Restricted P

This way, we don't need to define a separate predicate, but Closure' is no longer a subsingleton and I'm not sure how that affects my proofs using Closure. Does anyone have ideas for simplifying the set up like this?

To give a bit of context, my project involves an NFA and I'd like to define a predicate like "we have a path where each state satisfies some condition". Currently, I'm embedding the condition in the definition (example), but wondering if there is another way.

pandaman (Aug 15 2024 at 10:03):

#new members > What do propositional types do for us? answers some questions about Prop vs Type.

Chris Bailey (Aug 15 2024 at 10:32):

Can you just declare the more complicated one first and define the simpler one with it?

inductive RestrictedClosure (R : Nat  Nat  Prop) (P : Nat  Prop) : Nat  Nat  Prop where
  | refl : RestrictedClosure R P a a
  | cons : P a  R a b  RestrictedClosure R P b c  RestrictedClosure R P a c

-- potentially want to make this reducible/an abbrev
def Closure (R) := RestrictedClosure R (fun _ => True)

pandaman (Aug 16 2024 at 10:19):

Well, it doesn't cover the case like when I want to constrain both side. Maybe I should just include both in P to make it maximally generic

Chris Bailey (Aug 16 2024 at 10:21):

Can you elaborate on what you mean by constraining both sides?

pandaman (Aug 16 2024 at 11:42):

-- We might need to define another predicate if I want to allow P to look at both a and b.
-- That being said, this is more general than RestrictedClosure so it's enough to have this.
inductive RestrictedClosure' (R : Nat  Nat  Prop) (P : Nat  Nat  Prop) : Nat  Nat  Prop where
  | refl : RestrictedClosure R P a a
  | cons : P a b  R a b  RestrictedClosure R P b c  RestrictedClosure R P a c

Daniel Weber (Aug 16 2024 at 13:37):

Can't you just apply Closure to P \and R?


Last updated: May 02 2025 at 03:31 UTC