Zulip Chat Archive

Stream: lean4

Topic: Idiomatic way to split into cases 0, 1, and 2≤


Markus Schmaus (May 12 2024 at 11:13):

A couple of times now I had n : ℕ and wanted to split my proof into three cases, n = 0, n = 1, and 2 ≤ n. I can get there using multiple by_cases, but I wonder if there is a more idiomatic way to get there. The most recent case also works as an mwe

import Mathlib

theorem Nat.log2_eq_size_pred (n : Nat) : log2 n  = size n - 1 := by
  induction n using Nat.binaryRec with
  | z => rfl
  | f b n ih =>
    unfold log2
    sorry

In this case I want to split into the three cases for bit b n.

Markus Schmaus (May 12 2024 at 11:15):

This mwe uses Mathlib (due to docs#Nat.size), but I would assume that splitting into those three cases could be done without relying on Mathlib.

Henrik Böving (May 12 2024 at 11:19):

You can use the normal programming match in tactics as well to pattern match on some number arbitrarily

Damiano Testa (May 12 2024 at 11:23):

Also, rcases n with _|_|n may get you to the right place (untested).

Markus Schmaus (May 12 2024 at 11:25):

I tried match, and I can split it into three cases, but how to I get the hypothesis 2 ≤ bit b n in the last case?

import Mathlib

theorem Nat.log2_eq_size_pred (n : Nat) : log2 n  = size n - 1 := by
  induction n using Nat.binaryRec with
  | z => rfl
  | f b n ih =>
    unfold log2
    match m : bit b n with
    | 0 => rfl
    | 1 => rfl
    | x =>
      rw [ m]
      sorry

Henrik Böving (May 12 2024 at 11:36):

import Mathlib

theorem Nat.log2_eq_size_pred (n : Nat) : log2 n  = size n - 1 := by
  induction n using Nat.binaryRec with
  | z => rfl
  | f b n ih =>
    unfold log2
    match h : bit b n with
    | 0 => rfl
    | 1 => rfl
    | x + 2 => -- note that we explicitly match on x + 2 here and lean understands that the other cases are not possible
      -- You could explicitly derive it now but we can also just do
      simp
      sorry

Markus Schmaus (May 12 2024 at 12:12):

This is how I completed the proof using match, rcases n with _|_|n works as well.

import Mathlib

namespace Nat

@[simp]
theorem bit_div_two {b : Bool} {n : Nat} : bit b n / 2 = n := by
  cases b <;> simp only [bit_false, bit_true, Nat.bit1_div_two, Nat.bit0_div_two]

@[simp]
theorem bit_true_zero : bit true 0 = 1 := rfl

@[simp]
theorem bit_false_zero : bit false 0 = 0 := rfl

theorem log2_eq_size_pred (n : Nat) : log2 n  = size n - 1 := by
  induction n using Nat.binaryRec with
  | z => rfl
  | f b n ih =>
    unfold log2
    match hm : bit b n with
    | 0 => rfl
    | 1 => rfl
    | x + 2 =>
      simp only [ge_iff_le, le_add_iff_nonneg_left, _root_.zero_le, reduceIte]
      simp only [succ_eq_add_one] at hm
      rw [ hm]
      have : Nat.bit b n  0 := by omega
      simp only [bit_div_two, ih, Nat.size_bit this, succ_eq_add_one, add_tsub_cancel_right]
      match n with
      | 0 =>
        induction b <;> simp at hm
      | m + 1 =>
        apply Nat.sub_add_cancel
        apply Nat.size_le_size (m := 1)
        omega

Eric Wieser (May 12 2024 at 12:33):

Are you looking for docs#Nat.binaryRec' (the primed one)?

Markus Schmaus (May 12 2024 at 15:07):

I see that docs#Nat.binaryRec' allows me to replace the induction b <;> simp at hm line by a simple simp_all, but I don't see how it would have helped me with any of the case distinctions I made.

Yuyang Zhao (May 13 2024 at 04:54):

import Mathlib

theorem Nat.log2_eq_size_pred (n : Nat) : log2 n = size n - 1 := by
  induction n using Nat.binaryRecFromOne with
  | z₀ | z₁ => rfl
  | f b n n0 ih =>
    have : 2  bit b n := by
      rw [bit_val]; omega
    sorry

Last updated: May 02 2025 at 03:31 UTC