Library FlipG: Hofstadter's flipped G tree


Require Import Arith Omega Wf_nat List Program Program.Wf NPeano.
Require Import DeltaList Fib FunG.
Set Implicit Arguments.

See first the file FunG for the study of:
and the associated tree where nodes are labeled breadth-first from left to right.
Now, question by Hofstadter: what if we still label the nodes from right to left, but for the mirror tree ? What is the algebraic definition of the "parent" function for this flipped tree ?
9 10 11 12  13
 \/   |  \ /
  6   7   8
   \   \ /
    4   5
     \ /
      3
      |
      2
      |
      1
References:
  • Hofstadter's book: Goedel, Escher, Bach, page 137.
  • Sequence A123070 on the Online Encyclopedia of Integer Sequences http://oeis.org/A123070


The flip function

If we label the node from right to left, the effect on node numbers is the flip function below. The idea is to map a row [1+fib (k+1);...;fib (k+2)] to the flipped row [fib (k+2);...;1+fib (k+1)] .

Definition flip n :=
  if n <=? 1 then n else S (fib (S (S (S (depth n))))) - n.

Ltac tac_leb := rewrite <- ?Bool.not_true_iff_false, leb_le.

Lemma flip_depth n : depth (flip n) = depth n.

Lemma flip_eqn0 n : depth n 0 →
 flip n = S (fib (S (S (S (depth n))))) - n.

Lemma flip_eqn k n : 1 n fib k
 flip (fib (S k) + n) = S (fib (S (S k))) - n.

Two special cases : leftmost and rightmost node at a given depth

Lemma flip_Sfib k : 1<kflip (S (fib k)) = fib (S k).

Lemma flip_fib k : 1<kflip (fib (S k)) = S (fib k).

flip is involutive (and hence a bijection)

Lemma flip_flip n : flip (flip n) = n.

Lemma flip_eq n m : flip n = flip m n = m.

Lemma flip_swap n m : flip n = m n = flip m.

Lemma flip_low n : n 1 flip n 1.

Lemma flip_high n : 1 < n 1 < flip n.

flip and neighbors

Lemma flip_S n : 1<ndepth (S n) = depth n
  flip (S n) = flip n - 1.

Lemma flip_pred n : 1<ndepth (n-1) = depth n
  flip (n-1) = S (flip n).


The fg function corresponding to the flipped G tree


Definition fg n := flip (g (flip n)).


Lemma fg_depth n : depth (fg n) = depth n - 1.

Lemma fg_fib k : k0 → fg (fib (S k)) = fib k.

Lemma fg_Sfib k : 1<kfg (S (fib (S k))) = S (fib k).

Lemma fg_fib´ k : 1<kfg (fib k) = fib (k-1).

Lemma fg_Sfib´ k : 2<kfg (S (fib k)) = S (fib (k-1)).

Lemma fg_step n : fg (S n) = fg n fg (S n) = S (fg n).
Lemma fg_mono_S n : fg n fg (S n).

Lemma fg_mono n m : nmfg n fg m.

Lemma fg_lipschitz n m : fg m - fg n m - n.

Lemma fg_nonzero n : 0 < n → 0 < fg n.

Lemma fg_0_inv n : fg n = 0 → n = 0.

Lemma fg_nz n : n 0 → fg n 0.

Lemma fg_fix n : fg n = n n 1.

Lemma fg_le n : fg n n.

Lemma fg_lt n : 1<nfg n < n.

Lemma fg_onto a : n, fg n = a.

Lemma fg_nonflat n : fg (S n) = fg nfg (S (S n)) = S (fg n).

Lemma fg_max_two_antecedents n m :
 fg n = fg mn < mm = S n.

Lemma fg_inv n m : fg n = fg mn = m n = S m m = S n.

Lemma fg_eqn n : 3 < nfg n + fg (S (fg (n-1))) = S n.

This equation, along with initial values up to n=3, characterizes fg entirely. It can hence be used to give an algebraic recursive definition to fg, answering the Hofstader's question.

Lemma fg_eqn_unique f :
  f 0 = 0 →
  f 1 = 1 →
  f 2 = 1 →
  f 3 = 2 →
  ( n, 3<nf n + f (S (f (n-1))) = S n) →
   n, f n = fg n.


fg and the shape of its tree

We already know that fg is onto, hence each node has at least a child. Moreover, fg_max_two_antecedents says that we have at most two children per node.
We could even exhibit at least one child for each node

