User:CarlWitty/Definitions proposal

Goals of a definition mechanism
There are two essential goals for a definition mechanism:
 * 1) Be conservative.  Any theorem that is provable with a definition, but that does not actually use the definition, must be provable without the definition.
 * 2) Allow arbitrary "sensible" definitions.

Also, User:GrafZahl wants a definition mechanism where definitions can be automatically folded and unfolded during a proof.

I (and perhaps Raph Levien) would like it to be possible to automatically translate proofs to and from equivalent metamath theories; this argues against automatic definition unfolding, and in favor of a system that looks a lot like metamath, where there is a single statement df-FOO and all folding and unfolding is done (directly or indirectly) by applying this statement. (The essential difference is that with a conservative definition mechanism, df-FOO would be a theorem rather than an axiom.)

Proposed specification of a definition mechanism
Here I will give a specification of definitions from the user's and implementor's point of view, as an amendment to Help:JHilbert.

There are two new statements,  and. Also, the spec for the  statement has changed to require that variables appearing on the left also appear on the right.

The  statement declares a "variable kind". vkind (new-kind) There are two differences between a variable kind and a normal kind. First, in every pair of disjoint variables in a disjoint variable declaration, at least one of the variables must be in a variable kind. Second, no term constructor or definition can have a variable kind as a result. (So the only terms whose kind is a variable kind are variables.)

(In a translation of set.mm, set would be a variable kind, class and wff would be normal kinds. Note that the concept of a variable kind is essentially the same as an atom-sort in formalizations of nominal logic.)

The  statement creates a new definition. def (new-defined definition) For example, def ((¬ p) (p | p)) defines ¬ in terms of |. A variable which appears on the right hand side but not the left hand side is called a dummy. Every variable that appears on the left hand side must also appear on the right.

The  statement is the only way to actually use a definition. def-thm (label (distinct-variables) (hypothesis) (consequent) defn-name orig-label) This creates a new theorem (with label, distinct-variables, hypothesis, and consequent as in ). This new theorem is the same as orig-label, except for possible foldings and unfoldings of the definition defn-name.

The process of checking a  statement is slightly involved. First we define the level of a use of a definition. For a definition, the  -level of any term that does not mention   is 0. The -level of   (where   is any term constructor other than  ) is the maximum of the levels of A, B, C... .  The  -level of   is one more than the maximum of the levels of A, B, C... .

Next we define the -unfolding of a statement. Let N be the maximal level at which  appears within the statement. Let M be the number of dummy variables in 's definition. Create N*M new variables. Add all possible disjoint variable conditions involving the new variables. (If the new variable is of variable kind, then it is disjoint from all other variables in the statement (new or old); if the new variable is not of variable kind, then it is disjoint from all variable-kind variables in the statement (new or old).) Unfold each instance of   in the statement; for an instance at level K, use the corresponding set of M dummy variables you just created. If a statement uses a definition  that directly or indirectly refers to , then it has no  -unfolding.

To check a  statement over the definition , compute the  -unfolding of the original and new statements. Verify that there is a variable substitution that takes the original statement to the new statement, while respecting disjoint variable constraints.

Examples
I will use set.mm syntax here.

First, consider a sensible definition. set.mm has an axiom,. Our goal is to prove this as a theorem instead of an axiom. To do so, we define  to be. We then prove ; from this theorem, we can use   over   to deduce that. Note that we could not start from  and use   to deduce  ; the unfolding of the latter is something like , which is not a substitution instance of. (From  it would be possible to deduce  .)

Next, consider a non-sensible definition. Suppose you define  to be   (a dummy class metavariable), with the goal of proving   and deriving an inconsistency. But to use  to derive , you would have to start from a theorem.

Sketch of the ideas behind a proof of conservativity
The basic idea of a proof of conservativity is to show that any proof is still valid if you replace every statement in the proof by its complete unfolding with respect to all definitions. The tricky case is to verify that if statement2 is a substitution instance of statement1 (respecting disjoint variable conditions), then complete_unfolding(statement2) is a substitution instance of complete_unfolding(statement1) (respecting disjoint variable conditions).

(To compute the complete unfolding of a statement, compute its unfolding with respect to every definition in turn, most recent definition first.)

