Documentation

ExistentialRules.ChaseSequence.TreeDerivation

Tree Derivation #

The TreeDerivation is the tree version of the ChaseDerivation. Since we allow rules to feature disjunctions, there are multiple possible results for a given trigger. The ChaseDerivation picks one possible choice. For the TreeDerivation, we consider all possiblities at once. That is, the tree branches out for the disjunctions.

We try to mimic much of the machinery introduced for ChaseDerivation but we will see that some of this requires a different approach. Most prominently, we now need to consider addresses of nodes in the tree to be able to define a proper predecessor relation.

Chase Step #

To define how one chase step follows from the previous, we introduce two auxiliary definitions that capture two cases that can occur for a given ChaseNode in a TreeDerivation. This is similar to the definitions for ChaseDerivation only that now the result is a list of ChaseNodes.

  1. Case (exists_trigger_list): There still exists an active trigger, in which case one chase node for each disjunct of the trigger is introduced and contains the facts from the previous step together with the respective head result of the trigger.

  2. Case (not_exists_trigger_list): There is no active trigger. Then the successor list must be empty, i.e. the respective tree node does not have any children.

def exists_trigger_list_condition {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] (obs : ObsoletenessCondition sig) (rules : RuleSet sig) (before : ChaseNode obs rules) (after : List (ChaseNode obs rules)) (trg : RTrigger { cond := obs.cond, monotone := } rules) :
Equations
  • One or more equations did not get rendered due to their size.