Definition rchild n :=
 if eq_nat_dec n 1 then 2 else n + fg (S n) - 1.
rightmost son, always there

Lemma rightmost_child_carac a n : fg n = a
 (fg (S n) = S a n = rchild a).

Lemma fg_onto_eqn a : fg (rchild a) = a.

Definition lchild n :=
 if eq_nat_dec n 1 then 1 else flip (FunG.rchild (flip n)).
leftmost son, always there (but might be equal to the rightmost son for unary nodes)

Lemma lchild´_alt n : n1 → lchild n = flip (flip n + flip (fg n)).

Lemma fg_onto_eqn´ n : fg (lchild n) = n.

Lemma lchild_leftmost n : fg (lchild n - 1) = n - 1.

Lemma lchild_leftmost´ n a :
  fg n = an = lchild a n = S (lchild a).

Lemma rchild_lchild n :
 rchild n = lchild n rchild n = S (lchild n).

Lemma lchild_rchild n : lchild n rchild n.

Lemma fg_children a n :
  fg n = a → (n = lchild a n = rchild a).

Lemma binary_lchild_is_unary n :
 1<nMultary fg nUnary fg (lchild n).

Lemma rightmost_son_is_binary n :
  1<nMultary fg (rchild n).

Lemma unary_child_is_binary n :
 n 0 → Unary fg nMultary fg (rchild n).

Lemma binary_rchild_is_binary n :
 1<nMultary fg nMultary fg (rchild n).

Hence the shape of the fg tree is a repetition of this pattern:
    r
    |
    p   q
     \ /
      n
where n and q and r are binary nodes and p is unary.
As expected, this is the mirror of the G tree. We hence retrieve the fractal aspect of G, flipped.


Comparison of fg and g

First, a few technical lemmas

Lemma fg_g_S_inv n : 3<n
 fg (S (fg (n-1))) = g (g (n-1)) →
 fg n = S (g n).

Lemma fg_g_eq_inv n : 3<n
 fg (S (fg (n-1))) = S (g (g (n-1))) →
 fg n = g n.

Now, the proof that fg(n) is either g(n) or g(n)+1. This proof is split in many cases according to the shape of the Fibonacci decomposition of n.

Definition IHeq n :=
  m, m<n¬Fib.ThreeOdd 2 mfg m = g m.
Definition IHsucc n :=
  m, m<nFib.ThreeOdd 2 mfg m = S (g m).

Lemma fg_g_aux0 n : IHeq nFib.ThreeOdd 2 nfg n = S (g n).

Lemma fg_g_aux1 n : IHeq n → 3<nFib.Two 2 nfg n = g n.

Lemma fg_g_aux2 n :
 IHeq nIHsucc n → 3<nFib.ThreeEven 2 nfg n = g n.

Lemma fg_g_aux3 n : IHeq nIHsucc n → 3<n
 Fib.High 2 nfg n = g n.

The main result:

Lemma fg_g n :
 (Fib.ThreeOdd 2 nfg n = S (g n))
 (¬Fib.ThreeOdd 2 nfg n = g n).

Note: the positions where fg and g differ start at 7 and then are separated by 5 or 8 (see Fib.ThreeOdd_next and related lemmas). Moreover these positions are always unary nodes in G (see FunG.decomp_unary).
In fact, the g tree can be turned into the fg tree by repeating the following transformation whenever s below is ThreeOdd:
  r   s t             r s   t
   \ /  |             |  \ /
    p   q   becomes   p   q
     \ /               \ /
      n                 n
In the left pattern above, s is ThreeOdd, hence r and p and n are Two, q is ThreeEven and t is High.
Some immediate consequences:

Lemma fg_g_step n : fg n = g n fg n = S (g n).

Lemma g_le_fg n : g n fg n.


fg and "delta" equations

We can characterize fg via its "delta" (a.k.a increments). Let d(n) = fg(n+1)-fg(n). For n>3 :
  • a) if d(n-1) = 0 then d(n) = 1
  • b) if d(n-1) 0 and d(fg(n)) = 0 then d(n) = 1
  • c) if d(n-1) 0 and d(fg(n)) 0 then d(n) = 0
In fact these deltas are always 0 or 1.
FD is a relational presentation of these "delta" equations.