I'll just mention a few details in such a proof, explaining some of the restrictions I gave above.

If definitions are just abbreviations, then there are extra variables running around that are not tracked by the disjoint variables mechanism. For instance, if you had a disjoint variable pair A,B, then you should not be allowed to substitute  (which is an abbreviation for  ) for both A and B, since then A and B would share the variable. However, A and B are not of variable kind, so no disjoint variable pair A,B can exist. (If you tried to declare A,B of variable kind, by translating set.mm with class as a vkind, then you could not define V or class comprehension at all, since no definition or term constructor can have a vkind result.)

It is probably necessary that folding or unfolding one definition does not change the level of another definition. This is the reason for the restriction that every variable on the left-hand side of a definition must also appear on the right; otherwise, you could define  to be , and then unfolding   in   would change the outer   from level 2 to level 1.

Consider a definition  to. Then  is an abbreviation for  ; if this appears in some statement, and you substitute   for , then you need to get. That is, when you substitute  for , you need to simultaneously substitute   for. This is always possible.

Discussion
This is a variant of GHilbert's definition mechanism, as described at the bottom of http://wiki.planetmath.org/AsteroidMeta/Ghilbert_specification. Unfortunately, if I'm understanding it correctly, the proposed GHilbert mechanism is unsound. (It needs to have the concept of levels, and it doesn't.) Here's an example.

Define  to be. You can prove that  is equivalent to , so you can prove that   (there are at least two elements in the universe). Unfortunately, you can also prove, because that's the GHilbert-folding of  , which is equivalent to  , which is equivalent to  , which is certainly true.


 * I'm retracting the above; it's incorrect. (I forgot that the   is proper substitution, not textual substitution.)


 * Instead, I'm making the much weaker claim that I don't see how to prove that the GHilbert mechanism is conservative (and I'm not totally convinced that it is, although I haven't been able to think of any counterexamples). A proof along the lines of the above, via a simple induction over proofs, doesn't work; the problem is that the crucial lemma, that if st2 is a substitution instance of st1 then complete_unfolding(st2) is a substitution instance of complete_unfolding(st1), does not hold.  (For instance, in set.mm, the definition of   uses a dummy variable y, which must be disjoint from ph.  If you have a generic theorem about , and then you substitute   for ph, then in unfolded terms, you are substituting a wff containing y for ph, when y is disjoint from ph.) CarlWitty

Here are some variants on my proposal.

Variant 1: You could make the definition of  much simpler by requiring, for instance, that the definition appears only once, and only in the new theorem. (This would let you get rid of the whole concept of levels.) I believe this would suffice for providing conservative versions of all of set.mm's definitions (except possibly for biimplication). I prefer the powerful version of, for two reasons. First, you would still need levels in the proof of conservativity, so the simpler version wouldn't actually simplify the spec much if you consider the proof to be part of the spec. Second, with the powerful version of, it is easy to see that the metalogic is complete with respect to the intended semantics of definitions; with a weaker  , it might be that the definition metalogic is only complete for sufficiently powerful object logics. (For instance, some object logics might not have a notion of equality or biimplication, and I can't convince myself that a weak  would be complete for such a logic.)

Variant 2: The  statement and the concept of variable kinds could be eliminated if the normal proof machinery were changed to consider dummy variables in definitions. That makes the proof checker much more complicated to describe; I think that the spec is overall simpler by adding  instead.

Variant 3: The restriction that variables on the left of a definition must also appear on the right could be removed if each definition tracked which arguments actually appeared in the complete unfolding of the definition, and this information was used in a revised definition of level.

Variant 4: Definitions without dummy variables are much simpler. There could be essentially two different definition mechanisms, with more flexibility when there are no dummy variables. For example, such definitions could be folded and unfolded automatically during proof. Or (a much smaller change from my proposal) the restriction that if a statement mentions, and the definition of   mentions  , then the statement has no  -unfolding could be removed in the case where   has no dummy variables.

Any comments on this proposal would be greatly appreciated! CarlWitty 19:37, 12 February 2010 (UTC)


 * I think this is a fine proposal, which could be implemented alongside my own (your variant 4), eliminating my  proposal in favour of   (you would still have a companion keyword   or something, so that you can have definitions in interfaces to import them elsewhere). This would also be an actual improvement over the way   handles definitions.


 * I'm curious what you think about the "interoperability with metamath" reason to avoid automatic definition folding/unfolding. Are you interested in being able to automatically translate JHilbert theories into metamath theories?


 * Yes, inasmuch as it facilitates a soundness proof for JHilbert (if metamath is sound, and JHilbert code can always be translated to working metamath code, then JHilbert is sound, too).


 * The  mechanism is quite clever and your weakened dv capabilities are still sufficient to implement something like  . Actually, it makes me wonder whether   has definitions with a dummy that is not a   variable. The question remains whether the weakened dv mechanism would already make JHilbert weaker than metamath in general. Would it be sufficient to enact this restriction on dv constraints only for  s and the   they reference?


 * I don't recall any such definitions in set.mm, but if you wanted to define ⊤ or ⊥ in the propositional part of set.mm you would need to use a dummy wff variable (since the propositional part has no atomic formulas).


 * If I were doing that in metamath, I'd just go  and   (pseudocode as metamath does not know Unicode) because there definitions are just axioms anyway. But then, I see no reason why your way shouldn't work.


 * Limiting the restriction to  and orig-label is insufficient, at least with a semantics anything like I suggest.  The important lemma is that each folded substitution instance corresponds to an unfolded substitution instance, and that has to be true at every step in every proof. And that lemma would be false if you were ever allowed to substitute V for both A and B, when A and B were disjoint.


 * But V is really constant, so it should be allowed to replace both A and B with V. Even for nonconstant V (say, ) you should be allowed to substitute   and   for A and B, respectively, if X and Y are disjoint, as the definition should remain immutable under any legal substitution of dummy variables. I see your point now of course. If you have   and make   and then , then you've violated the constraint. I have no qualms about the global restriction as long as it causes us no problems. It just seems weird from a philosophical standpoint. This has something to do with the fact that   is really the same as   where x and y have been declared to be disjoint. Optimistically, the answer may turn out to be that limiting the restriction creates an onus on the user to declare extra disjoint variable constraints (which require a limited restriction in turn) which would not have been needed ever with the global restriction. In other words: the global restriction may remove user inconvenience without really reducing strength. Which would be great, of course.


 * The restriction certainly does not reduce strength in a "normal" axiomatization of first-order or higher-order logic; there would be no reason to have a term constructor with vkind result, or to have a disjoint variable restriction between variables of non-vkind kinds, in such a system. The only question is whether there might be exotic uses of disjoint variables, like formalizing more complicated binding structures (like the case of Common Lisp let described below), or using disjoint variables as a trick to formalize some other construct that really isn't a binding construct at all.


 * Well, there are some axiomatisations metamath (and hence JHilbert) is not capable of formalising without packing quite a lot of metalogic into the expressions. Multi-stacked calculi are an example. For those, we'd need an extension or an additional layer which hides the metalogic anyway. We can do the same in cases of "misuse" of the DV constraints. So I'd say we go with the restriction for now and cross any other bridges when we come to them.


 * Also: you definitely need something like the vkind restriction to keep you from defining  to be  .  If this definition is allowed, then you can treat   as a spare variable that's not subject to disjoint variable constraints.  (Or, I guess, you could allow the definition and then track   as if it were a variable when looking at disjoint variables.  But that's pretty annoying.)


 * Yes, that's a particularly annoying instance of the Ghilbert-type definition weirdness. Technically,  is not a variable. But to the user it looks as one, which can be just as bad.


 * It's a bit tricky to talk about one metamath variant being weaker than another, since in any reasonable variant, you can construct a theory that will recognize any recursively enumerable language. But I do know of one somewhat plausible kind of formalization where some one-step proofs in metamath would require multi-step proofs with the vkind restriction: abstraction over binding contexts.


 * Consider the Common Lisp  construct.  In , both v1 and v2 are bound in body, but neither is bound in T1 or T2.  In JHilbert, you could formalize this with something like   (note that this swaps the structure of the binding list, to be a pair of lists instead of a list of pairs).  Then you could have an axiom something like  , if B is disjoint from T*.  In other words, you are packaging up an arbitrary number of disjoint variable constraints into a single disjoint variable constraint.


 * To regain this power, it suffices to allow term constructors (but still not definitions) with vkind results, as long as the arguments are also vkind. Then in the above formalization, you would have one vkind var, and another vkind var-list, where var-list has vcons and vnil term constructors.  (The important thing is that the complete unfolding of any vkind term must not have any dummy variables; you could also allow a restricted class of vkind definitions and still keep this property, but it makes the spec more complicated for a fairly limited benefit.)


 * For sake of simplicity, I think we should keep the spec as simple as possible. Of course, we'll need to see how this affects the soundness proof.


 * The creation of $$N\cdot M$$ extra variables together with enough dv constraints looks a bit daunting efficiency-wise, but in most cases the level would be 1, I guess, and the number of dummy variables should not be too high as well.


 * In a set.mm-style theory, where there is one  per definition which is used only to create a df- theorem, then N is always 1 and M will usually be 0 or 1.


 * I don't like your variant 3 too much as it creates bureaucracy that is rarely needed. Are there actual cases where extra variables in the definiendum make sense?


 * Well, there can't be a technical reason for extra variables in the definiendum, because it would be straightforward to automatically remove any such variables. I suppose there could be an aesthetic reason.  For instance, you could have a generic development of fields, where a field is represented as an addition function and a multiplication function.  And you could say that every operation on field values should be defined using the definition mechanism, and should take the field addition and field multiplication as its first two arguments.  Then you could run into trouble with operations that only used the addition function but not the multiplication function.  But this is a very contrived case.


 * (I don't like variant 3 either, which is why it's relegated to variant status instead of being in the main proposal.)


 * One note about the original Ghilbert. Ghilbert used definitions in only a very restrictive way. Definitions were only ever applied to the final result on the proof stack, and even then, only folding, not unfolding, would occur. So, yes, you could prove wrong statements, but the wrongness would always be buried in ununfoldable definitions, causing weirdness and confusion, but no actual harm (I think). For example, you could do stuff like

import (PROP pax/prop "") import (ZFC zfc/set_mm_ax (PROP) "")

var (wff ph) var (set x)

def ((foo) (-> ph (A. x ph)))

thm (bar ((ph x)) (foo) ( ph x ax-17 ))

thm (baz  (foo) ( bar ))
 * This proves a theorem  without dv constraints whose consequent is , which is defined to be  , seemingly proving a wrong theorem with the consequent of   without the necessary constraints. But since   never gets unfolded, nothing actually bad has happened.
 * --GrafZahl (talk) 13:29, 13 February 2010 (UTC)


 * Well, if I'm right, I gave a way to prove both a formula and its negation, which means the theory is inconsistent and can prove anything


 * Note that my proposal would also let you prove  (with no explicit disjoint variable constraints).  This is safe because all dummy variables are disjoint from all other variables, so the required disjoint-variable constraints would appear again if you ever unfolded  . CarlWitty 18:09, 13 February 2010 (UTC)


 * I haven't had the time to check this yet. Is there a metamath proof for the lemmas anywhere?--GrafZahl (talk) 19:00, 16 February 2010 (UTC)


 * Thanks for prodding me to take another look at this. As I described above, my counterexample is wrong, and I haven't been able to find an actual counterexample for the GHilbert definition mechanism (augmented with vkind; GHilbert definitions without vkind are definitely unsound, by defining   to be  ). CarlWitty 19:50, 20 February 2010 (UTC)


 * Technically, it's not unsound because  is not a variable (see above). It just looks terribly unsound and should therefore not be allowed.--GrafZahl (talk) 11:19, 24 February 2010 (UTC)


 * No, this time I double-checked... it really is unsound. See User:CarlWitty/bad-const-defn.mm for a metamath proof of   (that is, a proof of anything whatsoever) from such a definition. CarlWitty 17:39, 24 February 2010 (UTC)


 * You are right. See User:GrafZahl/unsound-def.gh. Just folding  to   does not work because of the constraint violation. But you can simply instantiate   with   instead of  . D'oh. BTW, Raph added the link  to User:GrafZahl/Definitions in JHilbert, which seems to contain a further idea for safe definitions. I've yet to read it properly, though.--GrafZahl (talk) 10:34, 25 February 2010 (UTC)