Instances For
    def exists_trigger_list {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] (obs : ObsoletenessCondition sig) (rules : RuleSet sig) (before : ChaseNode obs rules) (after : List (ChaseNode obs rules)) :
    Equations
    Instances For
      def not_exists_trigger_list {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] (obs : ObsoletenessCondition sig) (rules : RuleSet sig) (before : ChaseNode obs rules) (after : List (ChaseNode obs rules)) :
      Equations
      Instances For

        The TreeDerivation Structure #

        The backbone of the TreeDerivation is a FiniteDegreeTree of ChaseNodes with a couple of conditions.

        1. We enforce that there is at least an initial ChaseNode.
        2. At each step in the derivation, either there exists a trigger that yields the child nodes or there is no trigger and consequently the derivation stops at this point. This is expressed by the two auxiliary definitions above.
        3. No triggers are active on leaf nodes.
        4. For each trigger, there exists a depth in the tree from which on the trigger is never active anymore.

        Conditions 3 and 4 together are "fairness", i.e. each trigger must eventually be non-active. Fairness ensures that the chase result (or in this case each fact set in the chase result) is indeed a model.

        structure TreeDerivation {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] (obs : ObsoletenessCondition sig) (rules : RuleSet sig) :
        Type (max (max u_1 u_2) u_3)
        Instances For

          Basic Definitions #

          Here we introduce some auxiliary definitions and theorems and we lift some of the machinery of the underlying FiniteDegreeTree to TreeDerivation.

          We can convert a TreeDerivation directly to a FiniteDegreeTreeWithRoot.

          Equations
          Instances For
            instance TreeDerivation.instMembershipChaseNode {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} :
            Membership (ChaseNode obs rules) (TreeDerivation obs rules)

            Membership of ChaseNodes in the TreeDerivation directly corresponds to membership in the FiniteDegreeTree.

            Equations
            def TreeDerivation.derivation_for_suffix {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} (td : TreeDerivation obs rules) (t2 : FiniteDegreeTree (ChaseNode obs rules)) (suffix : t2 <:+ td.tree) (t2_root_some : t2.root.isSome = true) :
            TreeDerivation obs rules

            Each subtree of the underlying FiniteDegreeTree is itself a TreeDerivation as long as its root is not none.

            Equations
            • td.derivation_for_suffix t2 suffix t2_root_some = { tree := t2, isSome_root := t2_root_some, triggers_exist := , fairness_leaves := , fairness_infinite_branches := }
            Instances For
              def TreeDerivation.root {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} (td : TreeDerivation obs rules) :
              ChaseNode obs rules

              The root of the TreeDerivation is the initial ChaseNode. We know that this is never none.

              Equations
              Instances For
                theorem TreeDerivation.root_mem {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} :
                td.root td

                The root is a member.

                The (immediate) ChildNodes #

                For a TreeDerivation derivation, its childNodes are the ChaseNodes immediately following the root. We mainly introduce a couple of theorems here that abstract away the triggers_exist condition from the TreeDerivation definition.

                def TreeDerivation.childNodes {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} (td : TreeDerivation obs rules) :
                List (ChaseNode obs rules)
                Equations
                Instances For
                  theorem TreeDerivation.mem_of_mem_childNodes {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (n : ChaseNode obs rules) :
                  n td.childNodesn td

                  Each child node is a member.

                  theorem TreeDerivation.isSome_origin_of_mem_childNodes {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (n : ChaseNode obs rules) :

                  The origin of the childNodes needs to be set.

                  theorem TreeDerivation.active_trigger_origin_of_mem_childNodes {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {n : ChaseNode obs rules} (mem : n td.childNodes) :

                  The trigger used to derive the childNodes is active for head.

                  theorem TreeDerivation.childNodes_ne_nil_iff_trg_ex {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} :
                  td.childNodes [] (trg : RTrigger { cond := obs.cond, monotone := } rules), trg.val.active td.root.facts

                  The childNodes are not nil if and only if some trigger is active on root.

                  theorem TreeDerivation.facts_childNodes {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {n : ChaseNode obs rules} (mem : n td.childNodes) :

                  The fact set of each of the childNodes consists exactly of the facts from root and the result of the trigger that introduces the child node.

                  TreeDerivation Subtrees #

                  We define a suffix/subtree relation on TreeDerivation simply as the subtree relation of the underlying FiniteDegreeTree.

                  def TreeDerivation.IsSuffix {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} (td1 td2 : TreeDerivation obs rules) :
                  Equations
                  Instances For
                    theorem TreeDerivation.IsSuffix_iff {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td1 td2 : TreeDerivation obs rules} :
                    td1 <:+ td2 td1.tree <:+ td2.tree
                    theorem TreeDerivation.mem_of_mem_suffix {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {cd1 cd2 : TreeDerivation obs rules} (suffix : cd1 <:+ cd2) (node : ChaseNode obs rules) :
                    node cd1node cd2

                    Members of our subtrees are also our members.

                    Child Trees #

                    We can drop the root of a TreeDerivation and obtain a (possibly empty) list of childTrees, which are again TreeDerivations.

                    def TreeDerivation.childTrees {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} (td : TreeDerivation obs rules) :
                    List (TreeDerivation obs rules)

                    We obtain the child trees of the FiniteDegreeTree and convert each of them into a TreeDerivation using derivation_for_suffix. We know that all of those trees have non-none roots.

                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For

                      Membership in childTrees can be boiled down to membership in FiniteDegreeTree.childTrees.

                      theorem TreeDerivation.childNodes_eq {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} :

                      childNodes can be expressed by mapping each childTrees to its root.

                      theorem TreeDerivation.IsSuffix_of_mem_childTrees {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (td2 : TreeDerivation obs rules) :
                      td2 td.childTreestd2 <:+ td

                      Each childTrees is a suffix.

                      theorem TreeDerivation.suffix_iff_eq_or_suffix_childTree {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td1 td2 : TreeDerivation obs rules} :
                      td1 <:+ td2 td1 = td2 (td3 : TreeDerivation obs rules), td3 td2.childTrees td1 <:+ td3

                      A derivation is a subtree of another if and only if both are the same or the first is a suffix of one of the second's child trees.

                      Induction Principle for Members #

                      Similar to FiniteDegreeTree.mem_rec, we define an induction principle to show properties of ChaseNodes in a TreeDerivation.

                      Looking ahead a bit, we will also want to define a predecessor relation on nodes in the tree as we did for nodes in a ChaseDerivation. This is not so elegant here though as the same node might indeed occur multiple times in the tree. Therefore, we are going to associate each node with its address in the tree to tell them apart. Since we are doing this anyway, it makes sense to define the induction principle already with respect to this kind of node.

                      NodeWithAddress #

                      The NodeWithAddress is a structure of a ChaseNode, an address (i.e. a List Nat), and a proof that the chase node is indeed at the given address. We also introduce a couple of covenience functions and theorems for the NodeWithAddress.

                      structure TreeDerivation.NodeWithAddress {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} (td : TreeDerivation obs rules) :
                      Type (max (max u_1 u_2) u_3)
                      Instances For
                        def TreeDerivation.NodeWithAddress.subderivation {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (node : td.NodeWithAddress) :
                        TreeDerivation obs rules

                        Each NodeWithAddress induces a subderivation in the TreeDerivation.

                        Equations
                        Instances For

                          We can cast a node for one of our subderivations into our own node.

                          Equations
                          Instances For

                            The NodeWithAddress version of TreeDerivation.root.

                            Equations
                            Instances For

                              The NodeWithAddress version of TreeDerivation.childNodes.

                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                theorem TreeDerivation.NodeWithAddress.mem {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (node : td.NodeWithAddress) :
                                node.node td

                                The NodeWithAddress is a member.

                                theorem TreeDerivation.NodeWithAddress.eq_of_address_eq {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {n1 n2 : td.NodeWithAddress} :
                                n1.address = n2.addressn1 = n2

                                Two NodeWithAddress are equal if their addresses are.

                                subderivation is indeed a subtree.

                                theorem TreeDerivation.NodeWithAddress.root_subderivation {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {node : td.NodeWithAddress} :
                                root node.subderivation = { node := node.node, address := [], eq := }

                                The root of the subderivation is the node itself with empty address.

                                The root of the subderivation is the node itself.

                                Getting specific elements from child nodes can be translated between NodeWithAddress.childNodes and TreeDerivation.childNodes.

                                The subderivation for a child node is a child tree.

                                Now we are ready for the actual induction principle on NodeWithAddresss in a TreeDerivation.

                                theorem TreeDerivation.mem_rec_address {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {motive : td.NodeWithAddressProp} (root : motive (NodeWithAddress.root td)) (step : ∀ (new_root : td.NodeWithAddress), motive new_root∀ (c : new_root.subderivation.NodeWithAddress), c NodeWithAddress.childNodes new_root.subderivationmotive (new_root.cast_for_new_root_node c)) (node : td.NodeWithAddress) :
                                motive node

                                If we want to show a motive for all nodes in a derivation, it is enough to show the motive for the root and for each arbitrary child node in each abitrary subderivation where the motive in turn already holds for the root. This can be used with the induction tactic.

                                theorem TreeDerivation.mem_some_childTree_iff {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {node : ChaseNode obs rules} :
                                ( (t : TreeDerivation obs rules), t td.childTrees node t) (td2 : TreeDerivation obs rules), td2 <:+ td node td2.childNodes

                                A node is a member of some element of childTrees if and only if there is a subderivation where the node occurs in the childNodes. Part of this proof uses the induction principle defined above.

                                Subset Monotonicity of Facts in ChaseNodes #

                                Since ChaseNodes always extend the previous facts, the fact sets can only be growing along the branches of the TreeDerivation. This has a couple of convenient implications. For example, the root of a TreeDerivation can never occur in its childTrees.

                                theorem TreeDerivation.facts_node_subset_every_mem {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (node : ChaseNode obs rules) :
                                node tdtd.root.facts node.facts

                                Each member's facts contain the root facts.

                                theorem TreeDerivation.root_not_mem_childTrees {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} :

                                The root cannot occur in the childTrees. Otherwise, it would be introduced using a trigger but then this trigger is already obsolete since all the facts from root already occur in the very beginning. We use ObsoletenessCondition.contains_trg_result_implies_cond here.

                                theorem TreeDerivation.eq_of_suffix_of_root_mem {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td1 td2 : TreeDerivation obs rules} (suffix : td1 <:+ td2) (root_mem : td2.root td1) :
                                td1 = td2

                                By root_not_mem_childTrees, if we have a subtree but our root occurs in the subtree, then our subtree is equal to us.

                                Predecessor Relation #

                                Opposed to the ChaseDerivation, we define the predecessor relation direclty using addresses here. This is because ChaseNodes may indeed occur multiple times in a TreeDerivation (just not in the same branch) and therefore the approach used in ChaseDerivation would not quite work. In particular, note that the TreeDerivation has no equivalent for ChaseDerivation.suffix_of_suffix_of_suffix_of_head_mem.

                                Also, even with the address approach, the relation is not total here (which is expected for a tree).

                                def TreeDerivation.predecessor {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (n1 n2 : td.NodeWithAddress) :

                                Node $n$ is a predecessor of node $m$ if the address of $n$ is a prefix of the address of $m$. Predecessor can therefore also be understood as ancestor in the tree.

                                Equations
                                Instances For
                                  theorem TreeDerivation.predecessor_of_suffix {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {new_root : td.NodeWithAddress} {n1 n2 : new_root.subderivation.NodeWithAddress} :
                                  n1 n2new_root.cast_for_new_root_node n1 new_root.cast_for_new_root_node n2

                                  The predecessor relation is stable across suffixes. That is, predecessor in our suffix are also predecessor for us. We only need to cast the nodes.

                                  theorem TreeDerivation.predecessor_refl {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {node : td.NodeWithAddress} :
                                  node node

                                  The predecessor relation is reflexive.

                                  theorem TreeDerivation.predecessor_antisymm {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {n1 n2 : td.NodeWithAddress} :
                                  n1 n2n2 n1n1 = n2

                                  The predecessor relation is antisymmetric.

                                  theorem TreeDerivation.predecessor_trans {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {n1 n2 n3 : td.NodeWithAddress} :
                                  n1 n2n2 n3n1 n3

                                  The predecessor relation is transitive.

                                  The root is a predecessor of each childNodes.

                                  theorem TreeDerivation.facts_node_subset_of_prec {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {node1 node2 : td.NodeWithAddress} :
                                  node1 node2node1.node.facts node2.node.facts

                                  The facts of our predecessor are a subset of our facts.

                                  Branches and Chase Result #

                                  Here, we define the result of a TreeDerivation, which requires us to also define the branches of the TreeDerivation. It should be no surprise that these are ChaseDerivations. The result is then just the set of the results of all the ChaseDerivations in the tree. We already know from the ChaseDerivation that each element of TreeDerivation.result is therefore a model of the rules.

                                  def TreeDerivation.derivation_for_branch {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} (td : TreeDerivation obs rules) (branch : PossiblyInfiniteList (ChaseNode obs rules)) (branch_mem : branch td.tree.branches) :
                                  ChaseDerivation obs rules

                                  Each branch of the underlying tree can be transformed into a proper ChaseDerivation.

                                  Equations
                                  • td.derivation_for_branch branch branch_mem = { branch := branch, isSome_head := , triggers_exist := , fairness := }
                                  Instances For
                                    def TreeDerivation.branches {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} (td : TreeDerivation obs rules) :
                                    Set (ChaseDerivation obs rules)

                                    The branches of the TreeDerivation are defined as all the ChaseDerivation that occur as branches in the tree.

                                    Equations
                                    Instances For
                                      theorem TreeDerivation.derivation_for_branch_mem_branches {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {branch : PossiblyInfiniteList (ChaseNode obs rules)} {branch_mem : branch td.tree.branches} :
                                      td.derivation_for_branch branch branch_mem td.branches

                                      Each ChaseDerivation constructed using derivation_for_branch occurs in branches.

                                      def TreeDerivation.result {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} (td : TreeDerivation obs rules) :
                                      Set (FactSet sig)

                                      The result is the set of FactSets that correspond to the results of the branches.

                                      Equations
                                      Instances For
                                        theorem TreeDerivation.result_models_rules {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (fs : FactSet sig) :
                                        fs td.resultfs.modelsRules rules

                                        Each element of the result models the rules.

                                        Terms in the Chase #

                                        We make some general observations about certain terms that might occur in the chase.

                                        1. Constants can only originate directly from rules or from the initial fact set. No other constants can be introduced.
                                        2. Functional terms can either also originate from the initial fact set or they are introduced as fresh terms by a trigger.

                                        The second observation entails that the precense of a functional term that does not occur in the initial fact set implies that the trigger that introduces this term must have been applied in some node.

                                        theorem TreeDerivation.constants_node_subset_constants_fs_union_constants_rules {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} {node : ChaseNode obs rules} (node_mem : node td) :

                                        Constants in the chase can only come from the initial fact set or from a constant in a rule.

                                        theorem TreeDerivation.functional_term_originates_from_some_trigger {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (node : td.NodeWithAddress) {t : GroundTerm sig} (t_is_func : (func : SkolemFS sig), (ts : List (GroundTerm sig)), (arity_ok : ts.length = func.arity), t = GroundTerm.func func ts arity_ok) (t_mem : t node.node.facts.terms) :
                                        t td.root.facts.terms (node2 : td.NodeWithAddress), node2 node (orig : (trg : RTrigger { cond := obs.cond, monotone := } rules) × Fin trg.val.mapped_head.length), orig node2.node.origin t orig.fst.val.fresh_terms_for_head_disjunct orig.snd

                                        Each functional term in the chase originates as a fresh term from a trigger if it was not already part of the initial fact set.

                                        theorem TreeDerivation.trigger_introducing_functional_term_occurs_in_chase {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (node : td.NodeWithAddress) {t : GroundTerm sig} (t_mem_node : t node.node.facts.terms) {trg : RTrigger { cond := obs.cond, monotone := } rules} {disj_idx : Nat} {lt : disj_idx < trg.val.rule.head.length} (t_mem_trg : t trg.val.fresh_terms_for_head_disjunct disj_idx lt) :
                                        t td.root.facts.terms (node2 : td.NodeWithAddress), node2 node (orig : (trg : RTrigger { cond := obs.cond, monotone := } rules) × Fin trg.val.mapped_head.length), orig node2.node.origin orig.fst.equiv trg orig.snd = disj_idx

                                        If a functional term occurs in the chase, then the trigger that introduces this term must have been used in the chase, unless the term already occurs in the initial fact set.

                                        theorem TreeDerivation.result_of_trigger_introducing_functional_term_occurs_in_chase {sig : Signature} [DecidableEq sig.P] [DecidableEq sig.C] [DecidableEq sig.V] {obs : ObsoletenessCondition sig} {rules : RuleSet sig} {td : TreeDerivation obs rules} (node : td.NodeWithAddress) {t : GroundTerm sig} (t_mem_node : t node.node.facts.terms) {trg : RTrigger { cond := obs.cond, monotone := } rules} {disj_idx : Nat} {lt : disj_idx < trg.val.rule.head.length} (t_mem_trg : t trg.val.fresh_terms_for_head_disjunct disj_idx lt) :

                                        If a functional term occurs in the chase, then the result of the trigger that introduces this term is contained in the current node, unless the functional term already occurs in the initial fact set.