Inductive FD : natnatProp :=
 | FD_0 : FD 0 0
 | FD_1 : FD 1 1
 | FD_2 : FD 2 1
 | FD_3 : FD 3 2
 | FD_4 : FD 4 3
 | FD_a n x : 4<nFD (n-2) xFD (n-1) xFD n (S x)
 | FD_b n x y z : 4<nFD (n-2) xFD (n-1) yxy
                   FD y zFD (S y) zFD n (S y)
 | FD_c n x y z t : 4<nFD (n-2) xFD (n-1) yxy
                     FD y zFD (S y) tz tFD n y.
Hint Constructors FD.

Lemma FD_le n k : FD n kk n.

Lemma FD_nz n k : FD n k → 0<n → 0<k.

Lemma FD_lt n k : FD n k → 1<n → 0<k<n.


Lemma FD_unique n k : FD n kFD n k = .

Lemma FD_step n k : FD n kFD (S n) =k = S k.

fg is an implementation of FD (hence the only one).

Lemma fg_implements_FD n : FD n (fg n).

Lemma fg_unique n k : FD n k k = fg n.

The three situations a) b) c) expressed in terms of fg.

Lemma fg_a n : 0<nfg (n-2) = fg (n-1) → fg n = S (fg (n-1)).

Lemma fg_b n y : 4<n
 y = fg (n-1) →
 fg (n-2) y
 fg (S y) = fg y
 fg n = S y.

Lemma fg_c n y : 4<n
 y = fg (n-1) →
 fg (n-2) y
 fg (S y) fg y
 fg n = y.

An old auxiliary lemma stating the converse of the c) case

Lemma fg_c_inv n :
  2<nfg n = fg (n-1) → fg (S (fg n)) = S (fg (fg n)).

Presentation via a "delta" function

Definition d n := fg (S n) - fg n.

Lemma delta_0_1 n : d n = 0 d n = 1.

Lemma delta_a n : n0 → d (n-1) = 0 → d n = 1.

Lemma delta_b n : 4n
 d (n-1) = 1 → d (fg n) = 0 → d n = 1.

Lemma delta_c n : 4n
 d (n-1) = 1 → d (fg n) = 1 → d n = 0.

Lemma delta_bc n : 4nd (n-1) = 1 → d n = 1 - d (fg n).


Lemma delta_eqn n : 4n
 d n = 1 - d (n-1) × d (fg n).


An alternative equation for fg

Another short equation for fg, but this one cannot be used for defining fg recursively :-(

Lemma fg_alt_eqn n : 3 < nfg (fg n) + fg (n-1) = n.

This last equation f(f(n)) + f(n-1) = n for n > 3 is nice and short, but unfortunately it doesn't define a unique function, even if the first values are fixed to 0 1 1 2. For instance:

Definition oups n :=
 match n with
 | 0 ⇒ 0
 | 1 ⇒ 1
 | 2 ⇒ 1
 | 3 ⇒ 2
 | 4 ⇒ 3
 | 5 ⇒ 3
 | 6 ⇒ 5
 | 7 ⇒ 3
 | _if even n then n-2 else 4
 end.

Lemma oups_def n : 7<noups n = if even n then n-2 else 4.

Lemma oups_alt_eqn n : 3<noups (oups n) + oups (n-1) = n.

We will show below that if we require this equation along with a monotonicity constraint, then there is a unique solution (which is hence fg).
Study of the alternative equation and its consequences.

Definition AltSpec (f:natnat) :=
  (f 0 = 0 f 1 = 1 f 2 = 1 f 3 = 2)
  ( n, 3<nf (f n) + f (n-1) = n).

Lemma alt_spec_fg : AltSpec fg.

Lemma alt_spec_oups : AltSpec oups.

Lemma alt_bound f : AltSpec f n, 1<n → 0 < f n < n.

Lemma alt_bound´ f : AltSpec f n, 0 f n n.

Lemma alt_4 f : AltSpec ff 4 = 3.

Lemma alt_5 f : AltSpec ff 5 = 3.

Alas, f(n) isn't unique for n>5 (e.g 4 or 5 for n=6)

Lemma monotone_equiv f :
 ( n, f n f (S n)) →
 ( n m, n mf n f m).

Lemma alt_mono_bound f : AltSpec f
  ( n, f n f (S n)) →
   n m, n mf m - f n m-n.

Lemma alt_mono_unique f1 f2 :
  AltSpec f1 → ( n, f1 n f1 (S n)) →
  AltSpec f2 → ( n, f2 n f2 (S n)) →
   n, f1 n = f2 n.

Lemma alt_mono_is_fg f :
  AltSpec f → ( n, f n f (S n)) →
   n, f n = fg n.