Fine paths in local tableaux and in tableaux #
This file collects helper definitions and lemmas that are used in Pdl.InterpolationCluster
to define interpolants for proper clusters (Section 9 of the paper).
The two main definitions are LocalPathIn, for paths to arbitrary (also intermediate) nodes
of a LocalTableau, and FinePathIn, for the nodes of a whole Tableau in the fine sense,
i.e. including those nodes inside a local tableau that a loc step jumps over.
Paths inside a local tableau #
The Tableau type applies a whole LocalTableau in one loc step, and thus the PathIn
type — and with it the edge relation ⋖_ and the clusters defined via ◃ — "jumps over"
the intermediate nodes inside a local tableau. For the quasi-tableau in Definition 9.8 we
need those intermediate nodes, because it is only there that each rule application is
either a left or a right rule.
We therefore first define LocalPathIn, the analogue of PathIn for local tableaux, in
the same spirit as LocalTableau.paths which is used for the completeness proof.
Note that in contrast to LocalTableau.paths we here keep the nodes themselves and not
only the sequents labelling them, so that we can still connect them to PathIn.
A path inside a LocalTableau, pointing at an arbitrary node of it — in contrast to
LocalTableau.paths which only goes to the end nodes.
- nil {X : Sequent} {lt : LocalTableau X} : LocalPathIn lt
- cons {X : Sequent} {lra : LocalRuleApp} {X_def : X = lra.X} {next : (Y : Sequent) → Y ∈ lra.C → LocalTableau Y} {Y : Sequent} (Y_in : Y ∈ lra.C) (tail : LocalPathIn (next Y Y_in)) : LocalPathIn (LocalTableau.byLocalRule lra X_def next)
Instances For
Equations
- One or more equations did not get rendered due to their size.
- instDecidableEqLocalPathIn.decEq LocalPathIn.nil LocalPathIn.nil = isTrue ⋯
- instDecidableEqLocalPathIn.decEq LocalPathIn.nil (LocalPathIn.cons Y_in tail) = isFalse ⋯
- instDecidableEqLocalPathIn.decEq (LocalPathIn.cons Y_in tail) LocalPathIn.nil = isFalse ⋯
Instances For
The sequent at the node a local path is pointing at.
Equations
- LocalPathIn.nil.last = X
- (LocalPathIn.cons Y_in tail).last = tail.last
Instances For
The local tableau rooted at the node a local path is pointing at.
Equations
- LocalPathIn.nil.ltAt = lt
- (LocalPathIn.cons Y_in tail).ltAt = tail.ltAt
Instances For
Is this the empty local path, i.e. does it point at the root of the local tableau?
Equations
- LocalPathIn.nil.isNilB = true
- (LocalPathIn.cons Y_in tail).isNilB = false
Instances For
Is a local rule applied at the root of this local tableau?
Equations
- (LocalTableau.byLocalRule lra X_def next).hasRule = True
- (LocalTableau.sim a).hasRule = False
Instances For
Equations
- One or more equations did not get rendered due to their size.
A local path is internal iff a local rule is applied at the node it points at, i.e. iff that node is not a leaf of the local tableau.
Equations
- lp.isInternal = lp.ltAt.hasRule
Instances For
Equations
If the local path points at a leaf then this gives the end node it reaches.
Equations
- LocalPathIn.nil.endNodeAt? = none
- LocalPathIn.nil.endNodeAt? = some ⟨X, ⋯⟩
- (LocalPathIn.cons Y_in tail).endNodeAt? = Option.map (fun (x : ↥(endNodesOf (next Y Y_in))) => match x with | ⟨Z, hZ⟩ => ⟨Z, ⋯⟩) tail.endNodeAt?
Instances For
The children of the node a local path points at, inside the same local tableau.
Equations
- LocalPathIn.nil.children = Finset.image (fun (x : ↥lra.C) => match x with | ⟨val, Y_in⟩ => LocalPathIn.cons Y_in LocalPathIn.nil) lra.C.attach
- LocalPathIn.nil.children = ∅
- (LocalPathIn.cons Y_in tail).children = Finset.image (LocalPathIn.cons Y_in) tail.children
Instances For
The sequents labelling the children of the root of a local tableau.
Equations
- (LocalTableau.byLocalRule lra X_def next).childLabels = lra.C
- (LocalTableau.sim a).childLabels = ∅
Instances For
The end nodes of the whole local tableau that are below a given local path.
Equations
- LocalPathIn.nil.endNodesBelow = (endNodesOf lt).attachList
- (LocalPathIn.cons Y_in tail).endNodesBelow = List.map (fun (x : ↥(endNodesOf (next Y Y_in))) => match x with | ⟨Z, hZ⟩ => ⟨Z, ⋯⟩) tail.endNodesBelow
Instances For
A leaf of a local tableau is the only end node below itself.
If an end node is below an internal node of a local tableau, then it is below one of the children of that node.
All internal nodes of a local tableau, i.e. those where a local rule is applied.
Compare allPaths for PathIn.
Equations
- One or more equations did not get rendered due to their size.
- internalLocalPaths (LocalTableau.sim a) = []
Instances For
Fine paths: all nodes of a tableau #
A FinePathIn points at a node of the tableau in the fine sense: it may also point at
an intermediate node inside a local tableau. Note that the end nodes of a local tableau
are not fine nodes of their own: in the Tableau type they are the roots of the tableaux
given by next, and that is where they show up here.
Hence a fine node is either
- an internal node of the local tableau applied at a
Tableau.locnode (inLoc), - a
Tableau.pdlnode (pdlHere), or - a
Tableau.lrepnode, i.e. a loaded-path repeat leaf (lrepHere), possibly below somelocandpdlsteps. Every node has exactly one representation as aFinePathIn.
A path in a tableau that may also stop at an intermediate node inside a LocalTableau.
- inLoc {Hist : History} {X : Sequent} {nrep : ¬flprep Hist X} {nbas : ¬X.basic} {lt : LocalTableau X} {next : (Y : Sequent) → Y ∈ endNodesOf lt → Tableau (X :: Hist) Y} (lp : LocalPathIn lt) (lp_int : lp.isInternal) : FinePathIn (Tableau.loc nrep nbas lt next)
- pdlHere {Hist : History} {X Y : Sequent} {nrep : ¬flprep Hist X} {bas : X.basic} {r : PdlRule X Y} {next : Tableau (X :: Hist) Y} : FinePathIn (Tableau.pdl nrep bas r next)
- lrepHere {Hist : History} {X : Sequent} {lpr : LoadedPathRepeat Hist X} : FinePathIn (Tableau.lrep lpr)
- loc {Hist : History} {X : Sequent} {nrep : ¬flprep Hist X} {nbas : ¬X.basic} {lt : LocalTableau X} {next : (Y : Sequent) → Y ∈ endNodesOf lt → Tableau (X :: Hist) Y} {Y : Sequent} (Y_in : Y ∈ endNodesOf lt) (tail : FinePathIn (next Y Y_in)) : FinePathIn (Tableau.loc nrep nbas lt next)
- pdl {Hist : History} {X Y : Sequent} {nrep : ¬flprep Hist X} {bas : X.basic} {r : PdlRule X Y} {next : Tableau (X :: Hist) Y} (tail : FinePathIn next) : FinePathIn (Tableau.pdl nrep bas r next)
Instances For
Equations
- One or more equations did not get rendered due to their size.
- instDecidableEqFinePathIn.decEq (FinePathIn.inLoc lp lp_int) (FinePathIn.loc Y_in tail) = isFalse ⋯
- instDecidableEqFinePathIn.decEq FinePathIn.pdlHere FinePathIn.pdlHere = isTrue ⋯
- instDecidableEqFinePathIn.decEq FinePathIn.pdlHere tail.pdl = isFalse ⋯
- instDecidableEqFinePathIn.decEq FinePathIn.lrepHere FinePathIn.lrepHere = isTrue ⋯
- instDecidableEqFinePathIn.decEq (FinePathIn.loc Y_in tail) (FinePathIn.inLoc lp lp_int) = isFalse ⋯
- instDecidableEqFinePathIn.decEq tail.pdl FinePathIn.pdlHere = isFalse ⋯
- instDecidableEqFinePathIn.decEq a_8.pdl b.pdl = if h : a_8 = b then h ▸ have inst := instDecidableEqFinePathIn.decEq a_8 a_8; isTrue ⋯ else isFalse ⋯
Instances For
The fine path pointing at the root of a tableau.
Equations
- rootFine (Tableau.loc nflprep nbas (LocalTableau.byLocalRule lra X_def next_2) next_3) = FinePathIn.inLoc LocalPathIn.nil True.intro
- rootFine (Tableau.loc nflprep nbas (LocalTableau.sim bas) next_2) = absurd bas nbas
- rootFine (Tableau.pdl nflprep bas r next) = FinePathIn.pdlHere
- rootFine (Tableau.lrep lpr) = FinePathIn.lrepHere
Instances For
The sequent at the node a fine path points at, i.e. Λ(t) for fine nodes t.
Equations
- (FinePathIn.inLoc lp lp_int).label = lp.last
- FinePathIn.pdlHere.label = x✝
- FinePathIn.lrepHere.label = x✝
- (FinePathIn.loc Y_in tail).label = tail.label
- tail.pdl.label = tail.label
Instances For
The PathIn node in whose local tableau the given fine node lies.
Equations
- (FinePathIn.inLoc lp lp_int).base = PathIn.nil
- FinePathIn.pdlHere.base = PathIn.nil
- FinePathIn.lrepHere.base = PathIn.nil
- (FinePathIn.loc Y_in tail).base = PathIn.loc Y_in tail.base
- tail.pdl.base = tail.base.pdl
Instances For
The children of a fine node. Note that a child of an internal node of a local tableau
may be a node of the tableau in the coarse PathIn sense, namely when it is an end node
of that local tableau.
Equations
- One or more equations did not get rendered due to their size.
- FinePathIn.pdlHere.children = {(rootFine next).pdl}
- FinePathIn.lrepHere.children = ∅
- (FinePathIn.loc Y_in tail).children = Finset.image (FinePathIn.loc Y_in) tail.children
- tail.pdl.children = Finset.image FinePathIn.pdl tail.children
Instances For
Any node in the coarse sense is also a node in the fine sense.
Equations
- PathIn.nil.toFine = rootFine x✝
- (PathIn.loc Y_in tail).toFine = FinePathIn.loc Y_in tail.toFine
- tail.pdl.toFine = tail.toFine.pdl
Instances For
All fine nodes of a tableau. Compare allPaths.
Equations
- One or more equations did not get rendered due to their size.
- allFinePaths (Tableau.pdl nflprep bas r next) = FinePathIn.pdlHere :: List.map FinePathIn.pdl (allFinePaths next)
- allFinePaths (Tableau.lrep lpr) = [FinePathIn.lrepHere]
Instances For
Fine children either stay at the same node in the coarse sense, or they are a child
of it. This connects the fine children with the edge relation ⋖_.
The local rule applied at a fine node, if any.
Equations
- (FinePathIn.inLoc lp lp_int).lra? = match lp.ltAt with | LocalTableau.byLocalRule lra X_def next => some lra | LocalTableau.sim a => none
- FinePathIn.pdlHere.lra? = none
- FinePathIn.lrepHere.lra? = none
- (FinePathIn.loc Y_in tail).lra? = tail.lra?
- tail.pdl.lra? = tail.lra?
Instances For
If a local rule is applied at a fine node then that node is labelled with the premise and its children are labelled with the conclusions of that rule.
Local soundness and invertibility at the fine level: whenever a local rule is applied at a fine node, its label is satisfied exactly if the label of one of its children is. This is the property of the fine tableau that makes the quasi-tableau work.
Left and right rules #
At the fine level each rule application is a left rule or a right rule or neither
(the latter for closing rules and loaded-path repeats), but never both.
This is what Lemma 9.7 (a) is about, and it is the reason why we needed the fine nodes:
on the Tableau level a loc step is in general a mix of left and right rules.
Is this a local rule applied to the right component?
Equations
- (LocalRule.oneSidedR orule YS_def).isRightRule = true
- (LocalRule.loadedR χ lrule YS_def).isRightRule = true
- x✝.isRightRule = false
Instances For
Is this a local rule applied to the left component?
Equations
- (LocalRule.oneSidedL orule YS_def).isLeftRule = true
- (LocalRule.loadedL χ lrule YS_def).isLeftRule = true
- x✝.isLeftRule = false
Instances For
Equations
- lra.isRightRule = lra.lr.isRightRule
Instances For
Equations
- lra.isLeftRule = lra.lr.isLeftRule
Instances For
The (M), (L+) and (L-) rules acting on the right component.
Equations
- (PdlRule.loadR a a_1 a_2).isRightRule = true
- (PdlRule.freeR a a_1).isRightRule = true
- (PdlRule.modR a a_1).isRightRule = true
- x✝.isRightRule = false
Instances For
The (M), (L+) and (L-) rules acting on the left component.
Equations
- (PdlRule.loadL a a_1 a_2).isLeftRule = true
- (PdlRule.freeL a a_1).isLeftRule = true
- (PdlRule.modL a a_1).isLeftRule = true
- x✝.isLeftRule = false
Instances For
Is a right rule applied at this fine node?
Equations
- (FinePathIn.inLoc lp lp_int).usesRightRule = match lp.ltAt with | LocalTableau.byLocalRule lra X_def next => lra.isRightRule | LocalTableau.sim a => false
- FinePathIn.pdlHere.usesRightRule = r.isRightRule
- FinePathIn.lrepHere.usesRightRule = false
- (FinePathIn.loc Y_in tail).usesRightRule = tail.usesRightRule
- tail.pdl.usesRightRule = tail.usesRightRule
Instances For
Is a left rule applied at this fine node?
Equations
- (FinePathIn.inLoc lp lp_int).usesLeftRule = match lp.ltAt with | LocalTableau.byLocalRule lra X_def next => lra.isLeftRule | LocalTableau.sim a => false
- FinePathIn.pdlHere.usesLeftRule = r.isLeftRule
- FinePathIn.lrepHere.usesLeftRule = false
- (FinePathIn.loc Y_in tail).usesLeftRule = tail.usesLeftRule
- tail.pdl.usesLeftRule = tail.usesLeftRule
Instances For
No node uses a left and a right rule at the same time.
A node where a right rule is applied is not a loaded-path repeat, and neither is the coarse node it belongs to.
Is this fine node also a node in the coarse sense, i.e. the root of the local tableau at its base?
Equations
- (FinePathIn.inLoc lp lp_int).atBigRoot = lp.isNilB
- FinePathIn.pdlHere.atBigRoot = true
- FinePathIn.lrepHere.atBigRoot = true
- (FinePathIn.loc Y_in tail).atBigRoot = tail.atBigRoot
- tail.pdl.atBigRoot = tail.atBigRoot
Instances For
The labels of those end nodes of the local tableau at f.base that are below f.
These are the labels of the children of f.base that can be reached from f.
Equations
- (FinePathIn.inLoc lp lp_int).endLabelsBelow = endNodesOf lp.ltAt
- FinePathIn.pdlHere.endLabelsBelow = ∅
- FinePathIn.lrepHere.endLabelsBelow = ∅
- (FinePathIn.loc Y_in tail).endLabelsBelow = tail.endLabelsBelow
- tail.pdl.endLabelsBelow = tail.endLabelsBelow
Instances For
The children of f.base in the coarse sense that are below the fine node f.
Note that when f is a coarse node itself, i.e. f.atBigRoot, then these are all
children of f.base, and that they get further restricted the deeper f sits inside the
local tableau at f.base.
Equations
- (FinePathIn.inLoc lp lp_int).coarseChildrenBelow = List.map (fun (x : ↥(endNodesOf lt)) => match x with | ⟨val, Y_in⟩ => PathIn.loc Y_in PathIn.nil) lp.endNodesBelow
- FinePathIn.pdlHere.coarseChildrenBelow = [PathIn.nil.pdl]
- FinePathIn.lrepHere.coarseChildrenBelow = []
- (FinePathIn.loc Y_in tail).coarseChildrenBelow = List.map (PathIn.loc Y_in) tail.coarseChildrenBelow
- tail.pdl.coarseChildrenBelow = List.map PathIn.pdl tail.coarseChildrenBelow
Instances For
If a coarse child q is below the fine node f, then f has a fine child g that
is either still at the same coarse node and has q below it, or g is q.
All children of a coarse node are below it in the fine sense. This is the converse of
FinePathIn.base_of_mem_children for coarse nodes.
Well-founded descent for fine paths #
The children of a fine node (FinePathIn.children) are not structurally smaller than the
node itself: a child of an internal node of a local tableau is again a path in the same
local tableau, and a child of the last internal node is a FinePathIn.loc step, hence even
structurally bigger. So there is no induction principle for FinePathIn that follows the
child relation for free.
Below we provide one, in the same way as PathIn.strong_upwards_inductionOn is obtained
from flipEdge.wellFounded for the coarse PathIn nodes: we equip fine paths with a
FinePathIn.length, bound it by a size measure Tableau.fineSize of the tableau, and
conclude that there is no infinite chain of fine children — the child relation fineEdge
has a well-founded flip. From that we get
FinePathIn.edge_upwards_inductionOn— induction from the leaves to the root, andFinePathIn.strong_upwards_inductionOn— its strong version, where the inductive hypothesis is available at all fine descendants, not only at the children.
Dually, FinePathIn.descent states the descent principle in the contrapositive form in
which it is used: if a property holds somewhere and always propagates to some child,
then it holds at a node without children.
A length for local paths #
The number of steps of a local path.
Equations
- LocalPathIn.nil.length = 0
- (LocalPathIn.cons Y_in tail).length = tail.length + 1
Instances For
The number of nodes of a local tableau.
Equations
- One or more equations did not get rendered due to their size.
- (LocalTableau.sim a).nodeCount = 1
Instances For
Going to a child inside a local tableau increases the length.
A length for fine paths #
A size measure for tableaux that also counts the intermediate nodes of the local
tableaux, i.e. an upper bound for the length of any FinePathIn.
Equations
- One or more equations did not get rendered due to their size.
- (Tableau.pdl nflprep bas r next).fineSize = 1 + next.fineSize
- (Tableau.lrep lpr).fineSize = 1
Instances For
The number of steps of a fine path, where a whole local tableau counts with its
LocalTableau.nodeCount so that leaving it strictly increases the length.
Equations
Instances For
The child relation on fine nodes and its well-founded flip #
The child relation on fine nodes, the fine analogue of edge.
Equations
- «term_⋖f_» = Lean.ParserDescr.trailingNode `«term_⋖f_» 50 50 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ⋖f ") (Lean.ParserDescr.cat `term 51))
Instances For
The flipped child relation on fine nodes is well-founded. Compare flipEdge.wellFounded.
The induction principles #
Induction on fine nodes going from the leaves (= childless fine nodes) to the root.
Compare PathIn.edge_upwards_inductionOn.
Strong induction on fine nodes going from the leaves to the root: the motive may be
assumed at all fine descendants. Compare PathIn.strong_upwards_inductionOn.
The descent principle for fine nodes: if a property holds at some fine node and, at every fine node where it holds and which has a child, it also holds at some child, then it holds at some childless fine node.
This is the form in which the well-foundedness is used when following a path downwards in the fine sense, cf. Lemma 9.7 (d) of the paper.
The descent principle in the strong form: the property is only required to propagate to some fine descendant (not necessarily a child) as long as the node is not childless.