Documentation

ExistentialRules.Terms.Basic

Terms #

In this file, we define various kinds of terms that form some of the most basic building blocks of other structures like atoms and rules.

structure Signature :
Type (max (max (u + 1) (v + 1)) (w + 1))

First of all, almost all of our definitions consider a fixed but arbitrary Signature of predicate symbols P, variables V, and constants C. Also every predicate has a fixed arity. Note that P, V, and C can be arbitrary types so there are no requirements in terms of countability or finiteness. However, intuitively you can consider them to be countably infinite sets. This would allow to pick fresh elements for example. In places where we need this property, we express this through the GetFreshInhabitant type class.

Instances For

    Skolem Terms #

    If you are familiar with existential rules, you may have expected (labelled) nulls to be part of the Signature. These nulls would act as placeholders that are introduced during the chase to find fresh representatives for existentially quantified variables. However, implementing this freshness is not really nice to model since it would require is to keep global state around to know which nulls have already been used. Instead, we act as if the existentially quantified variables where Skolemized. By that, freshly introduced terms simply become Skolem terms and we can show that these are indeed fresh by design. Some works on existential rules take this view, first and foremost of course the ones considering the Skolem chase.

    structure SkolemFS (sig : Signature) [DecidableEq sig.V] :
    Type u_2

    As a building block for Skolem terms, we introduce SkolemFS as a Skolem Function Symbol here. This structure captures the rule, disjunct, and (existential) variable for that the Skolem function was introduced. The arity corresponds to the size of the frontier of the rule, i.e. the universal variables that occur in both body and head.

    • ruleId : Nat
    • disjunctIndex : Nat
    • var : sig.V
    • arity : Nat
    Instances For
      def instDecidableEqSkolemFS.decEq {sig✝ : Signature} {inst✝ : DecidableEq sig✝.V} (x✝ x✝¹ : SkolemFS sig✝) :
      Decidable (x✝ = x✝¹)
      Equations
      • One or more equations did not get rendered due to their size.
      Instances For
        inductive SkolemTerm (sig : Signature) [DecidableEq sig.C] [DecidableEq sig.V] :
        Type (max u_2 u_3)

        With SkolemTerm we mean the Skolemized version of an existential variable. That is, a SkolemTerm only consists of a function symbol (SkolemFS) and a list of universal variables. Beyond that, we allow this inductive structure also to be a plain variable or constant. Thereby, the SkolemTerm can represent any term occurring in a Skolemized rule.

        Instances For
          def instDecidableEqSkolemTerm.decEq {sig✝ : Signature} {inst✝ : DecidableEq sig✝.C} {inst✝¹ : DecidableEq sig✝.V} (x✝ x✝¹ : SkolemTerm sig✝) :
          Decidable (x✝ = x✝¹)
          Equations
          Instances For

            We may obtain all variables from a SkolemTerm term as the list of all variables occurring in the functional term or, if the term is a plain variable, simply as the singleton list with this one variable.

            Equations
            Instances For

              VarOrConst #

              We introduce VarOrConst as yet another inductive type representing a term. This is a function free SkolemTerm, i.e. either a variable or a constant (thus the name). Having this is a separate type is more convenient for us than restricting the SkolemTerm further. VarOrConst is used to define FunctionFreeAtom later and is thus also the basic building block of (non-Skolemized) Rules.

              inductive VarOrConst (sig : Signature) [DecidableEq sig.C] [DecidableEq sig.V] :
              Type (max u_2 u_3)

              As the name suggests, a VarOrConst is either a variable or a constant.

              Instances For

                A VarOrConst is a variable if it was built using the var constructor.

                Equations
                Instances For

                  Given a list of VarOrConst, we can filter out all the variables. Note that we do not use List.filter here since we need to change the list type on the way.

                  Equations
                  Instances For
                    def VarOrConst.skolemize {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (ruleId disjunctIndex : Nat) (frontier : List sig.V) (voc : VarOrConst sig) :

                    In the context of a rule and a disjunct (in that rule), we can turn a VarOrConst into a SkolemTerm using the frontier of the rule. This function is used for skolemizing existential variables in rules.

                    Equations
                    Instances For
                      theorem VarOrConst.filterVars_occur_in_original_list {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (l : List (VarOrConst sig)) (v : sig.V) :
                      v filterVars lvar v l

                      Each member of filterVars is in the original list (when applyign the var constructor again.)

                      theorem VarOrConst.mem_filterVars_of_var {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (l : List (VarOrConst sig)) (v : sig.V) :
                      var v lv filterVars l

                      If a variable is in a list of VarOrConst, then it occurs in filterVars.

                      Each member of filterConsts is in the original list (when applyign the const constructor again.)

                      theorem VarOrConst.mem_filterConsts_of_const {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (l : List (VarOrConst sig)) (c : sig.C) :

                      If a constant is in a list of VarOrConst, then it occurs in filterConsts.

                      theorem VarOrConst.skolemize_injective {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (ruleId i : Nat) (frontier : List sig.V) (s t : VarOrConst sig) :
                      skolemize ruleId i frontier s = skolemize ruleId i frontier ts = t

                      The skolemize function is injective. That is, if the produced SkolemTerms are the same, then bey need to result from the same variable. This is important to ensure that introduced Skolem terms are indeed fresh (and unique) in the chase.

                      Ground Terms #

                      A GroundTerm is a constant or a functional term with arbitrary nesting of function symbols (SkolemFS). Aiming to define GroundTerm, we need to define a more basic structure first, where we do not demand yet that function symbol arities are respected. PreGroundTerms need to be able to model Skolem terms, i.e. function terms. We can represent those conveniently using inductively defined FiniteTrees.

                      With PreGroundTerms in place, we merely define GroundTerms to be the PreGroundTerms where arity_ok holds. We then define appropriate constructors and recursion principles on the GroundTerm to make it behave almost like an inductive type with a const and func constructor.

                      @[reducible, inline]
                      abbrev PreGroundTerm (sig : Signature) [DecidableEq sig.C] [DecidableEq sig.V] :
                      Type (max u_2 u_3)

                      The PreGroundTerm is simply a FiniteTree (SkolemFS sig) sig.C. That is a tree that features Skolem function symbols in its inner nodes and constants in its leaf nodes.

                      Equations
                      Instances For
                        @[irreducible]

                        The arity of a functional term is ok if the defined arity of its function symbol matches its number of children and arity_ok also holds for each child. For constants, i.e. the leaf nodes, the arity is trivially ok.

                        Equations
                        Instances For
                          @[reducible, inline]
                          abbrev GroundTerm (sig : Signature) [DecidableEq sig.C] [DecidableEq sig.V] :
                          Type (max 0 u_3 u_2)

                          As mentioned above, a GroundTerm is simply a PreGroundTerm subtype where arity_ok holds.

                          Equations
                          Instances For
                            def GroundTerm.const {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (c : sig.C) :

                            A GroundTerm can be direclty constructed from a constant.

                            Equations
                            Instances For
                              def GroundTerm.func {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (func : SkolemFS sig) (ts : List (GroundTerm sig)) (arity_ok : ts.length = func.arity) :

                              Also, a GroundTerm can be constructed from a SkolemFS and a list of GroundTerms as long as the length of the list matches the function symbol's arity.

                              Equations
                              Instances For
                                def GroundTerm.cases {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] {motive : GroundTerm sigSort u} (t : GroundTerm sig) (const : (c : sig.C) → motive (const c)) (func : (func : SkolemFS sig) → (ts : List (GroundTerm sig)) → (arity_ok : ts.length = func.arity) → motive (GroundTerm.func func ts arity_ok)) :
                                motive t

                                We define a cases eliminator for the GroundTerm having a case for each constructor. This allows to use the cases tactic direcly on GroundTerms.

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  @[irreducible]
                                  def GroundTerm.rec {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] {motive : GroundTerm sigSort u} (const : (c : sig.C) → motive (const c)) (func : (func : SkolemFS sig) → (ts : List (GroundTerm sig)) → (arity_ok : ts.length = func.arity) → ((t : GroundTerm sig) → t tsmotive t)motive (GroundTerm.func func ts arity_ok)) (t : GroundTerm sig) :
                                  motive t

                                  We define an induction eliminator for the GroundTerm having a case for each constructor. This allows to use the induction tactic direcly on GroundTerms.

                                  Equations
                                  • One or more equations did not get rendered due to their size.
                                  Instances For
                                    def GroundTerm.toConst {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (t : GroundTerm sig) (isConst : (c : sig.C), t = const c) :
                                    sig.C

                                    A GroundTerm that has been constructed from a constants can be converted into this constants again.

                                    Equations
                                    Instances For
                                      def GroundTerm.depth {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (t : GroundTerm sig) :

                                      The depth of a GroundTerm is the depth of the underlying FiniteTree, i.e. the deepest nesting of function symbols (+1).

                                      Equations
                                      Instances For
                                        def GroundTerm.constants {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (t : GroundTerm sig) :
                                        List sig.C

                                        The constants occurring in a GroundTerm are exactly the leaves of the underlying FiniteTree.

                                        Equations
                                        Instances For

                                          The functions (i.e. function symbols SkolemFS) occurring in a GroundTerm are exactly the inner labels of the underlying FiniteTree.

                                          Equations
                                          Instances For
                                            theorem GroundTerm.depth_const {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (c : sig.C) :
                                            (const c).depth = 1

                                            Constants have depth 1.

                                            theorem GroundTerm.depth_func {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (f : SkolemFS sig) (ts : List (GroundTerm sig)) (arity_ok : ts.length = f.arity) :
                                            (func f ts arity_ok).depth = 1 + (List.map depth ts).max?.getD 1

                                            The depth of a function term is the maximum depth of its children + 1.

                                            theorem GroundTerm.constants_const {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (c : sig.C) :

                                            The constants of a constant are the singleton list with the constant itself.

                                            theorem GroundTerm.constants_func {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (f : SkolemFS sig) (ts : List (GroundTerm sig)) (arity_ok : ts.length = f.arity) :

                                            The constants of a function term are the constants of its children.

                                            theorem GroundTerm.functions_const {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (c : sig.C) :

                                            A constant has no functions.

                                            theorem GroundTerm.functions_func {sig : Signature} [DecidableEq sig.C] [DecidableEq sig.V] (f : SkolemFS sig) (ts : List (GroundTerm sig)) (arity_ok : ts.length = f.arity) :
                                            (func f ts arity_ok).functions = f :: List.flatMap functions ts

                                            The functions of a function term consist of the function symbol of the current term and the function symbols of all its children.