Problem: house_robber

Your task is to implement the House Robber algorithm and verify its correctness in Lean. Given a list of house values, maximize the total loot without robbing adjacent houses. Postconditions: Result is the value of some valid non-adjacent robbery plan, and no valid plan yields a higher value. Values are non-negative.


import Mathlib

def seq_u64_to_int (xs : List Nat) : List Nat := xs

def is_valid_robbery (houses : List Nat) (len : Nat) : Prop :=
  (∀ i, i < houses.length → houses.getD i 0 < len) ∧
  (∀ i, i < houses.length - 1 → houses.getD (i+1) 0 ≥ houses.getD i 0 + 2)

def total_loot (houses : List Nat) (values : List Nat) : Nat :=
  houses.foldl (fun acc i => acc + values.getD i 0) 0

-- Precondition definition
@[simp, reducible]
def rob_precond (nums : List Nat) : Prop :=
  -- !benchmark @start precond
  nums.length ≤ 100 ∧
  ∀ i, i < nums.length → nums.getD i 0 ≤ 10000
  -- !benchmark @end precond

-- !benchmark @start auxcode
-- !benchmark @end auxcode

-- Main function (dynamic programming solution)
def rob (nums : List Nat) (h_precond : rob_precond nums) : Nat :=
  -- !benchmark @start code
  sorry
  -- !benchmark @end code

-- Postcondition definition
@[simp, reducible]
def rob_postcond (nums : List Nat) (result : Nat) (h_precond : rob_precond nums) : Prop :=
  -- !benchmark @start postcond
  (∀ houses : List Nat,
      is_valid_robbery houses nums.length →
        total_loot houses (seq_u64_to_int nums) ≤ result) ∧
    (∃ houses : List Nat,
        is_valid_robbery houses nums.length ∧
          total_loot houses (seq_u64_to_int nums) = result)
  -- !benchmark @end postcond

-- !benchmark @start lemma
-- !benchmark @end lemma

-- Proof that the implementation satisfies the postcondition
theorem rob_postcond_satisfied (nums : List Nat) (h_precond : rob_precond nums) :
    rob_postcond nums (rob nums h_precond) h_precond := by
  -- !benchmark @start proof
  sorry
  -- !benchmark @end proof