The @[to_additive] attribute. #

The attribute to_additive can be used to automatically transport theorems and definitions (but not inductive types and structures) from a multiplicative theory to an additive theory.

An attr := ... option for to_additive.

Instances For

    Remaining arguments of to_additive.

    Instances For

      The to_additive attribute.

      Instances For

        The to_additive attribute.

        Instances For

          A set of strings of names that end in a capital letter.

          • If the string contains a lowercase letter, the string should be split between the first occurrence of a lower-case letter followed by an upper-case letter.
          • If multiple strings have the same prefix, they should be grouped by prefix
          • In this case, the second list should be prefix-free (no element can be a prefix of a later element)

          Todo: automate the translation from String to an element in this RBMap (but this would require having something similar to the rb_lmap from Lean 3).

          Instances For
            partial def String.splitCase (s : String) (i₀ : optParam String.Pos 0) (r : optParam (List String) []) :

            This function takes a String and splits it into separate parts based on the following (naming conventions)[].

            E.g. #eval "InvHMulLEConjugate₂SMul_ne_top".splitCase yields ["Inv", "HMul", "LE", "Conjugate₂", "SMul", "_", "ne", "_", "top"].

            Linter to check that the reorder attribute is not given manually

            Linter, mostly used by @[to_additive], that checks that the source declaration doesn't have certain attributes

            Linter to check that the to_additive attribute is not given manually

            Linter to check whether the user correctly specified that the additive declaration already exists

            An attribute that tells @[to_additive] that certain arguments of this definition are not involved when using @[to_additive]. This helps the heuristic of @[to_additive] by also transforming definitions if or another fixed type occurs as one of these arguments.

            An attribute that stores all the declarations that needs their arguments reordered when applying @[to_additive]. It is applied automatically by the (reorder := ...) syntax of to_additive, and should not usually be added manually.

            An attribute that is automatically added to declarations tagged with @[to_additive], if needed.

            This attribute tells which argument is the type where this declaration uses the multiplicative structure. If there are multiple argument, we typically tag the first one. If this argument contains a fixed type, this declaration will note be additivized. See the Heuristics section of to_additive.attr for more details.

            If a declaration is not tagged, it is presumed that the first argument is relevant. @[to_additive] uses the function to_additive.first_multiplicative_arg to automatically tag declarations. It is ok to update it manually if the automatic tagging made an error.

            Implementation note: we only allow exactly 1 relevant argument, even though some declarations (like have multiple arguments with a multiplicative structure on it. The reason is that whether we additivize a declaration is an all-or-nothing decision, and if we will not be able to additivize declarations that (e.g.) talk about multiplication on ℕ × α anyway.

            Warning: interactions between this and the (reorder := ...) argument are not well-tested.

            An attribute that stores all the declarations that deal with numeric literals on variable types.

            Numeral literals occur in expressions without type information, so in order to decide whether 1 needs to be changed to 0, the context around the numeral is relevant. Most numerals will be in an OfNat.ofNat application, though tactics can add numeral literals inside arbitrary functions. By default we assume that we do not change numerals, unless it is in a function application with the to_additive_change_numeral attribute.

            @[to_additive_change_numeral n₁ ...] should be added to all functions that take one or more numerals as argument that should be changed if additiveTest succeeds on the first argument, i.e. when the numeral is only translated if the first argument is a variable (or consists of variables). The arguments n₁ ... are the positions of the numeral arguments (starting counting from 1).

            Maps multiplicative names to their additive counterparts.

            Get the multiplicative → additive translation for the given name.

            Instances For

              Add a (multiplicative → additive) name translation to the translations map.

              Instances For
                • trace : Bool

                  View the trace of the to_additive procedure. Equivalent to set_option trace.to_additive true.

                • tgt : Lean.Name

                  The name of the target (the additive declaration).

                • An optional doc string.

                • allowAutoName : Bool

                  If allowAutoName is false (default) then @[to_additive] will check whether the given name can be auto-generated.

                • reorder : List (List )

                  The arguments that should be reordered by to_additive, using cycle notation.

                • The attributes which we want to give to both the multiplicative and additive versions. For certain attributes (such as simp and simps) this will also add generated lemmas to the translation dictionary.

                • The Syntax element corresponding to the original multiplicative declaration (or the to_additive attribute if it is added later), which we need for adding definition ranges.

                • existing : Option Bool

                  An optional flag stating whether the additive declaration already exists. If this flag is set but wrong about whether the additive declaration exists, to_additive will raise a linter error. Note: the linter will never raise an error for inductive types and structures.

                Config is the type of the arguments that can be provided to to_additive.

                Instances For
                  unsafe def ToAdditive.additiveTestUnsafe (findTranslation? : Lean.NameOption Lean.Name) (ignore : Lean.NameOption (List )) (e : Lean.Expr) :

                  Implementation function for additiveTest. We cache previous applications of the function, using the same method that Expr.find? uses, to avoid visiting the same subexpression many times. Note that we only need to cache the expressions without taking the value of inApp into account, since inApp only matters when the expression is a constant. However, for this reason we have to make sure that we never cache constant expressions, so that's why the ifs in the implementation are in this order.

                  Note that this function is still called many times by applyReplacementFun and we're not remembering the cache between these calls.

                  Instances For
                    def ToAdditive.additiveTest (findTranslation? : Lean.NameOption Lean.Name) (ignore : Lean.NameOption (List )) (e : Lean.Expr) :

                    additiveTest e tests whether the expression e contains no constant nm that is not applied to any arguments, and such that translations.find?[nm] = none. This is used in @[to_additive] for deciding which subexpressions to transform: we only transform constants if additiveTest applied to their first argument returns true. This means we will replace expression applied to e.g. α or α × β, but not when applied to e.g. or ℝ × α. We ignore all arguments specified by the ignore NameMap.

                    Instances For
                      def List.swapFirstTwo {α : Type u_1} :
                      List αList α

                      Swap the first two elements of a list

                      Instances For

                        Change the numeral nat_lit 1 to the numeral nat_lit 0. Leave all other expressions unchanged.

                        Instances For

                          applyReplacementFun e replaces the expression e with its additive counterpart. It translates each identifier (inductive type, defined function etc) in an expression, unless

                          • The identifier occurs in an application with first argument arg; and
                          • test arg is false. However, if f is in the dictionary relevant, then the argument relevant.find f is tested, instead of the first argument.

                          It will also reorder arguments of certain functions, using reorderFn: e.g. g x₁ x₂ x₃ ... xₙ becomes g x₂ x₁ x₃ ... xₙ if reorderFn g = some [1].

                          Instances For
                            def ToAdditive.applyReplacementFun.aux (findTranslation? : Lean.NameOption Lean.Name) (reorderFn : Lean.NameList (List )) (ignore : Lean.NameOption (List )) (changeNumeral? : Lean.NameOption (List )) (relevantArg : Lean.Name) (trace : Bool) :

                            Implementation of applyReplacementFun.

                            Instances For

                              Eta expands e at most n times.

                              Instances For

                                e.expand eta-expands all expressions that have as head a constant n in reorder. They are expanded until they are applied to one more argument than the maximum in reorder.find n.

                                Instances For

                                  Reorder pi-binders. See doc of reorderAttr for the interpretation of the argument

                                  Instances For

                                    Reorder lambda-binders. See doc of reorderAttr for the interpretation of the argument

                                    Instances For

                                      Run applyReplacementFun on the given srcDecl to make a new declaration with name tgt

                                      Instances For

                                        Find the target name of pre and all created auxiliary declarations.

                                        Instances For

                                          Returns a NameSet of all auxiliary constants in e that might have been generated when adding pre to the environment. Examples include pre.match_5, Mathlib.MyFile._auxLemma.3 and _private.Mathlib.MyFile.someOtherNamespace.someOtherDeclaration._eq_2. The last two examples may or may not have been generated by this declaration. The last example may or may not be the equation lemma of a declaration with the @[to_additive] attribute. We will only translate it has the @[to_additive] attribute.

                                          Instances For

                                            transform the declaration src and all declarations pre._proof_i occurring in src using the transforms dictionary. replace_all, trace, ignore and reorder are configuration options. pre is the declaration that got the @[to_additive] attribute and tgt_pre is the target of this declaration.

                                            Copy the instance attribute in a to_additive

                                            [todo] it seems not to work when the to_additive is added as an attribute later.

                                            Instances For
                                              def ToAdditive.warnExt {σ : Type} {α : Type} {β : Type} [Inhabited σ] (stx : Lean.Syntax) (ext : Lean.PersistentEnvExtension α β σ) (f : σLean.NameBool) (thisAttr : Lean.Name) (attrName : Lean.Name) (src : Lean.Name) (tgt : Lean.Name) :

                                              Warn the user when the multiplicative declaration has an attribute.

                                              Instances For
                                                def ToAdditive.warnAttr {β : Type} {α : Type} [Inhabited β] (stx : Lean.Syntax) (attr : Lean.SimpleScopedEnvExtension α β) (f : βLean.NameBool) (thisAttr : Lean.Name) (attrName : Lean.Name) (src : Lean.Name) (tgt : Lean.Name) :

                                                Warn the user when the multiplicative declaration has a simple scoped attribute.

                                                Instances For
                                                  def ToAdditive.warnParametricAttr {β : Type} (stx : Lean.Syntax) (attr : Lean.ParametricAttribute β) (thisAttr : Lean.Name) (attrName : Lean.Name) (src : Lean.Name) (tgt : Lean.Name) :

                                                  Warn the user when the multiplicative declaration has a parametric attribute.

                                                  Instances For

                                                    runAndAdditivize names desc t runs t on all elements of names and adds translations between the generated lemmas (the output of t). names must be non-empty.

                                                    Instances For

                                                      Find the first argument of nm that has a multiplicative type-class on it. Returns 1 if there are no types with a multiplicative class as arguments. E.g. Prod.Group returns 1, and Pi.One returns 2. Note: we only consider the first argument of each type-class. E.g. [Pow A N] is a multiplicative type-class on A, not on N.

                                                      Instances For

                                                        Capitalizes s char-by-char like r. If s is longer, it leaves the tail untouched.

                                                        Instances For

                                                          Capitalize First element of a list like s. Note that we need to capitalize multiple characters in some cases, in examples like HMul or hAdd.

                                                          Instances For

                                                            Dictionary used by guessName to autogenerate names.

                                                            Note: guessName capitalizes first element of the output according to capitalization of the input. Input and first element should therefore be lower-case, 2nd element should be capitalized properly.

                                                            Instances For

                                                              Turn each element to lower-case, apply the nameDict and capitalize the output like the input.

                                                              Instances For

                                                                There are a few abbreviations we use. For example "Nonneg" instead of "ZeroLE" or "addComm" instead of "commAdd". Note: The input to this function is case sensitive! Todo: A lot of abbreviations here are manual fixes and there might be room to improve the naming logic to reduce the size of fixAbbreviation.

                                                                Instances For

                                                                  Autogenerate additive name. This runs in several steps:

                                                                  1. Split according to capitalisation rule and at _.
                                                                  2. Apply word-by-word translation rules.
                                                                  3. Fix up abbreviations that are not word-by-word translations, like "addComm" or "Nonneg".
                                                                  Instances For

                                                                    Return the provided target name or autogenerate one if one was not provided.

                                                                    Instances For

                                                                      if f src = #[a_1, ..., a_n] and f tgt = #[b_1, ... b_n] then proceedFieldsAux src tgt f will insert translations from src.a_i to tgt.b_i.

                                                                      Instances For

                                                                        Add the structure fields of src to the translations dictionary so that future uses of to_additive will map them to the corresponding tgt fields.

                                                                        Instances For

                                                                          Elaboration of the configuration options for to_additive.

                                                                          Instances For

                                                                            Apply attributes to the multiplicative and additive declarations.

                                                                            Copies equation lemmas and attributes from src to tgt

                                                                            Make a new copy of a declaration, replacing fragments of the names of identifiers in the type and the body using the translations dictionary. This is used to implement @[to_additive].

                                                                            addToAdditiveAttr src cfg adds a @[to_additive] attribute to src with configuration cfg. See the attribute implementation for more details. It returns an array with names of additive declarations (usually 1, but more if there are nested to_additive calls.