Scope preservation for π-calculus names and processes
DefinitionName scoped at a binder depth#✓fully proved
A name refers only to the depth surrounding binders or to a free
constant. At depth zero, no variable is permitted.
def Name.ClosedAt (depth : ℕ) : Name → Prop
| .const _ => True
| .var i => i < depth
inductive Name where
| const (n : ℕ) : Name
| var (i : ℕ) : Name
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:45
Uses 1 · Used by 210
DefinitionLocally closed processes at a binder depth#✓fully proved
Every variable refers to an enclosing input/restriction binder.
ClosedAt 0 permits free constants, but no dangling de Bruijn variables.
def Proc.ClosedAt (depth : ℕ) : Proc → Prop
| .nil => True
| .out a b p =>
a.ClosedAt depth ∧ b.ClosedAt depth ∧ Proc.ClosedAt depth p
| .inp a p => a.ClosedAt depth ∧ Proc.ClosedAt (depth + 1) p
| .par p q => Proc.ClosedAt depth p ∧ Proc.ClosedAt depth q
| .nu p => Proc.ClosedAt (depth + 1) p
| .repl p => Proc.ClosedAt depth p
| .sum p q => Proc.ClosedAt depth p ∧ Proc.ClosedAt depth q
inductive Proc where
| nil : Proc
| out (a b : Name) (p : Proc) : Proc
| inp (a : Name) (p : Proc) : Proc
| par (p q : Proc) : Proc
| nu (p : Proc) : Proc
| repl (p : Proc) : Proc
| sum (p q : Proc) : Proc
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:52
Uses 3 · Used by 19
TheoremLifting fixes an in-scope name#✓fully proved
Lifting above the ambient binder depth fixes an in-scope name.
theorem liftName_eq_of_closedAt {a : Name} {k : ℕ}
(h : a.ClosedAt k) : liftName k a = a
inductive Name where
| const (n : ℕ) : Name
| var (i : ℕ) : Name
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:45
def liftName (cutoff : ℕ) : Name → Name
| .const n => .const n
| .var i => if cutoff ≤ i then .var (i + 1) else .var i
CSLibExt/Languages/PiCalculus/Basic.lean:64
Uses 3 · Used by 1
TheoremLifting fixes a locally closed process#✓fully proved
Lifting above the surrounding binders fixes a locally closed process. At depth zero, insertion under a fresh binder cannot capture its names.
theorem liftProc_eq_of_closedAt {p : Proc} {k : ℕ}
(h : Proc.ClosedAt k p) : liftProc k p = p
inductive Proc where
| nil : Proc
| out (a b : Name) (p : Proc) : Proc
| inp (a : Name) (p : Proc) : Proc
| par (p q : Proc) : Proc
| nu (p : Proc) : Proc
| repl (p : Proc) : Proc
| sum (p q : Proc) : Proc
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:52
def Proc.ClosedAt (depth : ℕ) : Proc → Prop
| .nil => True
| .out a b p =>
a.ClosedAt depth ∧ b.ClosedAt depth ∧ Proc.ClosedAt depth p
| .inp a p => a.ClosedAt depth ∧ Proc.ClosedAt (depth + 1) p
| .par p q => Proc.ClosedAt depth p ∧ Proc.ClosedAt depth q
| .nu p => Proc.ClosedAt (depth + 1) p
| .repl p => Proc.ClosedAt depth p
| .sum p q => Proc.ClosedAt depth p ∧ Proc.ClosedAt depth q
CSLibExt/Languages/PiCalculus/Scoping.lean:46
def liftProc (cutoff : ℕ) : Proc → Proc
| .nil => .nil
| .out a b p => .out (liftName cutoff a) (liftName cutoff b) (liftProc cutoff p)
| .inp a p => .inp (liftName cutoff a) (liftProc (cutoff + 1) p)
| .par p q => .par (liftProc cutoff p) (liftProc cutoff q)
| .nu p => .nu (liftProc (cutoff + 1) p)
| .repl p => .repl (liftProc cutoff p)
| .sum p q => .sum (liftProc cutoff p) (liftProc cutoff q)
CSLibExt/Languages/PiCalculus/Basic.lean:70
Uses 7 · Used by 1
TheoremLifting preserves name scoping#✓fully proved
Inserting a binder at any cutoff preserves name scoping in the larger environment.
theorem Name.ClosedAt.lift {n k : ℕ} {b : Name} (h : b.ClosedAt n) :
(liftName k b).ClosedAt (n + 1)
inductive Name where
| const (n : ℕ) : Name
| var (i : ℕ) : Name
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:45
def liftName (cutoff : ℕ) : Name → Name
| .const n => .const n
| .var i => if cutoff ≤ i then .var (i + 1) else .var i
CSLibExt/Languages/PiCalculus/Basic.lean:64
Uses 3 · Used by 10
TheoremName substitution preserves scoping#✓fully proved
Removing the binder at k ≤ n preserves name scoping when its
replacement is scoped in the remaining environment.
theorem Name.ClosedAt.subst {n k : ℕ} {b x : Name}
(hb : b.ClosedAt n) (hx : x.ClosedAt (n + 1)) (hk : k ≤ n) :
(substName b k x).ClosedAt n
inductive Name where
| const (n : ℕ) : Name
| var (i : ℕ) : Name
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:45
def substName (n : Name) : ℕ → Name → Name
| _, .const m => .const m
| cutoff, .var i =>
if i < cutoff then .var i
else if i = cutoff then n
else .var (i - 1)
CSLibExt/Languages/PiCalculus/Basic.lean:83
Uses 3 · Used by 12
TheoremLifting preserves process scoping#✓fully proved
Shifting a process past a new binder preserves scoping. Inner input
and restriction binders increase the cutoff as in Basic.liftProc.
theorem Proc.ClosedAt.lift {p : Proc} {n k : ℕ}
(h : p.ClosedAt n) : (liftProc k p).ClosedAt (n + 1)
inductive Proc where
| nil : Proc
| out (a b : Name) (p : Proc) : Proc
| inp (a : Name) (p : Proc) : Proc
| par (p q : Proc) : Proc
| nu (p : Proc) : Proc
| repl (p : Proc) : Proc
| sum (p q : Proc) : Proc
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:52
def liftProc (cutoff : ℕ) : Proc → Proc
| .nil => .nil
| .out a b p => .out (liftName cutoff a) (liftName cutoff b) (liftProc cutoff p)
| .inp a p => .inp (liftName cutoff a) (liftProc (cutoff + 1) p)
| .par p q => .par (liftProc cutoff p) (liftProc cutoff q)
| .nu p => .nu (liftProc (cutoff + 1) p)
| .repl p => .repl (liftProc cutoff p)
| .sum p q => .sum (liftProc cutoff p) (liftProc cutoff q)
CSLibExt/Languages/PiCalculus/Basic.lean:70
TheoremSubstitution at any cutoff preserves process scoping#✓fully proved
Capture-avoiding substitution removes one ambient binder while preserving every name's scope, including under input and restriction.
theorem Proc.ClosedAt.substProc {p : Proc} {n k : ℕ} {b : Name}
(h : p.ClosedAt (n + 1)) (hb : b.ClosedAt n) (hk : k ≤ n) :
(PiCalculus.substProc b k p).ClosedAt n
inductive Proc where
| nil : Proc
| out (a b : Name) (p : Proc) : Proc
| inp (a : Name) (p : Proc) : Proc
| par (p q : Proc) : Proc
| nu (p : Proc) : Proc
| repl (p : Proc) : Proc
| sum (p q : Proc) : Proc
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:52
inductive Name where
| const (n : ℕ) : Name
| var (i : ℕ) : Name
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:45
def substProc (n : Name) : ℕ → Proc → Proc
| _, .nil => .nil
| cutoff, .out a b p =>
.out (substName n cutoff a) (substName n cutoff b) (substProc n cutoff p)
| cutoff, .inp a p =>
.inp (substName n cutoff a) (substProc (liftName 0 n) (cutoff + 1) p)
| cutoff, .par p q => .par (substProc n cutoff p) (substProc n cutoff q)
| cutoff, .nu p => .nu (substProc (liftName 0 n) (cutoff + 1) p)
| cutoff, .repl p => .repl (substProc n cutoff p)
| cutoff, .sum p q => .sum (substProc n cutoff p) (substProc n cutoff q)
CSLibExt/Languages/PiCalculus/Basic.lean:96
Uses 9 · Used by 1
TheoremInstantiating the innermost binder preserves process scoping#✓fully proved
Instantiating the innermost binder preserves process scoping.
theorem Proc.ClosedAt.subst {p : Proc} {n : ℕ} {b : Name}
(h : p.ClosedAt (n + 1)) (hb : b.ClosedAt n) :
(PiCalculus.subst p b).ClosedAt n
inductive Proc where
| nil : Proc
| out (a b : Name) (p : Proc) : Proc
| inp (a : Name) (p : Proc) : Proc
| par (p q : Proc) : Proc
| nu (p : Proc) : Proc
| repl (p : Proc) : Proc
| sum (p q : Proc) : Proc
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:52
inductive Name where
| const (n : ℕ) : Name
| var (i : ℕ) : Name
deriving DecidableEq, Repr
CSLibExt/Languages/PiCalculus/Basic.lean:45
def subst (p : Proc) (n : Name) : Proc := substProc n 0 p
CSLibExt/Languages/PiCalculus/Basic.lean:108
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.