import Mathlib.Data.Nat.Prime.Basic
import Mathlib.Data.Nat.Factorial.Basic
import Mathlib.Tactic.Linarith

LoVe Preface

Proof Assistants

Proof assistants (also called interactive theorem provers)

The basic picture:

A proof assistant is the combination of the language for writing these things, the interface for developing proofs, the algorithm for checking these proofs, and even the logic that defines when a proof is complete.

A selection of proof assistants, classified by logical foundations:

Success Stories

Mathematics:

Computer science:

Lean

Lean is a proof assistant developed primarily by Leonardo de Moura (Microsoft Research) since 2012.

Its mathematical library, mathlib, is developed by a user community.

We are using Lean 4, a recent version. We use its basic libraries, mathlib, and LoVelib. Lean is a research project.

Strengths:

This Course

Web Site

https://BrownCS1951x.github.io

Repository (Demos, Exercises, Homework)

https://github.com/BrownCS1951x/fpv2024

The file you are currently looking at is a demo. For each chapter of the Hitchhiker's Guide, there will be approximately one demo, one exercise sheet, and one homework.

The Hitchhiker's Guide to Logical Verification

https://cs.brown.edu/courses/cs1951x/static_files/main.pdf

The lecture notes consist of a preface and 14 chapters. They cover the same material as the corresponding lectures but with more details. Sometimes there will not be enough time to cover everything in class, so reading the lecture notes will be necessary.

Download this version, not others that you might find online!

Our Goal

We want you to

This course is neither a pure logical foundations course nor a Lean tutorial. Lean is our vehicle, not an end in itself.

open Nat

-- here's a proof that there are infinitely many primes, as a mathematical theorem

theorem infinitude_of_primes : ∀ N, ∃ p ≥ N, Nat.Prime p := by

  intro M

  let F := M ! + 1
  let q := minFac F
  use q

  have qPrime : Nat.Prime q := by
    refine minFac_prime ?_
    have hm : M ! > 0 := by exact factorial_pos M
    linarith

  apply And.intro

  { by_contra hqM
    have h1 : q ∣ M ! + 1 := by exact minFac_dvd F
    have hqM2 : q ≤ M := by exact Nat.le_of_not_ge hqM
    have hqM3 : q ∣ M ! := by exact (Prime.dvd_factorial qPrime).mpr hqM2
    have hq1 : q ∣ 1 := by exact (Nat.dvd_add_iff_right hqM3).mpr h1
    have hqn1 : ¬ q ∣ 1 := by exact Nat.Prime.not_dvd_one qPrime
    contradiction }

  { exact qPrime }
  done



-- but really, this is a proof about a *program* called `biggerPrime`!

def biggerPrime (M : ℕ) : ℕ := Nat.minFac (M ! + 1)

#eval biggerPrime 11

theorem biggerPrime_is_prime : ∀ N, Nat.Prime (biggerPrime N) := by
  intro M
  refine minFac_prime ?_
  have hm : M ! > 0 := by exact factorial_pos M
  linarith
  done

theorem biggerPrime_is_bigger : ∀ N, biggerPrime N ≥ N := by
  intro M
  let F := M ! + 1
  let q := minFac F
  by_contra hqM
  have h1 : q ∣ M ! + 1 := by exact minFac_dvd F
  have hqM2 : q ≤ M := by exact Nat.le_of_not_ge hqM
  have hqM3 : q ∣ M ! := by exact (Prime.dvd_factorial (biggerPrime_is_prime _)).mpr hqM2
  have hq1 : q ∣ 1 := by exact (Nat.dvd_add_iff_right hqM3).mpr h1
  have hqn1 : ¬ q ∣ 1 := by exact Nat.Prime.not_dvd_one (biggerPrime_is_prime _)
  contradiction
  done


-- we can use our verified program to prove our original theorem
theorem infinitude_of_primes2 : ∀ N, ∃ p ≥ N, Nat.Prime p := by
  intro N
  use biggerPrime N
  apply And.intro
  { exact biggerPrime_is_bigger _ }
  { exact biggerPrime_is_prime _ }
  done